From 87be570ee1b4d9e9d143860e512a4bddf4dc7428 Mon Sep 17 00:00:00 2001 From: Stefano Trettel Date: Sat, 20 Feb 2016 08:52:01 +0100 Subject: [PATCH] Initial commit --- .gitignore | 3 + LICENSE | 28 + Makefile | 21 + README.md | 50 + doc/Makefile | 53 + doc/bindings.adoc | 19 + doc/colony.css | 684 +++++++++++ doc/context.adoc | 25 + doc/index.adoc | 17 + doc/index.html | 1526 +++++++++++++++++++++++++ doc/initialization.adoc | 25 + doc/input.adoc | 131 +++ doc/monitor.adoc | 47 + doc/native.adoc | 6 + doc/powered-by-lua.gif | Bin 0 -> 4805 bytes doc/powered-by-lua.png | Bin 0 -> 10815 bytes doc/preface.adoc | 84 ++ doc/window.adoc | 114 ++ examples/callbacks.lua | 29 + examples/hello.lua | 20 + src/Makefile | 101 ++ src/_make | 1 + src/callbacks.c | 370 ++++++ src/context.c | 86 ++ src/cur.c | 100 ++ src/enum.c | 379 ++++++ src/enum.h | 105 ++ src/hint.c | 334 ++++++ src/id.c | 114 ++ src/input.c | 344 ++++++ src/internal.h | 231 ++++ src/main.c | 123 ++ src/mon.c | 100 ++ src/monitor.c | 202 ++++ src/moonglfw.h | 41 + src/structs.h | 89 ++ src/tree.h | 748 ++++++++++++ src/utils.c | 219 ++++ src/win.c | 145 +++ src/window.c | 252 ++++ thirdparty/asciidoctor-styles-license | 55 + thirdparty/openbsd-tree-license | 33 + thirdparty/powered-by-lua-license | 20 + 43 files changed, 7074 insertions(+) create mode 100644 .gitignore create mode 100644 LICENSE create mode 100644 Makefile create mode 100644 README.md create mode 100644 doc/Makefile create mode 100644 doc/bindings.adoc create mode 100644 doc/colony.css create mode 100644 doc/context.adoc create mode 100644 doc/index.adoc create mode 100644 doc/index.html create mode 100644 doc/initialization.adoc create mode 100644 doc/input.adoc create mode 100644 doc/monitor.adoc create mode 100644 doc/native.adoc create mode 100644 doc/powered-by-lua.gif create mode 100644 doc/powered-by-lua.png create mode 100644 doc/preface.adoc create mode 100644 doc/window.adoc create mode 100644 examples/callbacks.lua create mode 100644 examples/hello.lua create mode 100644 src/Makefile create mode 100755 src/_make create mode 100644 src/callbacks.c create mode 100644 src/context.c create mode 100644 src/cur.c create mode 100644 src/enum.c create mode 100644 src/enum.h create mode 100644 src/hint.c create mode 100644 src/id.c create mode 100644 src/input.c create mode 100644 src/internal.h create mode 100644 src/main.c create mode 100644 src/mon.c create mode 100644 src/monitor.c create mode 100644 src/moonglfw.h create mode 100644 src/structs.h create mode 100644 src/tree.h create mode 100644 src/utils.c create mode 100644 src/win.c create mode 100644 src/window.c create mode 100644 thirdparty/asciidoctor-styles-license create mode 100644 thirdparty/openbsd-tree-license create mode 100644 thirdparty/powered-by-lua-license diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..643ec1b --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +*.log +core.* +local/ diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..5e31ebe --- /dev/null +++ b/LICENSE @@ -0,0 +1,28 @@ +The MIT License (MIT) + +Copyright (c) 2016 Stefano Trettel + +Software repository: MoonGLFW, https://github.com/stetre/moonglfw + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +(See also the THIRD-PARTY LICENSES contained in the thirdparty/ directory +of the Software repository.) + diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..940549b --- /dev/null +++ b/Makefile @@ -0,0 +1,21 @@ + +default: build + +check: + @cd src; $(MAKE) -s $@ + +build: + @cd src; $(MAKE) $@ + +install: + @cd src; $(MAKE) $@ + +clean : + @cd src; $(MAKE) $@ + @cd doc; $(MAKE) $@ +# @cd examples; $(MAKE) $@ +# @cd tests; $(MAKE) $@ + +cleanall: clean + +backup: clean diff --git a/README.md b/README.md new file mode 100644 index 0000000..cbead44 --- /dev/null +++ b/README.md @@ -0,0 +1,50 @@ +##MoonGLFW: Lua bindings for GLFW + +MoonGLFW is a Lua binding library for [GLFW](http://www.glfw.org/). + +It runs on GNU/Linux and requires [Lua](http://www.lua.org/) (>=5.3) +and [GLFW](http://www.glfw.org/download.html) (>=3.1). + +_Authored by:_ _[Stefano Trettel](https://www.linkedin.com/in/stetre)_ + +[![Lua logo](./doc/powered-by-lua.gif)](http://www.lua.org/) + +#### License + +MIT/X11 license (same as Lua). See [LICENSE](./LICENSE). + +#### Documentation, Getting and installing, etc. + +See the [Reference Manual](https://stetre.github.io/moonglfw/doc/index.html). + +#### Example + +```lua +-- Script: hello.lua + +glfw = require("moonglfw") + +-- Create a window: +window = glfw.create_window(640, 480, "Hello world!") + +function my_callback(w, x, y) + assert(w == window) + print("cursor position:", x, y) +end + +-- Register a callback to track the cursor's position: +glfw.set_cursor_pos_callback(window, my_callback) + +-- Repeatedly poll for events: +while not glfw.window_should_close(window) do + glfw.poll_events() +end +``` + +The script can be executed at the shell prompt with the standard Lua interpreter: + +```shell +$ lua hello.lua +``` + +Other examples can be found in the **examples/** directory contained in the release package. diff --git a/doc/Makefile b/doc/Makefile new file mode 100644 index 0000000..a622968 --- /dev/null +++ b/doc/Makefile @@ -0,0 +1,53 @@ +TgtAdoc := index +TgtPdf := MoonGLFW-RefMan + +Stylesdir = ./ +Stylesheet = colony.css +Style = -a stylesheet=$(Stylesheet) -a stylesdir=$(Stylesdir) +Style = + +ifdef TgtAdoc +# one file only +Src = $(TgtAdoc).adoc +else +# all .adoc files +Src := $(wildcard *.adoc) +endif + +Xml := $(Src:.adoc=.xml) +Html := $(Src:.adoc=.html) +Pdf := $(Src:.adoc=.pdf) + +default: html + +check: + +clean: + @-rm -f *~ + @-rm -f *.pdf + @-rm -f *.pdfmarks + @-rm -f *.xml + @-rm -f *.html + @-rm -f *.epub + @-rm -f *.fo + @-rm -f *.log + +install: + +html: clean + @asciidoctor $(Style) $(Src) + +preview: html + @google-chrome $(Html) + +ifdef TgtAdoc +# one file only +pdf: clean + @asciidoctor-pdf $(TgtAdoc).adoc -o $(TgtPdf).pdf +else +# all .adoc files +pdf: clean + @asciidoctor-pdf -a pdf-style=asciidoctor $(TgtAdoc).adoc +endif + +docs: html pdf diff --git a/doc/bindings.adoc b/doc/bindings.adoc new file mode 100644 index 0000000..92624d1 --- /dev/null +++ b/doc/bindings.adoc @@ -0,0 +1,19 @@ + +== Bindings + +The structure of this section purposedly replicates the structure of the +http://www.glfw.org/docs/latest/modules.html[GLFW Reference documentation]. + +include::context.adoc[] + +include::initialization.adoc[] + +include::input.adoc[] + +include::monitor.adoc[] + +include::native.adoc[] + +include::window.adoc[] + +<<< diff --git a/doc/colony.css b/doc/colony.css new file mode 100644 index 0000000..30b9765 --- /dev/null +++ b/doc/colony.css @@ -0,0 +1,684 @@ +/*! normalize.css v2.1.2 | MIT License | git.io/normalize */ +/* ========================================================================== HTML5 display definitions ========================================================================== */ +/** Correct `block` display not defined in IE 8/9. */ +article, aside, details, figcaption, figure, footer, header, hgroup, main, nav, section, summary { display: block; } + +/** Correct `inline-block` display not defined in IE 8/9. */ +audio, canvas, video { display: inline-block; } + +/** Prevent modern browsers from displaying `audio` without controls. Remove excess height in iOS 5 devices. */ +audio:not([controls]) { display: none; height: 0; } + +/** Address `[hidden]` styling not present in IE 8/9. Hide the `template` element in IE, Safari, and Firefox < 22. */ +[hidden], template { display: none; } + +script { display: none !important; } + +/* ========================================================================== Base ========================================================================== */ +/** 1. Set default font family to sans-serif. 2. Prevent iOS text size adjust after orientation change, without disabling user zoom. */ +html { font-family: sans-serif; /* 1 */ -ms-text-size-adjust: 100%; /* 2 */ -webkit-text-size-adjust: 100%; /* 2 */ } + +/** Remove default margin. */ +body { margin: 0; } + +/* ========================================================================== Links ========================================================================== */ +/** Remove the gray background color from active links in IE 10. */ +a { background: transparent; } + +/** Address `outline` inconsistency between Chrome and other browsers. */ +a:focus { outline: thin dotted; } + +/** Improve readability when focused and also mouse hovered in all browsers. */ +a:active, a:hover { outline: 0; } + +/* ========================================================================== Typography ========================================================================== */ +/** Address variable `h1` font-size and margin within `section` and `article` contexts in Firefox 4+, Safari 5, and Chrome. */ +h1 { font-size: 2em; margin: 0.67em 0; } + +/** Address styling not present in IE 8/9, Safari 5, and Chrome. */ +abbr[title] { border-bottom: 1px dotted; } + +/** Address style set to `bolder` in Firefox 4+, Safari 5, and Chrome. */ +b, strong { font-weight: bold; } + +/** Address styling not present in Safari 5 and Chrome. */ +dfn { font-style: italic; } + +/** Address differences between Firefox and other browsers. */ +hr { -moz-box-sizing: content-box; box-sizing: content-box; height: 0; } + +/** Address styling not present in IE 8/9. */ +mark { background: #ff0; color: #000; } + +/** Correct font family set oddly in Safari 5 and Chrome. */ +code, kbd, pre, samp { font-family: monospace, serif; font-size: 1em; } + +/** Improve readability of pre-formatted text in all browsers. */ +pre { white-space: pre-wrap; } + +/** Set consistent quote types. */ +q { quotes: "\201C" "\201D" "\2018" "\2019"; } + +/** Address inconsistent and variable font size in all browsers. */ +small { font-size: 80%; } + +/** Prevent `sub` and `sup` affecting `line-height` in all browsers. */ +sub, sup { font-size: 75%; line-height: 0; position: relative; vertical-align: baseline; } + +sup { top: -0.5em; } + +sub { bottom: -0.25em; } + +/* ========================================================================== Embedded content ========================================================================== */ +/** Remove border when inside `a` element in IE 8/9. */ +img { border: 0; } + +/** Correct overflow displayed oddly in IE 9. */ +svg:not(:root) { overflow: hidden; } + +/* ========================================================================== Figures ========================================================================== */ +/** Address margin not present in IE 8/9 and Safari 5. */ +figure { margin: 0; } + +/* ========================================================================== Forms ========================================================================== */ +/** Define consistent border, margin, and padding. */ +fieldset { border: 1px solid #c0c0c0; margin: 0 2px; padding: 0.35em 0.625em 0.75em; } + +/** 1. Correct `color` not being inherited in IE 8/9. 2. Remove padding so people aren't caught out if they zero out fieldsets. */ +legend { border: 0; /* 1 */ padding: 0; /* 2 */ } + +/** 1. Correct font family not being inherited in all browsers. 2. Correct font size not being inherited in all browsers. 3. Address margins set differently in Firefox 4+, Safari 5, and Chrome. */ +button, input, select, textarea { font-family: inherit; /* 1 */ font-size: 100%; /* 2 */ margin: 0; /* 3 */ } + +/** Address Firefox 4+ setting `line-height` on `input` using `!important` in the UA stylesheet. */ +button, input { line-height: normal; } + +/** Address inconsistent `text-transform` inheritance for `button` and `select`. All other form control elements do not inherit `text-transform` values. Correct `button` style inheritance in Chrome, Safari 5+, and IE 8+. Correct `select` style inheritance in Firefox 4+ and Opera. */ +button, select { text-transform: none; } + +/** 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio` and `video` controls. 2. Correct inability to style clickable `input` types in iOS. 3. Improve usability and consistency of cursor style between image-type `input` and others. */ +button, html input[type="button"], input[type="reset"], input[type="submit"] { -webkit-appearance: button; /* 2 */ cursor: pointer; /* 3 */ } + +/** Re-set default cursor for disabled elements. */ +button[disabled], html input[disabled] { cursor: default; } + +/** 1. Address box sizing set to `content-box` in IE 8/9. 2. Remove excess padding in IE 8/9. */ +input[type="checkbox"], input[type="radio"] { box-sizing: border-box; /* 1 */ padding: 0; /* 2 */ } + +/** 1. Address `appearance` set to `searchfield` in Safari 5 and Chrome. 2. Address `box-sizing` set to `border-box` in Safari 5 and Chrome (include `-moz` to future-proof). */ +input[type="search"] { -webkit-appearance: textfield; /* 1 */ -moz-box-sizing: content-box; -webkit-box-sizing: content-box; /* 2 */ box-sizing: content-box; } + +/** Remove inner padding and search cancel button in Safari 5 and Chrome on OS X. */ +input[type="search"]::-webkit-search-cancel-button, input[type="search"]::-webkit-search-decoration { -webkit-appearance: none; } + +/** Remove inner padding and border in Firefox 4+. */ +button::-moz-focus-inner, input::-moz-focus-inner { border: 0; padding: 0; } + +/** 1. Remove default vertical scrollbar in IE 8/9. 2. Improve readability and alignment in all browsers. */ +textarea { overflow: auto; /* 1 */ vertical-align: top; /* 2 */ } + +/* ========================================================================== Tables ========================================================================== */ +/** Remove most spacing between table cells. */ +table { border-collapse: collapse; border-spacing: 0; } + +meta.foundation-mq-small { font-family: "only screen and (min-width: 768px)"; width: 768px; } + +meta.foundation-mq-medium { font-family: "only screen and (min-width:1280px)"; width: 1280px; } + +meta.foundation-mq-large { font-family: "only screen and (min-width:1440px)"; width: 1440px; } + +*, *:before, *:after { -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; } + +html, body { font-size: 100%; } + +body { background: white; color: #222222; padding: 0; margin: 0; font-family: "Helvetica Neue", "Helvetica", Helvetica, Arial, sans-serif; font-weight: normal; font-style: normal; line-height: 1; position: relative; cursor: auto; } + +a:hover { cursor: pointer; } + +img, object, embed { max-width: 100%; height: auto; } + +object, embed { height: 100%; } + +img { -ms-interpolation-mode: bicubic; } + +#map_canvas img, #map_canvas embed, #map_canvas object, .map_canvas img, .map_canvas embed, .map_canvas object { max-width: none !important; } + +.left { float: left !important; } + +.right { float: right !important; } + +.text-left { text-align: left !important; } + +.text-right { text-align: right !important; } + +.text-center { text-align: center !important; } + +.text-justify { text-align: justify !important; } + +.hide { display: none; } + +.antialiased, body { -webkit-font-smoothing: antialiased; } + +img { display: inline-block; vertical-align: middle; } + +textarea { height: auto; min-height: 50px; } + +select { width: 100%; } + +p.lead, .paragraph.lead > p, #preamble > .sectionbody > .paragraph:first-of-type p { font-size: 1.21875em; line-height: 1.6; } + +.subheader, .admonitionblock td.content > .title, .audioblock > .title, .exampleblock > .title, .imageblock > .title, .listingblock > .title, .literalblock > .title, .stemblock > .title, .openblock > .title, .paragraph > .title, .quoteblock > .title, table.tableblock > .title, .verseblock > .title, .videoblock > .title, .dlist > .title, .olist > .title, .ulist > .title, .qlist > .title, .hdlist > .title { line-height: 1.4; color: #003b6b; font-weight: 300; margin-top: 0.2em; margin-bottom: 0.5em; } + +/* Typography resets */ +div, dl, dt, dd, ul, ol, li, h1, h2, h3, #toctitle, .sidebarblock > .content > .title, h4, h5, h6, pre, form, p, blockquote, th, td { margin: 0; padding: 0; direction: ltr; } + +/* Default Link Styles */ +a { color: #00579e; text-decoration: none; line-height: inherit; } +a:hover, a:focus { color: #333333; } +a img { border: none; } + +/* Default paragraph styles */ +p { font-family: Arial, sans-serif; font-weight: normal; font-size: 1em; line-height: 1.6; margin-bottom: 0.75em; text-rendering: optimizeLegibility; } +p aside { font-size: 0.875em; line-height: 1.35; font-style: italic; } + +/* Default header styles */ +h1, h2, h3, #toctitle, .sidebarblock > .content > .title, h4, h5, h6 { font-family: Arial, sans-serif; font-weight: normal; font-style: normal; color: #7b2d00; text-rendering: optimizeLegibility; margin-top: 0.5em; margin-bottom: 0.5em; line-height: 1.2125em; } +h1 small, h2 small, h3 small, #toctitle small, .sidebarblock > .content > .title small, h4 small, h5 small, h6 small { font-size: 60%; color: #ff6b15; line-height: 0; } + +h1 { font-size: 2.125em; } + +h2 { font-size: 1.6875em; } + +h3, #toctitle, .sidebarblock > .content > .title { font-size: 1.375em; } + +h4 { font-size: 1.125em; } + +h5 { font-size: 1.125em; } + +h6 { font-size: 1em; } + +hr { border: solid #dddddd; border-width: 1px 0 0; clear: both; margin: 1.25em 0 1.1875em; height: 0; } + +/* Helpful Typography Defaults */ +em, i { font-style: italic; line-height: inherit; } + +strong, b { font-weight: bold; line-height: inherit; } + +small { font-size: 60%; line-height: inherit; } + +code { font-family: Consolas, "Liberation Mono", Courier, monospace; font-weight: bold; color: #003426; } + +/* Lists */ +ul, ol, dl { font-size: 1em; line-height: 1.6; margin-bottom: 0.75em; list-style-position: outside; font-family: Arial, sans-serif; } + +ul, ol { margin-left: 1.5em; } +ul.no-bullet, ol.no-bullet { margin-left: 1.5em; } + +/* Unordered Lists */ +ul li ul, ul li ol { margin-left: 1.25em; margin-bottom: 0; font-size: 1em; /* Override nested font-size change */ } +ul.square li ul, ul.circle li ul, ul.disc li ul { list-style: inherit; } +ul.square { list-style-type: square; } +ul.circle { list-style-type: circle; } +ul.disc { list-style-type: disc; } +ul.no-bullet { list-style: none; } + +/* Ordered Lists */ +ol li ul, ol li ol { margin-left: 1.25em; margin-bottom: 0; } + +/* Definition Lists */ +dl dt { margin-bottom: 0.3em; font-weight: bold; } +dl dd { margin-bottom: 0.75em; } + +/* Abbreviations */ +abbr, acronym { text-transform: uppercase; font-size: 90%; color: black; border-bottom: 1px dotted #dddddd; cursor: help; } + +abbr { text-transform: none; } + +/* Blockquotes */ +blockquote { margin: 0 0 0.75em; padding: 0.5625em 1.25em 0 1.1875em; border-left: 1px solid #dddddd; } +blockquote cite { display: block; font-size: 0.8125em; color: #e15200; } +blockquote cite:before { content: "\2014 \0020"; } +blockquote cite a, blockquote cite a:visited { color: #e15200; } + +blockquote, blockquote p { line-height: 1.6; color: #333333; } + +/* Microformats */ +.vcard { display: inline-block; margin: 0 0 1.25em 0; border: 1px solid #dddddd; padding: 0.625em 0.75em; } +.vcard li { margin: 0; display: block; } +.vcard .fn { font-weight: bold; font-size: 0.9375em; } + +.vevent .summary { font-weight: bold; } +.vevent abbr { cursor: auto; text-decoration: none; font-weight: bold; border: none; padding: 0 0.0625em; } + +@media only screen and (min-width: 768px) { h1, h2, h3, #toctitle, .sidebarblock > .content > .title, h4, h5, h6 { line-height: 1.4; } + h1 { font-size: 2.75em; } + h2 { font-size: 2.3125em; } + h3, #toctitle, .sidebarblock > .content > .title { font-size: 1.6875em; } + h4 { font-size: 1.4375em; } } +/* Tables */ +table { background: white; margin-bottom: 1.25em; border: solid 1px #d8d8ce; } +table thead, table tfoot { background: -webkit-linear-gradient(top, #add386, #90b66a); font-weight: bold; } +table thead tr th, table thead tr td, table tfoot tr th, table tfoot tr td { padding: 0.5em 0.625em 0.625em; font-size: inherit; color: white; text-align: left; } +table tr th, table tr td { padding: 0.5625em 0.625em; font-size: inherit; color: #6d6e71; } +table tr.even, table tr.alt, table tr:nth-of-type(even) { background: #edf2f2; } +table thead tr th, table tfoot tr th, table tbody tr td, table tr td, table tfoot tr td { display: table-cell; line-height: 1.4; } + +h1, h2, h3, #toctitle, .sidebarblock > .content > .title, h4, h5, h6 { line-height: 1.4; } + +a:hover, a:focus { text-decoration: underline; } + +.clearfix:before, .clearfix:after, .float-group:before, .float-group:after { content: " "; display: table; } +.clearfix:after, .float-group:after { clear: both; } + +*:not(pre) > code { font-size: inherit; font-style: normal !important; letter-spacing: 0; padding: 3px 2px 1px 2px; background-color: #eeeeee; border: 1px solid #dddddd; -webkit-border-radius: 0; border-radius: 0; line-height: inherit; } + +pre, pre > code { line-height: 1.6; color: black; font-family: Consolas, "Liberation Mono", Courier, monospace; font-weight: normal; } + +.keyseq { color: #333333; } + +kbd { display: inline-block; color: black; font-size: 0.75em; line-height: 1.4; background-color: #f7f7f7; border: 1px solid #ccc; -webkit-border-radius: 3px; border-radius: 3px; -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.2), 0 0 0 0.1em white inset; box-shadow: 0 1px 0 rgba(0, 0, 0, 0.2), 0 0 0 0.1em white inset; margin: -0.15em 0.15em 0 0.15em; padding: 0.2em 0.6em 0.2em 0.5em; vertical-align: middle; white-space: nowrap; } + +.keyseq kbd:first-child { margin-left: 0; } + +.keyseq kbd:last-child { margin-right: 0; } + +.menuseq, .menu { color: black; } + +b.button:before, b.button:after { position: relative; top: -1px; font-weight: normal; } + +b.button:before { content: "["; padding: 0 3px 0 2px; } + +b.button:after { content: "]"; padding: 0 2px 0 3px; } + +#header, #content, #footnotes, #footer { width: 100%; margin-left: auto; margin-right: auto; margin-top: 0; margin-bottom: 0; max-width: 62.5em; *zoom: 1; position: relative; padding-left: 1.5em; padding-right: 1.5em; } +#header:before, #header:after, #content:before, #content:after, #footnotes:before, #footnotes:after, #footer:before, #footer:after { content: " "; display: table; } +#header:after, #content:after, #footnotes:after, #footer:after { clear: both; } + +#content { margin-top: 1.25em; } + +#content:before { content: none; } + +#header > h1:first-child { color: #7b2d00; margin-top: 2.25rem; margin-bottom: 0; } +#header > h1:first-child + #toc { margin-top: 8px; border-top: 1px solid #dddddd; } +#header > h1:only-child, body.toc2 #header > h1:nth-last-child(2) { border-bottom: 1px solid #dddddd; padding-bottom: 8px; } +#header .details { border-bottom: 1px solid #dddddd; line-height: 1.45; padding-top: 0.25em; padding-bottom: 0.25em; padding-left: 0.25em; color: #e15200; display: -ms-flexbox; display: -webkit-flex; display: flex; -ms-flex-flow: row wrap; -webkit-flex-flow: row wrap; flex-flow: row wrap; } +#header .details span:first-child { margin-left: -0.125em; } +#header .details span.email a { color: #333333; } +#header .details br { display: none; } +#header .details br + span:before { content: "\00a0\2013\00a0"; } +#header .details br + span.author:before { content: "\00a0\22c5\00a0"; color: #333333; } +#header .details br + span#revremark:before { content: "\00a0|\00a0"; } +#header #revnumber { text-transform: capitalize; } +#header #revnumber:after { content: "\00a0"; } + +#content > h1:first-child:not([class]) { color: #7b2d00; border-bottom: 1px solid #dddddd; padding-bottom: 8px; margin-top: 0; padding-top: 1rem; margin-bottom: 1.25rem; } + +#toc { border-bottom: 0 solid #dddddd; padding-bottom: 0.5em; } +#toc > ul { margin-left: 0.125em; } +#toc ul.sectlevel0 > li > a { font-style: italic; } +#toc ul.sectlevel0 ul.sectlevel1 { margin: 0.5em 0; } +#toc ul { font-family: Arial, sans-serif; list-style-type: none; } +#toc a { text-decoration: none; } +#toc a:active { text-decoration: underline; } + +#toctitle { color: #003b6b; font-size: 1.2em; } + +@media only screen and (min-width: 768px) { #toctitle { font-size: 1.375em; } + body.toc2 { padding-left: 15em; padding-right: 0; } + #toc.toc2 { margin-top: 0 !important; background-color: white; position: fixed; width: 15em; left: 0; top: 0; border-right: 1px solid #dddddd; border-top-width: 0 !important; border-bottom-width: 0 !important; z-index: 1000; padding: 1.25em 1em; height: 100%; overflow: auto; } + #toc.toc2 #toctitle { margin-top: 0; font-size: 1.2em; } + #toc.toc2 > ul { font-size: 0.9em; margin-bottom: 0; } + #toc.toc2 ul ul { margin-left: 0; padding-left: 1em; } + #toc.toc2 ul.sectlevel0 ul.sectlevel1 { padding-left: 0; margin-top: 0.5em; margin-bottom: 0.5em; } + body.toc2.toc-right { padding-left: 0; padding-right: 15em; } + body.toc2.toc-right #toc.toc2 { border-right-width: 0; border-left: 1px solid #dddddd; left: auto; right: 0; } } +@media only screen and (min-width: 1280px) { body.toc2 { padding-left: 20em; padding-right: 0; } + #toc.toc2 { width: 20em; } + #toc.toc2 #toctitle { font-size: 1.375em; } + #toc.toc2 > ul { font-size: 0.95em; } + #toc.toc2 ul ul { padding-left: 1.25em; } + body.toc2.toc-right { padding-left: 0; padding-right: 20em; } } +#content #toc { border-style: solid; border-width: 1px; border-color: #e6e6e6; margin-bottom: 1.25em; padding: 1.25em; background: white; -webkit-border-radius: 0; border-radius: 0; } +#content #toc > :first-child { margin-top: 0; } +#content #toc > :last-child { margin-bottom: 0; } + +#footer { max-width: 100%; background-color: none; padding: 1.25em; } + +#footer-text { color: black; line-height: 1.44; } + +.sect1 { padding-bottom: 0.625em; } + +@media only screen and (min-width: 768px) { .sect1 { padding-bottom: 1.25em; } } +.sect1 + .sect1 { border-top: 0 solid #dddddd; } + +#content h1 > a.anchor, h2 > a.anchor, h3 > a.anchor, #toctitle > a.anchor, .sidebarblock > .content > .title > a.anchor, h4 > a.anchor, h5 > a.anchor, h6 > a.anchor { position: absolute; z-index: 1001; width: 1.5ex; margin-left: -1.5ex; display: block; text-decoration: none !important; visibility: hidden; text-align: center; font-weight: normal; } +#content h1 > a.anchor:before, h2 > a.anchor:before, h3 > a.anchor:before, #toctitle > a.anchor:before, .sidebarblock > .content > .title > a.anchor:before, h4 > a.anchor:before, h5 > a.anchor:before, h6 > a.anchor:before { content: "\00A7"; font-size: 0.85em; display: block; padding-top: 0.1em; } +#content h1:hover > a.anchor, #content h1 > a.anchor:hover, h2:hover > a.anchor, h2 > a.anchor:hover, h3:hover > a.anchor, #toctitle:hover > a.anchor, .sidebarblock > .content > .title:hover > a.anchor, h3 > a.anchor:hover, #toctitle > a.anchor:hover, .sidebarblock > .content > .title > a.anchor:hover, h4:hover > a.anchor, h4 > a.anchor:hover, h5:hover > a.anchor, h5 > a.anchor:hover, h6:hover > a.anchor, h6 > a.anchor:hover { visibility: visible; } +#content h1 > a.link, h2 > a.link, h3 > a.link, #toctitle > a.link, .sidebarblock > .content > .title > a.link, h4 > a.link, h5 > a.link, h6 > a.link { color: #7b2d00; text-decoration: none; } +#content h1 > a.link:hover, h2 > a.link:hover, h3 > a.link:hover, #toctitle > a.link:hover, .sidebarblock > .content > .title > a.link:hover, h4 > a.link:hover, h5 > a.link:hover, h6 > a.link:hover { color: #622400; } + +.audioblock, .imageblock, .literalblock, .listingblock, .stemblock, .videoblock { margin-bottom: 1.25em; } + +.admonitionblock td.content > .title, .audioblock > .title, .exampleblock > .title, .imageblock > .title, .listingblock > .title, .literalblock > .title, .stemblock > .title, .openblock > .title, .paragraph > .title, .quoteblock > .title, table.tableblock > .title, .verseblock > .title, .videoblock > .title, .dlist > .title, .olist > .title, .ulist > .title, .qlist > .title, .hdlist > .title { text-rendering: optimizeLegibility; text-align: left; } + +table.tableblock > caption.title { white-space: nowrap; overflow: visible; max-width: 0; } + +.paragraph.lead > p, #preamble > .sectionbody > .paragraph:first-of-type p { color: #7b2d00; } + +table.tableblock #preamble > .sectionbody > .paragraph:first-of-type p { font-size: inherit; } + +.admonitionblock > table { border-collapse: separate; border: 0; background: none; width: 100%; } +.admonitionblock > table td.icon { text-align: center; width: 80px; } +.admonitionblock > table td.icon img { max-width: none; } +.admonitionblock > table td.icon .title { font-weight: bold; font-family: Arial, sans-serif; text-transform: uppercase; } +.admonitionblock > table td.content { padding-left: 1.125em; padding-right: 1.25em; border-left: 1px solid #dddddd; color: #e15200; } +.admonitionblock > table td.content > :last-child > :last-child { margin-bottom: 0; } + +.exampleblock > .content { border-style: solid; border-width: 1px; border-color: #e6e6e6; margin-bottom: 1.25em; padding: 1.25em; background: white; -webkit-border-radius: 0; border-radius: 0; } +.exampleblock > .content > :first-child { margin-top: 0; } +.exampleblock > .content > :last-child { margin-bottom: 0; } + +.sidebarblock { border-style: solid; border-width: 1px; border-color: #e6e6e6; margin-bottom: 1.25em; padding: 1.25em; background: white; -webkit-border-radius: 0; border-radius: 0; } +.sidebarblock > :first-child { margin-top: 0; } +.sidebarblock > :last-child { margin-bottom: 0; } +.sidebarblock > .content > .title { color: #003b6b; margin-top: 0; } + +.exampleblock > .content > :last-child > :last-child, .exampleblock > .content .olist > ol > li:last-child > :last-child, .exampleblock > .content .ulist > ul > li:last-child > :last-child, .exampleblock > .content .qlist > ol > li:last-child > :last-child, .sidebarblock > .content > :last-child > :last-child, .sidebarblock > .content .olist > ol > li:last-child > :last-child, .sidebarblock > .content .ulist > ul > li:last-child > :last-child, .sidebarblock > .content .qlist > ol > li:last-child > :last-child { margin-bottom: 0; } + +.literalblock pre, .listingblock pre:not(.highlight), .listingblock pre[class="highlight"], .listingblock pre[class^="highlight "], .listingblock pre.CodeRay, .listingblock pre.prettyprint { background: #eeeeee; } +.sidebarblock .literalblock pre, .sidebarblock .listingblock pre:not(.highlight), .sidebarblock .listingblock pre[class="highlight"], .sidebarblock .listingblock pre[class^="highlight "], .sidebarblock .listingblock pre.CodeRay, .sidebarblock .listingblock pre.prettyprint { background: #f2f1f1; } + +.literalblock pre, .literalblock pre[class], .listingblock pre, .listingblock pre[class] { border: 1px dashed #666666; -webkit-border-radius: 0; border-radius: 0; word-wrap: break-word; padding: 1.25em 1.5625em 1.125em 1.5625em; font-size: 0.8125em; } +.literalblock pre.nowrap, .literalblock pre[class].nowrap, .listingblock pre.nowrap, .listingblock pre[class].nowrap { overflow-x: auto; white-space: pre; word-wrap: normal; } +@media only screen and (min-width: 768px) { .literalblock pre, .literalblock pre[class], .listingblock pre, .listingblock pre[class] { font-size: 0.90625em; } } +@media only screen and (min-width: 1280px) { .literalblock pre, .literalblock pre[class], .listingblock pre, .listingblock pre[class] { font-size: 1em; } } + +.literalblock.output pre { color: #eeeeee; background-color: black; } + +.listingblock pre.highlightjs { padding: 0; } +.listingblock pre.highlightjs > code { padding: 1.25em 1.5625em 1.125em 1.5625em; -webkit-border-radius: 0; border-radius: 0; } + +.listingblock > .content { position: relative; } + +.listingblock code[data-lang]:before { display: none; content: attr(data-lang); position: absolute; font-size: 0.75em; top: 0.425rem; right: 0.5rem; line-height: 1; text-transform: uppercase; color: #999; } + +.listingblock:hover code[data-lang]:before { display: block; } + +.listingblock.terminal pre .command:before { content: attr(data-prompt); padding-right: 0.5em; color: #999; } + +.listingblock.terminal pre .command:not([data-prompt]):before { content: "$"; } + +table.pyhltable { border-collapse: separate; border: 0; margin-bottom: 0; background: none; } + +table.pyhltable td { vertical-align: top; padding-top: 0; padding-bottom: 0; } + +table.pyhltable td.code { padding-left: .75em; padding-right: 0; } + +pre.pygments .lineno, table.pyhltable td:not(.code) { color: #999; padding-left: 0; padding-right: .5em; border-right: 1px solid #dddddd; } + +pre.pygments .lineno { display: inline-block; margin-right: .25em; } + +table.pyhltable .linenodiv { background: none !important; padding-right: 0 !important; } + +.quoteblock { margin: 0 1em 0.75em 1.5em; display: table; } +.quoteblock > .title { margin-left: -1.5em; margin-bottom: 0.75em; } +.quoteblock blockquote, .quoteblock blockquote p { color: #333333; font-size: 1.15rem; line-height: 1.75; word-spacing: 0.1em; letter-spacing: 0; font-style: italic; text-align: justify; } +.quoteblock blockquote { margin: 0; padding: 0; border: 0; } +.quoteblock blockquote:before { content: "\201c"; float: left; font-size: 2.75em; font-weight: bold; line-height: 0.6em; margin-left: -0.6em; color: #003b6b; text-shadow: 0 1px 2px rgba(0, 0, 0, 0.1); } +.quoteblock blockquote > .paragraph:last-child p { margin-bottom: 0; } +.quoteblock .attribution { margin-top: 0.5em; margin-right: 0.5ex; text-align: right; } +.quoteblock .quoteblock { margin-left: 0; margin-right: 0; padding: 0.5em 0; border-left: 3px solid #e15200; } +.quoteblock .quoteblock blockquote { padding: 0 0 0 0.75em; } +.quoteblock .quoteblock blockquote:before { display: none; } + +.verseblock { margin: 0 1em 0.75em 1em; } +.verseblock pre { font-family: "Open Sans", "DejaVu Sans", sans; font-size: 1.15rem; color: #333333; font-weight: 300; text-rendering: optimizeLegibility; } +.verseblock pre strong { font-weight: 400; } +.verseblock .attribution { margin-top: 1.25rem; margin-left: 0.5ex; } + +.quoteblock .attribution, .verseblock .attribution { font-size: 0.8125em; line-height: 1.45; font-style: italic; } +.quoteblock .attribution br, .verseblock .attribution br { display: none; } +.quoteblock .attribution cite, .verseblock .attribution cite { display: block; letter-spacing: -0.05em; color: #e15200; } + +.quoteblock.abstract { margin: 0 0 0.75em 0; display: block; } +.quoteblock.abstract blockquote, .quoteblock.abstract blockquote p { text-align: left; word-spacing: 0; } +.quoteblock.abstract blockquote:before, .quoteblock.abstract blockquote p:first-of-type:before { display: none; } + +table.tableblock { max-width: 100%; border-collapse: separate; } +table.tableblock td > .paragraph:last-child p > p:last-child, table.tableblock th > p:last-child, table.tableblock td > p:last-child { margin-bottom: 0; } + +table.spread { width: 100%; } + +table.tableblock, th.tableblock, td.tableblock { border: 0 solid #d8d8ce; } + +table.grid-all th.tableblock, table.grid-all td.tableblock { border-width: 0 1px 1px 0; } + +table.grid-all tfoot > tr > th.tableblock, table.grid-all tfoot > tr > td.tableblock { border-width: 1px 1px 0 0; } + +table.grid-cols th.tableblock, table.grid-cols td.tableblock { border-width: 0 1px 0 0; } + +table.grid-all * > tr > .tableblock:last-child, table.grid-cols * > tr > .tableblock:last-child { border-right-width: 0; } + +table.grid-rows th.tableblock, table.grid-rows td.tableblock { border-width: 0 0 1px 0; } + +table.grid-all tbody > tr:last-child > th.tableblock, table.grid-all tbody > tr:last-child > td.tableblock, table.grid-all thead:last-child > tr > th.tableblock, table.grid-rows tbody > tr:last-child > th.tableblock, table.grid-rows tbody > tr:last-child > td.tableblock, table.grid-rows thead:last-child > tr > th.tableblock { border-bottom-width: 0; } + +table.grid-rows tfoot > tr > th.tableblock, table.grid-rows tfoot > tr > td.tableblock { border-width: 1px 0 0 0; } + +table.frame-all { border-width: 1px; } + +table.frame-sides { border-width: 0 1px; } + +table.frame-topbot { border-width: 1px 0; } + +th.halign-left, td.halign-left { text-align: left; } + +th.halign-right, td.halign-right { text-align: right; } + +th.halign-center, td.halign-center { text-align: center; } + +th.valign-top, td.valign-top { vertical-align: top; } + +th.valign-bottom, td.valign-bottom { vertical-align: bottom; } + +th.valign-middle, td.valign-middle { vertical-align: middle; } + +table thead th, table tfoot th { font-weight: bold; } + +tbody tr th { display: table-cell; line-height: 1.4; background: -webkit-linear-gradient(top, #add386, #90b66a); } + +tbody tr th, tbody tr th p, tfoot tr th, tfoot tr th p { color: white; font-weight: bold; } + +p.tableblock > code:only-child { background: none; padding: 0; } + +p.tableblock { font-size: 1em; } + +td > div.verse { white-space: pre; } + +ol { margin-left: 1.75em; } + +ul li ol { margin-left: 1.5em; } + +dl dd { margin-left: 1.125em; } + +dl dd:last-child, dl dd:last-child > :last-child { margin-bottom: 0; } + +ol > li p, ul > li p, ul dd, ol dd, .olist .olist, .ulist .ulist, .ulist .olist, .olist .ulist { margin-bottom: 0.375em; } + +ul.unstyled, ol.unnumbered, ul.checklist, ul.none { list-style-type: none; } + +ul.unstyled, ol.unnumbered, ul.checklist { margin-left: 0.625em; } + +ul.checklist li > p:first-child > .fa-square-o:first-child, ul.checklist li > p:first-child > .fa-check-square-o:first-child { width: 1em; font-size: 0.85em; } + +ul.checklist li > p:first-child > input[type="checkbox"]:first-child { width: 1em; position: relative; top: 1px; } + +ul.inline { margin: 0 auto 0.375em auto; margin-left: -1.375em; margin-right: 0; padding: 0; list-style: none; overflow: hidden; } +ul.inline > li { list-style: none; float: left; margin-left: 1.375em; display: block; } +ul.inline > li > * { display: block; } + +.unstyled dl dt { font-weight: normal; font-style: normal; } + +ol.arabic { list-style-type: decimal; } + +ol.decimal { list-style-type: decimal-leading-zero; } + +ol.loweralpha { list-style-type: lower-alpha; } + +ol.upperalpha { list-style-type: upper-alpha; } + +ol.lowerroman { list-style-type: lower-roman; } + +ol.upperroman { list-style-type: upper-roman; } + +ol.lowergreek { list-style-type: lower-greek; } + +.hdlist > table, .colist > table { border: 0; background: none; } +.hdlist > table > tbody > tr, .colist > table > tbody > tr { background: none; } + +td.hdlist1 { padding-right: .75em; font-weight: bold; } + +td.hdlist1, td.hdlist2 { vertical-align: top; } + +.literalblock + .colist, .listingblock + .colist { margin-top: -0.5em; } + +.colist > table tr > td:first-of-type { padding: 0 0.75em; line-height: 1; } +.colist > table tr > td:last-of-type { padding: 0.25em 0; } + +.thumb, .th { line-height: 0; display: inline-block; border: solid 4px white; -webkit-box-shadow: 0 0 0 1px #dddddd; box-shadow: 0 0 0 1px #dddddd; } + +.imageblock.left, .imageblock[style*="float: left"] { margin: 0.25em 0.625em 1.25em 0; } +.imageblock.right, .imageblock[style*="float: right"] { margin: 0.25em 0 1.25em 0.625em; } +.imageblock > .title { margin-bottom: 0; } +.imageblock.thumb, .imageblock.th { border-width: 6px; } +.imageblock.thumb > .title, .imageblock.th > .title { padding: 0 0.125em; } + +.image.left, .image.right { margin-top: 0.25em; margin-bottom: 0.25em; display: inline-block; line-height: 0; } +.image.left { margin-right: 0.625em; } +.image.right { margin-left: 0.625em; } + +a.image { text-decoration: none; } + +span.footnote, span.footnoteref { vertical-align: super; font-size: 0.875em; } +span.footnote a, span.footnoteref a { text-decoration: none; } +span.footnote a:active, span.footnoteref a:active { text-decoration: underline; } + +#footnotes { padding-top: 0.75em; padding-bottom: 0.75em; margin-bottom: 0.625em; } +#footnotes hr { width: 20%; min-width: 6.25em; margin: -.25em 0 .75em 0; border-width: 1px 0 0 0; } +#footnotes .footnote { padding: 0 0.375em; line-height: 1.3; font-size: 0.875em; margin-left: 1.2em; text-indent: -1.2em; margin-bottom: .2em; } +#footnotes .footnote a:first-of-type { font-weight: bold; text-decoration: none; } +#footnotes .footnote:last-of-type { margin-bottom: 0; } + +#content #footnotes { margin-top: -0.625em; margin-bottom: 0; padding: 0.75em 0; } + +.gist .file-data > table { border: 0; background: #fff; width: 100%; margin-bottom: 0; } +.gist .file-data > table td.line-data { width: 99%; } + +div.unbreakable { page-break-inside: avoid; } + +.big { font-size: larger; } + +.small { font-size: smaller; } + +.underline { text-decoration: underline; } + +.overline { text-decoration: overline; } + +.line-through { text-decoration: line-through; } + +.aqua { color: #00bfbf; } + +.aqua-background { background-color: #00fafa; } + +.black { color: black; } + +.black-background { background-color: black; } + +.blue { color: #0000bf; } + +.blue-background { background-color: #0000fa; } + +.fuchsia { color: #bf00bf; } + +.fuchsia-background { background-color: #fa00fa; } + +.gray { color: #606060; } + +.gray-background { background-color: #7d7d7d; } + +.green { color: #006000; } + +.green-background { background-color: #007d00; } + +.lime { color: #00bf00; } + +.lime-background { background-color: #00fa00; } + +.maroon { color: #600000; } + +.maroon-background { background-color: #7d0000; } + +.navy { color: #000060; } + +.navy-background { background-color: #00007d; } + +.olive { color: #606000; } + +.olive-background { background-color: #7d7d00; } + +.purple { color: #600060; } + +.purple-background { background-color: #7d007d; } + +.red { color: #bf0000; } + +.red-background { background-color: #fa0000; } + +.silver { color: #909090; } + +.silver-background { background-color: #bcbcbc; } + +.teal { color: #006060; } + +.teal-background { background-color: #007d7d; } + +.white { color: #bfbfbf; } + +.white-background { background-color: #fafafa; } + +.yellow { color: #bfbf00; } + +.yellow-background { background-color: #fafa00; } + +span.icon > .fa { cursor: default; } + +.admonitionblock td.icon [class^="fa icon-"] { font-size: 2.5em; text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.5); cursor: default; } +.admonitionblock td.icon .icon-note:before { content: "\f05a"; color: #004176; } +.admonitionblock td.icon .icon-tip:before { content: "\f0eb"; text-shadow: 1px 1px 2px rgba(155, 155, 0, 0.8); color: #111; } +.admonitionblock td.icon .icon-warning:before { content: "\f071"; color: #bf6900; } +.admonitionblock td.icon .icon-caution:before { content: "\f06d"; color: #bf3400; } +.admonitionblock td.icon .icon-important:before { content: "\f06a"; color: #bf0000; } + +.conum[data-value] { display: inline-block; color: #fff !important; background-color: black; -webkit-border-radius: 100px; border-radius: 100px; text-align: center; font-size: 0.75em; width: 1.67em; height: 1.67em; line-height: 1.67em; font-family: "Open Sans", "DejaVu Sans", sans-serif; font-style: normal; font-weight: bold; } +.conum[data-value] * { color: #fff !important; } +.conum[data-value] + b { display: none; } +.conum[data-value]:after { content: attr(data-value); } +pre .conum[data-value] { position: relative; top: -0.125em; } + +b.conum * { color: inherit !important; } + +.conum:not([data-value]):empty { display: none; } + +h1, h2, h3, #toctitle, .sidebarblock > .content > .title, h4, h5, h6 { border-bottom: 1px solid #dddddd; } + +.sect1 { padding-bottom: 0; } + +#toctitle { color: #00406F; font-weight: normal; margin-top: 1.5em; } + +.sidebarblock { border-color: #aaa; } + +code { -webkit-border-radius: 4px; border-radius: 4px; } + +p.tableblock.header { color: #6d6e71; } + +.literalblock pre, .listingblock pre { background: #eeeeee; } diff --git a/doc/context.adoc b/doc/context.adoc new file mode 100644 index 0000000..c1ab535 --- /dev/null +++ b/doc/context.adoc @@ -0,0 +1,25 @@ + +=== Context handling + +[[glfw.make_context_current]] +* *glfw.make_context_current* (_window_) + +[[glfw.get_context_current]] +* *glfw.get_context_current* (_window_) + +-> _window_ + +[small]#Returns _nil_ if there is no current window.# + +[[glfw.swap_interval]] +* *glfw.swap_interval* (_interval_) + +[[glfw.extension_supported]] +* *glfw.extension_supported* (_extension_) + +-> _boolean_ + +[small]#_extension_: a string.# + +//// +GLFWglproc glfwGetProcAddress (const char *procname) @@ + Returns the address of the specified function for the current context. More... +//// + +<<< diff --git a/doc/index.adoc b/doc/index.adoc new file mode 100644 index 0000000..b994047 --- /dev/null +++ b/doc/index.adoc @@ -0,0 +1,17 @@ += MoonGLFW Reference Manual +Stefano Trettel +v0.1, 2016-01-31 +:toc: left +:stylesdir: ./ +:stylesheet: colony.css +:source-highlighter: pygments +:pygments-style: autumn +:source-language: lua +:examplesdir: ../examples + +image::powered-by-lua.png[Lua logo, link=http://www.lua.org] + +include::preface.adoc[] + +include::bindings.adoc[] + diff --git a/doc/index.html b/doc/index.html new file mode 100644 index 0000000..dd70105 --- /dev/null +++ b/doc/index.html @@ -0,0 +1,1526 @@ + + + + + + + + +MoonGLFW Reference Manual + + + + + +
+
+
+
+
+Lua logo +
+
+
+
+
+

Preface

+
+
+

This is the reference manual of MoonGLFW, which is a +Lua binding library for +GLFW. +[1]

+
+
+

It is assumed that the reader is familiar with both GLFW and the Lua programming language.

+
+
+

For convenience of reference, this document contains external (deep) links to the +Lua Reference Manual and the +GLFW documentation.

+
+
+

Getting and installing

+
+

The official repository of MoonGLFW is on GitHub at the following link: +https://github.com/stetre/moonglfw .

+
+
+

MoonGLFW runs on GNU/Linux and requires +Lua version 5.3 or greater, and +GLFW version 3.1 or greater.

+
+
+

To install MoonGLFW, download the +latest release and do the following:

+
+
+
+
# ... download moonglfw-0.1.tar.gz ...
+[ ]$ tar -zxpvf moonglfw-0.1.tar.gz
+[ ]$ cd moonglfw-0.1
+[moonglfw-0.1]$ make
+[moonglfw-0.1]$ make check
+[moonglfw-0.1]$ sudo make install
+
+
+
+

The $make check command shows you what will be installed and where (please read +its output before executing $make install). +By default, MoonGLFW installs its components in subdirectories of /usr/local/ +(and creates such directories, if needed). +This behaviour can be changed by defining PREFIX with the desired alternative +base installation directory. For example, this will install the components +in /home/joe/local:

+
+
+
+
[moonglfw-0.1]$ make
+[moonglfw-0.1]$ make install PREFIX=/home/joe/local
+
+
+
+
+

Module organization

+
+

The MoonGLFW module is loaded using Lua’s +require() and +returns a table containing the functions it provides +(as usual with Lua modules). This manual assumes that such +table is named glfw, i.e. that it is loaded with:

+
+
+
+
 glfw = require("moonglfw")
+
+
+
+

but nothing forbids the use of a different name.

+
+
+
+

Examples

+
+

A few examples can be found in the examples/ directory of the release package.

+
+
+
+

License

+
+

MoonGLFW is released under the MIT/X11 license (same as +Lua, and with the same only requirement to give proper +credits to the original author). +The copyright notice is in the LICENSE file in the base directory +of the official repository on GitHub.

+
+
+
+
+
+
+

Bindings

+
+
+

The structure of this section purposedly replicates the structure of the +GLFW Reference documentation.

+
+
+

Context handling

+
+
    +
  • +

    glfw.make_context_current (window)

    +
  • +
+
+
+
    +
  • +

    glfw.get_context_current (window)
    +→ window
    +Returns nil if there is no current window.

    +
  • +
+
+
+
    +
  • +

    glfw.swap_interval (interval)

    +
  • +
+
+
+
    +
  • +

    glfw.extension_supported (extension)
    +→ boolean
    +extension: a string.

    +
  • +
+
+
+
+
+

Initialization, version and errors

+
+

The glfwInit( ) and glfwTerminate( ) functions are handled internally by MoonGLFW +and thus not exposed to the script code.

+
+
+
    +
  • +

    The glfw table contains the following version fields:

    +
    +
      +
    • +

      _VERSION: a string describing the MoonGLFW version, and

      +
    • +
    • +

      _GLFW_VERSION: a string describing the GLFW version.

      +
    • +
    +
    +
  • +
+
+
+
    +
  • +

    glfw.get_version ( )
    +→ major, minor, rev

    +
  • +
+
+
+
    +
  • +

    glfw.get_version_string ( )
    +→ string

    +
  • +
+
+
+
    +
  • +

    glfw.set_error_callback ([func])
    +The func callback is executed as func(ec, descr) where ec (a number) is the +error code and descr (a string) is the description of the occurred error.
    +If func is nil, unregisters the current error callback (if any).

    +
  • +
+
+
+
+
+

Input handling

+
+
    +
  • +

    glfw.set_input_mode (window, mode, value)
    +glfw.get_input_mode (window, mode)
    +→ value
    +mode: 'cursor', 'sticky keys' or 'sticky mouse buttons'.
    +value: one of the following, depending on mode:
    +if mode is 'sticky …​': value = true or false (Lua boolean).
    +if mode is 'cursor': value = 'normal', 'hidden', or 'disabled'.

    +
  • +
+
+
+
+
    +
  • +

    glfw.get_key (window, key)
    +→ state
    +key: 'xxx' for GLFW_KEY_XXX (e.g. 'left bracket' for GLFW_LEFT_BRACKET). +See: keyboard keys.
    +state: 'press' or 'release'.

    +
  • +
+
+
+
+
    +
  • +

    glfw.get_mouse_button (window, button)
    +→ state
    +button: 'left', 'right', 'middle', or 'button 4' to 'button 8'.
    +state: 'press' or 'release'.

    +
  • +
+
+
+
    +
  • +

    glfw.set_cursor_pos (window, xpos, ypos)
    +glfw.get_cursor_pos (window)
    +→ xpos, ypos
    +xpos, ypos: Lua numbers.

    +
  • +
+
+
+
+
    +
  • +

    glfw.create_cursor (width, height, pixels, xhot, yhot)
    +glfw.create_cursor (shape)
    +→ cursor
    +width, height, pixels: the image (2 integers and a binary string).
    +shape: 'arrow', 'ibeam', 'crosshair', 'hand', 'hresize', '_vresize'.
    +Return a cursor handle to the newly created cursor.

    +
  • +
+
+
+
    +
  • +

    glfw.destroy_cursor (cursor)

    +
  • +
+
+
+
    +
  • +

    glfw.set_cursor (window, cursor)

    +
  • +
+
+
+
+
    +
  • +

    glfw.joystick_present (joy)
    +→ boolean
    +joy: 1 .. 16.

    +
  • +
+
+
+
    +
  • +

    glfw.joystick_axes (joy)
    +→ xpos, …​

    +
  • +
+
+
+
    +
  • +

    glfw.get_joystick_buttons (joy)
    +→ state1, …​
    +state: 'press' or 'release'.

    +
  • +
+
+
+
    +
  • +

    glfw.get_joystick_name (joy)
    +→ name

    +
  • +
+
+
+
+
    +
  • +

    glfw.set_clipboard_string (window, string)
    +glfw.get_clipboard_string (window)
    +→ string

    +
  • +
+
+
+
+
    +
  • +

    glfw.set_time (time)
    +glfw.get_time (time)
    +→ time

    +
  • +
+
+
+
+

All the following functions unregister the corresponding current callback when invoked with +func = nil.

+
+
+
    +
  • +

    glfw.set_key_callback (window [, func])
    +The func callback is executed as +func(window, key, scancode, action, shift, control, alt, super), where:
    +key: see glfw.get_key( ).
    +action: 'press', 'release' or 'repeat'.
    +shift, control, alt, super (modifiers): true or false (Lua booleans).

    +
  • +
+
+
+
    +
  • +

    glfw.set_char_callback (window [, func])
    +The func callback is executed as func(window, codepoint).

    +
  • +
+
+
+
    +
  • +

    glfw.set_char_mods_callback (window [, func])
    +The func callback is executed as +func(window, codepoint, shift, control, alt, super), where:
    +shift, control, alt, super (modifiers): true or false (Lua booleans).

    +
  • +
+
+
+
    +
  • +

    glfw.set_mouse_callback (window [, func])
    +The func callback is executed as +func(window, button, action, shift, control, alt, super), where:
    +button: 'left', 'right', 'middle', or 'button 4' to 'button 8'.
    +action: 'press' or 'release'.
    +shift, control, alt, super (modifiers): true or false (Lua booleans).

    +
  • +
+
+
+
    +
  • +

    glfw.set_cursor_pos_callback (window [, func])
    +The func callback is executed as func(window, xpos, ypos), where xpos +and ypos are Lua numbers (i.e. floating point).

    +
  • +
+
+
+
    +
  • +

    glfw.set_cursor_enter_callback (window [, func])
    +The func callback is executed as func(window, entered), where +entered is a boolean.

    +
  • +
+
+
+
    +
  • +

    glfw.set_scroll_callback (window [, func])
    +The func callback is executed as func(window, xoffset, yoffset), where +xoffset and yoffset are Lua numbers (i.e. floating point).

    +
  • +
+
+
+
    +
  • +

    glfw.set_drop_callback (window [, func])
    +The func callback is executed as func(window, path, …​), where +path (an any subsequent argument) is a string.

    +
  • +
+
+
+
+
+

Monitor handling

+
+
    +
  • +

    glfw.get_monitors ( )
    +→ monitor1, monitor2, …​

    +
  • +
+
+
+
    +
  • +

    glfw.get_primary_monitor ( )
    +→ monitor

    +
  • +
+
+
+
    +
  • +

    glfw.get_monitor_pos (monitor)
    +→ xpos, ypos

    +
  • +
+
+
+
    +
  • +

    glfw.get_monitor_physical_size (monitor)
    +→ widthmm, heightmm

    +
  • +
+
+
+
    +
  • +

    glfw.get_monitor_name (monitor)
    +→ name

    +
  • +
+
+
+
    +
  • +

    glfw.set_monitor_callback (monitor [, func])
    +The func callback is executed as func(monitor, event), where event (a string) +may be 'connected' or 'disconnected'.
    +If func = nil, unregisters the current callback (if any).

    +
  • +
+
+
+
    +
  • +

    glfw.get_video_mode (monitor)
    +→ videomode
    +glfw.get_video_modes (monitor)
    +→ videomode1, videomode2, …​
    +videomode: a table with the following fields, all having an integer value: +width, height, red_bits, blue_bits, green_bits, refresh_rate.

    +
  • +
+
+
+
    +
  • +

    glfw.set_gamma (monitor, gamma)

    +
  • +
+
+
+
    +
  • +

    glfw.set_gamma_ramp (monitor, red, green, blue)
    +glfw.get_gamma_ramp (monitor)
    +→ red, green, blue
    +red, green and blue: equally sized arrays (tables) of integers.

    +
  • +
+
+
+
+
+

Native access

+
+

Not supported.

+
+
+
+
+

Window handling

+
+
    +
  • +

    glfw.default_window_hints ( )

    +
  • +
+
+
+
    +
  • +

    glfw.window_hint (target, hint)
    +target: 'resizable' for GLFW_RESIZABLE, 'opengl api' for GLFW_OPENGL_API, etc.
    +hint: one of the following, depending on the target:
    +if target expects GL_TRUE or GL_FALSE: hint = true or false (Lua boolean);
    +if target expects an integer value: hint = integer or the string 'don’t care';
    +if target is 'opengl api': hint = 'opengl' or 'open es';
    +if target is 'opengl profile': hint = 'any', 'core' or 'compat';
    +if target is 'context robustness': hint = 'no robustness', 'no reset notification', or 'lose context on reset';
    +if target is 'context release behavior': hint = 'any', 'flush' or 'none'.

    +
  • +
+
+
+
    +
  • +

    glfw.create_window (width, height [, title [, monitor [, sharewindow]]])
    +→ window
    +Returns a window handle to the newly created window.

    +
  • +
+
+
+
    +
  • +

    glfw.destroy_window (window)

    +
  • +
+
+
+
    +
  • +

    glfw.set_window_should_close (window, boolean)
    +glfw.window_should_close (window)
    +→ boolean

    +
  • +
+
+
+
    +
  • +

    glfw.set_window_title (window, title)

    +
  • +
+
+
+
    +
  • +

    glfw.set_window_pos (window, xpos, ypos)
    +glfw.get_window_pos (window)
    +→ xpos, ypos

    +
  • +
+
+
+
    +
  • +

    glfw.set_window_size (window, width, height)
    +glfw.get_window_size (window)
    +→ width, height

    +
  • +
+
+
+
    +
  • +

    glfw.get_framebuffer_size (window)
    +→ width, height

    +
  • +
+
+
+
    +
  • +

    glfw.get_window_frame_size (window)
    +→ left, top, right, bottom

    +
  • +
+
+
+
    +
  • +

    glfw.iconify_window (window)
    +glfw.restore_window (window)

    +
  • +
+
+
+
    +
  • +

    glfw.show_window (window)
    +glfw.hide_window (window)

    +
  • +
+
+
+
    +
  • +

    glfw.get_window_monitor (window)
    +→ monitor (or nil)

    +
  • +
+
+
+
    +
  • +

    glfw.get_window_attribute (window, attrib)
    +→ value
    +attrib, value: see target and hint for the glfw.window_hint( ) function.

    +
  • +
+
+
+
    +
  • +

    glfw.poll_events ( )

    +
  • +
+
+
+
    +
  • +

    glfw.wait_events ( )

    +
  • +
+
+
+
    +
  • +

    glfw.post_empty_event ( )

    +
  • +
+
+
+
    +
  • +

    glfw.swap_buffers (window)

    +
  • +
+
+
+

All the following functions unregister the corresponding current callback when invoked with +func = nil.

+
+
+
    +
  • +

    glfw.set_window_pos_callback (window [, func])
    +The func callback is executed as func(window, xpos, ypos).

    +
  • +
+
+
+
    +
  • +

    glfw.set_window_size_callback (window [, func])
    +The func callback is executed as func(window, width, height).

    +
  • +
+
+
+
    +
  • +

    glfw.set_window_close_callback (window [, func])
    +The func callback is executed as func(window).

    +
  • +
+
+
+
    +
  • +

    glfw.set_window_refresh_callback (window [, func])
    +The func callback is executed as func(window).

    +
  • +
+
+
+
    +
  • +

    glfw.set_window_focus_callback (window [, func])
    +The func callback is executed as func(window, focused), where focused is a boolean.

    +
  • +
+
+
+
    +
  • +

    glfw.set_window_iconify_callback (window [, func])
    +The func callback is executed as func(window, iconified), where iconified is a boolean.

    +
  • +
+
+
+
    +
  • +

    glfw.set_framebuffer_size_callback (window [, func])
    +The func callback is executed as func(window, width, height).

    +
  • +
+
+
+
+
+
+
+
+
+
+
+1. This manual is written in AsciiDoc, rendered with AsciiDoctor and a CSS from the AsciiDoctor Stylesheet Factory. The PDF version is produced with AsciiDoctor-Pdf. +
+
+ + + \ No newline at end of file diff --git a/doc/initialization.adoc b/doc/initialization.adoc new file mode 100644 index 0000000..0b8c1f5 --- /dev/null +++ b/doc/initialization.adoc @@ -0,0 +1,25 @@ + +=== Initialization, version and errors + +The *glfwInit*( ) and *glfwTerminate*( ) functions are handled internally by MoonGLFW +and thus not exposed to the script code. + +* The *glfw* table contains the following version fields: + +** *_VERSION*: a string describing the MoonGLFW version, and + +** *_GLFW_VERSION*: a string describing the GLFW version. + +[[glfw.get_version]] +* *glfw.get_version* ( ) + +-> _major_, _minor_, _rev_ + +[[glfw.get_version_string]] +* *glfw.get_version_string* ( ) + +-> _string_ + +[[glfw.set_error_callback]] +* *glfw.set_error_callback* ([_func_]) + +[small]#The _func_ callback is executed as *_func(ec, descr)_* where _ec_ (a number) is the +error code and _descr_ (a string) is the description of the occurred error. + +If _func_ is _nil_, unregisters the current error callback (if any).# + +<<< diff --git a/doc/input.adoc b/doc/input.adoc new file mode 100644 index 0000000..004d802 --- /dev/null +++ b/doc/input.adoc @@ -0,0 +1,131 @@ + +=== Input handling + +[[glfw.set_input_mode]] +* *glfw.set_input_mode* (_window_, _mode_, _value_) + +*glfw.get_input_mode* (_window_, _mode_) + +-> _value_ + +[small]#_mode_: '_cursor_', '_sticky keys_' or '_sticky mouse buttons_'. + +_value_: one of the following, depending on _mode_: + +if _mode_ is '_sticky ..._': _value_ = _true_ or _false_ (Lua boolean). + +if _mode_ is '_cursor_': _value_ = '_normal_', '_hidden_', or '_disabled_'.# + +''' +[[glfw.get_key]] +* *glfw.get_key* (_window_, _key_) + +-> _state_ + +[small]#_key_: '_xxx_' for GLFW_KEY_XXX (e.g. '_left bracket_' for GLFW_LEFT_BRACKET). +See: http://www.glfw.org/docs/latest/group__keys.html[keyboard keys]. + +_state_: '_press_' or '_release_'.# + +''' +[[glfw.get_mouse_button]] +* *glfw.get_mouse_button* (_window_, _button_) + +-> _state_ + +[small]#_button_: '_left_', '_right_', '_middle_', or '_button 4_' to '_button 8_'. + +_state_: '_press_' or '_release_'.# + + +[[glfw.set_cursor_pos]] +* *glfw.set_cursor_pos* (_window_, _xpos_, _ypos_) + +*glfw.get_cursor_pos* (_window_) + +-> _xpos_, _ypos_ + +[small]#_xpos_, _ypos_: Lua numbers.# + +''' +[[glfw.create_cursor]] +* *glfw.create_cursor* (_width_, _height_, _pixels_, _xhot_, _yhot_) + +*glfw.create_cursor* (_shape_) + +-> _cursor_ + +[small]#_width_, _height_, _pixels_: the image (2 integers and a binary string). + +_shape_: '_arrow_', '_ibeam_', '_crosshair_', '_hand_', '_hresize', '_vresize_'. + +Return a _cursor_ handle to the newly created cursor.# + +[[glfw.destroy_cursor]] +* *glfw.destroy_cursor* (_cursor_) + +[[glfw.set_cursor]] +* *glfw.set_cursor* (_window_, _cursor_) + +''' +[[glfw.joystick_present]] +* *glfw.joystick_present* (_joy_) + +-> _boolean_ + +[small]#_joy_: 1 .. 16.# + +[[glfw.joystick_axes]] +* *glfw.joystick_axes* (_joy_) + +-> _xpos_, _..._ + +[[glfw.get_joystick_buttons]] +* *glfw.get_joystick_buttons* (_joy_) + +-> _state1_, _..._ + +[small]#_state_: '_press_' or '_release_'.# + +[[glfw.get_joystick_name]] +* *glfw.get_joystick_name* (_joy_) + +-> _name_ + +''' +[[glfw.set_clipboard_string]] +* *glfw.set_clipboard_string* (_window_, _string_) + +*glfw.get_clipboard_string* (_window_) + +-> _string_ + +''' +[[glfw.set_time]] +* *glfw.set_time* (_time_) + +*glfw.get_time* (_time_) + +-> _time_ + +''' +All the following functions unregister the corresponding current callback when invoked with +_func_ = _nil_. + +[[glfw.set_key_callback]] +* *glfw.set_key_callback* (_window_ [, _func_]) + +[small]#The _func_ callback is executed as +*_func(window, key, scancode, action, shift, control, alt, super)_*, where: + +_key_: see <>( ). + +_action_: '_press_', '_release_' or '_repeat_'. + +_shift_, _control_, _alt_, _super_ (modifiers): _true_ or _false_ (Lua booleans).# + +[[glfw.set_char_callback]] +* *glfw.set_char_callback* (_window_ [, _func_]) + +[small]#The _func_ callback is executed as *_func(window, codepoint)_*.# + +[[glfw.set_char_mods_callback]] +* *glfw.set_char_mods_callback* (_window_ [, _func_]) + +[small]#The _func_ callback is executed as +*_func(window, codepoint, shift, control, alt, super)_*, where: + +_shift_, _control_, _alt_, _super_ (modifiers): _true_ or _false_ (Lua booleans).# + +[[glfw.set_mouse_callback]] +* *glfw.set_mouse_callback* (_window_ [, _func_]) + +[small]#The _func_ callback is executed as +*_func(window, button, action, shift, control, alt, super)_*, where: + +_button_: '_left_', '_right_', '_middle_', or '_button 4_' to '_button 8_'. + +_action_: '_press_' or '_release_'. + +_shift_, _control_, _alt_, _super_ (modifiers): _true_ or _false_ (Lua booleans).# + +[[glfw.set_cursor_pos_callback]] +* *glfw.set_cursor_pos_callback* (_window_ [, _func_]) + +[small]#The _func_ callback is executed as *_func(window, xpos, ypos)_*, where _xpos_ +and _ypos_ are Lua numbers (i.e. floating point).# + +[[glfw.set_cursor_enter_callback]] +* *glfw.set_cursor_enter_callback* (_window_ [, _func_]) + +[small]#The _func_ callback is executed as *_func(window, entered)_*, where +_entered_ is a boolean.# + +[[glfw.set_scroll_callback]] +* *glfw.set_scroll_callback* (_window_ [, _func_]) + +[small]#The _func_ callback is executed as *_func(window, xoffset, yoffset)_*, where +_xoffset_ and _yoffset_ are Lua numbers (i.e. floating point).# + +[[glfw.set_drop_callback]] +* *glfw.set_drop_callback* (_window_ [, _func_]) + +[small]#The _func_ callback is executed as *_func(window, path, ...)_*, where +_path_ (an any subsequent argument) is a string.# + +<<< diff --git a/doc/monitor.adoc b/doc/monitor.adoc new file mode 100644 index 0000000..78cd2f1 --- /dev/null +++ b/doc/monitor.adoc @@ -0,0 +1,47 @@ + +=== Monitor handling + +[[glfw.get_monitors]] +* *glfw.get_monitors* ( ) + +-> _monitor1_, _monitor2_, _..._ + +[[glfw.get_primary_monitor]] +* *glfw.get_primary_monitor* ( ) + +-> _monitor_ + +[[glfw.get_monitor_pos]] +* *glfw.get_monitor_pos* (_monitor_) + +-> _xpos_, _ypos_ + +[[glfw.get_monitor_physical_size]] +* *glfw.get_monitor_physical_size* (_monitor_) + +-> _widthmm_, _heightmm_ + +[[glfw.get_monitor_name]] +* *glfw.get_monitor_name* (_monitor_) + +-> _name_ + +[[glfw.set_monitor_callback]] +* *glfw.set_monitor_callback* (_monitor_ [, _func_]) + +[small]#The _func_ callback is executed as *_func(monitor, event)_*, where _event_ (a string) +may be '_connected_' or '_disconnected_'. + +If _func_ = _nil_, unregisters the current callback (if any).# + +[[glfw.get_video_mode]] +* *glfw.get_video_mode* (_monitor_) + +-> _videomode_ + +*glfw.get_video_modes* (_monitor_) + +-> _videomode1_, _videomode2_, _..._ + +[small]#_videomode_: a table with the following fields, all having an integer value: +_width_, _height_, _red_bits_, _blue_bits_, _green_bits_, _refresh_rate_.# + +[[glfw.set_gamma]] +* *glfw.set_gamma* (_monitor_, _gamma_) + +[[glfw.set_gamma_ramp]] +* *glfw.set_gamma_ramp* (_monitor_, _red_, _green_, _blue_) + +*glfw.get_gamma_ramp* (_monitor_) + +-> _red_, _green_, _blue_ + +[small]#_red_, _green_ and _blue_: equally sized arrays (tables) of integers.# + +<<< diff --git a/doc/native.adoc b/doc/native.adoc new file mode 100644 index 0000000..5606969 --- /dev/null +++ b/doc/native.adoc @@ -0,0 +1,6 @@ + +=== Native access + +Not supported. + +<<< diff --git a/doc/powered-by-lua.gif b/doc/powered-by-lua.gif new file mode 100644 index 0000000000000000000000000000000000000000..e7ced3934d1abd20e6ed74dee100cd946fcc250e GIT binary patch literal 4805 zcmeH{*I!eK+J$#^b{Zh;B=nku(2)s5X%HX#ljgtMU)xDQ31yzo|%8)yZ)Zvx?MMGz3=k%^Ko&GT7nv|53o}Qkaot>ALcjU+s1cC=ad@MF!RaL02F3`{@*s!4x zk1x>HF2dtQT3W?=dL>3irN+kP`ub&La)p`MaSBCjW_H5Ls?y5pq^)h$=FK(s_SH^K zwf6QBH@7-Bw|aN?Gaer2yu8kOcu1MdCV&5?ZQEJ`1DjZ^w(#)QkdXGs$cs@?7owv( zcJ90s6LXQnxf~bQwRdk@~D{E?MBoaw|eLatNtEs7}t*x!Sy}h%uQznyLxpHM-VBqG>oB8>J zMMXo!#kWgJhAS%Wh{Yq7m7~?wW3{#SYHRPGJNIit!>^5v<1H9Gn>$c{MWf z`tIG=V`Fa~KAcx7-;R$jJbwIsYHD$Mdg=M|-)CoM=jZ2VWG1#gzb0V&kMW;h0I=(T z4bG4$lMd!%iPkZrvWDA5u&IANv#W8qRCiO-%h9f;k>e!K5<|a7rc^JpunX~P=6A97O1AO2=-HU}%Ob7(!iqrqN06VuwHj+CGZn)E zx4_%h9dq5JW>eL|2thXx+Ctq9`G-&{E2sUlhaKu2N5)R0{8cH%p?A$GD0Z8&ARbZ= z^go1m3-#EH6ZD~~S!5A4)d*EJH>uXY5QsP2lpYiHiAj1r3N;v}ZAtWt5^R&gf!(zq z4b4LdLERbQlyiC-5X8P2!$TSKImFOk?k3K5sPqx)(_gonD!_(ylB>rwiH!0&dp~WF zML3Q?plSQ)=iHHN>N3&Qe1%9rbugMmGyEZ6r2(4G$5H|^Em(%=tz9sM>v#f4P_qj4 z06uLXohw?s`xH1#V|Je;tFUH89)L+u7^opD4}W$Y+1K#q9gk}-OZ@nZ(U3kfz7N(R6i0w!AwLY zHP8z=RBqsWNPMK^Mv!&Uofp#Xn6ZYR&PAfVRa} zz<_lfZ>XZ+GYwT1oUmYpx8_IsNv}pGg->l{QjL2IPneM2*L6MA_L{>J%AUt6&Q!A- zQap{r{`A%JywCB#XnV1KLuzMohSWU8AAKLGe-HWNVgJfY{B90E1=Gjy$4eAQGr}FU zUIz;vp!@Xa-t>=qXrAl3#q{P;q;B%{p2J{{eEjBhe#d02hVvv-*TzL=C|c?2zxZZl z11}qC!y6POtLBpAw8DhoKFs zACv9(Y!L*X-cNh2#Y$y*#o@k0C0BWjRh^}tL^)up8?Kkhi^o2azdANnv> z8VvkpU{+eIrD`kX@m1^_Jy#c_-Ce%!BA%E>OOf8xcxds}^p6=$WVvF{w_18T5(05s zuDmB*M%;$xCV0zx0&_XvSO8@PrNqBhn^$3fa}NjBc2J{!=!p#yZo{M0IFw=dj7qld zkVd&Bux=w#A0{>B`+t2H%6&fM(>$Yjg@wS;;$G-EO)<0z#YKRk9x&&iv-?|7$tv~g zRyu%jrWY=(U14}i20$Gf$ez;EYx6n7ZY3dQARu5^+9TCZ1^NAJa<@-A4Rw+phX_8e zAc+cL_rkQpSqh41KJ1)&oJx>GjyB`EY;b)0pYCIK0evTmHOes-7ScdSi%_gd`Vd-q zlKR0%=-i(*>dEzBB&XaF+2jE3>B#`@`bU5)cw<#7xOd^<>E#t?Exa;(`>* z28Pt!029nv6sId+Np_jP6uZ zg}MqVX%=nn$Pd6I@^@uCaZjuW2D00+@h_98Xeqh!bzqb1eY8qY!S-5-Hzr$9bEr z36awWa?=Xj%4Y5#6WSnSH&ywFre>X-TwhzOHVO~{lIwLUiQaZw{T3T}pf2> za|3CZXZc#eWtZ;ZW^O&|R2WgV`XOQh$Zr$Rd#pF}pg{7@ihY95>fnU+qbKLDeix(F z|B7mPP7HFJqA{8YCm3aZ+i`4gJs(5BsnIJ(61F`$VIx4USTBRK;iE_^50SMa78j-~ z9GRre*bjYuu*wfh%(^Ca`t)#QFJKo{Ci{s(x!l1%^^S@W^S55?AaKOm8NQ`R`@Hyz zC)a=z!%ug&HQE3{w9PiIviH6^731W=XYE<1-mt;t-ad0|{6W@sraDjKCw`#rse4I1 zZrMFgrs=;4er~gyblbuGOVIHa_AXa@arXMr3~I6sppFIG)-^}9FP&)~FO2HVV9D$3 z1t760D{{+|js~1F-yWOSjEsdge14I%SjQoEmse*9)bR54rI%?vw$k>z+H3|P&A#-99S{pMO|4}I)|c{5WnAN_l>mh_?jXj3 zHz7=`eJG@oJ5+O#J2V?#ZL3iavcIgjziB$<%>Fvp^u=8on>X(jwr?fJM_~;l8<>)N z_4ASFh92Jst^P|(b08b(+e&-WT-PwwyZPGWxcic+`Q_92 zD|M@V9pAs~a-2@RYcqsX>#ksGy{}thowNB6a&92w+1Z|fFMX%}t@%}DHuJGix3OE3 zU-s7TRW!m)ag|Eh-iEfV*=$bQs3>x(c8sYGQ^kc}vh zEfP4K7o)~-aEyb?XoCA%l%GULw#4t)Bstcfp8q}D#AsQ63jm}#11NEjC+o;69`U^y z?}o^O$ZnOrTc2jV-+U>O$ih6C2|K3BSz>&U;{un@zB9t`h)3q zPs28dya$*Y+eU4Wa&Y$y=B#;2H67x$)74p-*e+<~5&la=R)eIpx&0V;0vR}Lzrz_W zmt!K8n6=0wAeXC}2Az@M#j}u7!7DFHbdVhX&qyg4!e328kfyME0f@!|Z=ir?=Ef59 zOdDgJ?G-w_R~LwCMCW;xRgi zj7QKdaqmtRfKqhE-xuuZtiMiza?yH%!~@2mLae=E)Ls0AyWtcHVDFn_>x7svhmXn8 zIjq3H$3r!@=)YLKQZ8n{95XD$pxL-|E^6I^?JS2grGUl?o~KM_=>l=$TxeYIulXqS zY#kt}6z)c{z0pW12;s4E3lsGj58Ouz6`|+B2`0%vD;Y@BZ*s71dU)PSM~V_~C?}=Z zWEq(G3PC%>ZZ-u>EaL1!^owDPS zR`+q^&JCLXi!zH%Wu1NZ@6<1Ci3IIS(q`1tXk3;OTDyQRl_rvy4+btP-Uf8#qp zARd-k&$?CBvGQby*}j7p{oMm95l;ynW@MBK?~>nRtcT>{jf4<5Z`}kj1D-SOzC}RI z48!{Ib%uEn2PkYjFINMBW3hT<2)7a%a!-lXheK%t4$cnCXVu4{lbf%ok}(1A{d%-g ze|^Hp@B}wu@hnz%U@R7O8ct$ejn4KxqfftuGy!F4#91_sQ{9tP%iIKKvygc4mY}=m z^{QOQ@QBTvVj>^w@r{tr@z)x}ialEo*-%!-8RFBfgQfsp>AKhQDj^o@BZhXLW`Tp) zy)a~<{G~nHneFSW#RVB$w6=BknHRQU%L8ZcB^>3Ve*qv@64Fi%+5$)y0DAlS+&go; zkP9(I{W|0x8zMf9W4mkQr(ad^25;;pO7S86JfKW)9h08^{1-TaTQjYS3*`YU)`jW3 zo5(J=UW7p^t8d|j*-{=cjSHy&H$Pm2v)~&PK9(s3!lbuW1K_<~K)Ae(jKD>3k~BIB0SXip6uPX8gev$B`1e6V0RMjo8I6K3IA<|gbtLfTgJc>G zj*%T@w4A~9SpPoIO#$34P*9{$vJ#@|9@!^3-X7|6bFacl*_26-q4Mb>Fvz57j_6Y1 zNGRd?v>(;&RT-{*CC^KGj7h#V%^$Ap)g8_*r)hUip+pWVwtXOFOe9soLZU2`ZG{s< z3Ly(LP1mJnAIaFg9oo$v^PNzjhSu(xWS^8ZpIEYhbj|B~S2Zo@>&z`LFaL_Wi<9gf zukMX&ZM#c=e)(}u0s9oTBaLu}G1Mani-(3_ZEbDu#%Zthw8Gvyl0H@CyXGS)UWtQiV=>P0K4Eu65)X=x4S;{+`VnD5?&F4_LH9VB;2;wO85vo$O2c`7ifq1G zZ*;Cw^8+od;q~Dh4lXVXCINw*s3`QickeEowX0GYb(*IZ7Z(psS~D>1-Qf8mudZCW zA5ZzI6*G6Q{*4YwDVwLSVNxhcstDR}G?meIr8y=!8Ha-a{rvnqTi8Dr96){f@@0Ra zh9npP{V?;ZM*wZ}us^C;z*7&Yi!ItlDps#4o66_UG8!7VZ{NP%ci~GbYzs)*Q3u z*R}jfJEm7xF8X_}k7{b-c|yM5s;Wu~3If?JCgPKmcds(0raqFBlS7RrLt*~+pR~F< z4tPCtpP$}j9R@K*+Hz|_w@L(AkVJ$AP z!V?xs*tg^~G=g&|?zbC)GVr^na&>k6uG^MaTg#$AjeWFGQ&w9WU#?ch=S$7N5Z&I+ z7X}Fq3bM4eh9PBTO~}tDm6MYj9vwBgJKJJwXbm1QEi5byTJQ3vZ{K*2gJbEr6XUSd zu!n|@jv(UlB~2ubcv|4)?xWvz<#}=OfY)`bju*<5braVz-)D}S=xDTzJ2En|u}sdW z!$WJW?3E(#+f%R^mM!nWWPno-Hz%l{(@m%HMUPin;=lQWjbY94XS+5||GBW;w_`mW?#}QL;bEhTIC?_T+ib+VoEiElk($LJdI2ge7 zk@u2QP<)`H>o;U!F&)MXyKvzn0zW9}?#>Mffg^bTeyQD+zL56f><7l^9}Z5=gq)o5 zsRD6)VZYA8b}1<-HtXNC?e36?6nae_mwn72(y1PQ|GZ_tKXOEBrM8<<%u0o-p`=KC zjg5^^RgKLRmR78@Gc)9`=vCj;1Chj76cxt_1w0~?Xeu)Vy=x20H&e4<=;-OSTI`AN z@$pxkCk63hq;8Iven^w}4pe-q43CT3J6>u~NN0f-Nre&gy4t)tn7w$N$Ak-nhDFF% zE%$glX<^M8zuKP;rjk!xT&a$m>}{)y#3{r8*9Oag6f?fvzx4sk)S))7%r6r7xMd(9Hk()>P}YHI&`}#^{j994x}6>gV`B9`3rD=(Hw++WZkCtjk_!pt!XmzjPfL?lRmJ-A=Z``TUkXTc87k)EnUdhtdv5z( zu;g%XaPjf+y{m1`5mC--AKhu`=!_xjUD3pX%OzA>7$Bd&A>UhSPcxd38d9N)=3(X z(A6cxrdHT|y1%T~vS7hmY;&f0ez;E3YcnMCk&f_Z2gxx^n{jx(BZprZ7A7!|PEw+! zyWJ$ZSLB_c@nmj8fU|>9njClw2}MQp>FMbU0e?u>ZDK~oNII*@Zky-NX#D!&xTvV4 z@fLVgTo*G}exe}EfDzN}U0FuVZ=cWA=%B~`YKV~1leoCI}y{kEFG<@cG@2^V{1q z?=SZnET_peYV;LfU!G-^mDBQOEjhTzH{LH|uXdjoE(T50s_NME+u9ejwT0&AL&3np zhDV}^R^bxj>K^CaB8u-{Q)k>w*!q+xY!U?iUf?$2hy>}5|7n>DEj}e>u+eH(MqVD4 z0Y&fQM@;usCqzT71^>IPu%&Kae&2_y1I+0YWTr^QY(X7GBO|H}e}lm`XHMPr;+?}! zu&%DunVAv<1k1k1WMqLMq400<@x^NNjVP&qvKfjHiih18{{E)F>LkrwM(@#QG|-uYsdo1w#;O%AaoSRVwX4fzd1aZtNafv5HTt)gCW>(pwMP!Wp(+5NkEme zGwaPbpKZe5K!k_tOww8%MG-$sKgx`|9h0iySXr_-on#V6z0sC>Bv(L^m1Q+GrDXMe zfGSmxrDkPq7f&RmmQwWa04Xo^!INTJ@BjffJt9JdpXhmBaLaxF+DmIGDl&2##Le&d z`FihL`&_>VD^M4{m6vZ_{22wQ3Y&;%Je$|q$19B#E`OF2T!Sz4az`m0tJ`mxtntc_ zE0#j{U6H<2k=Ht`;Vlho*q;ncuy?d|#*@=D)%5j8=BqrB#CWi2Zp_v@jmB~X({lxX zKtm|S#Kb6(krR@W@jjLZ>CKl>Q21|(EW9KrvBJvB%WE~5#}LLcT0LlKX$ibOU0$?z zjhK>?k_MceIoAAY(HM)2sySbE_TJxktzpor&lnqPz>87Ts5Cn%Or^?U9h6O!cj=z62>|n>)!df#N zg6vE5peRkKd=Q%ni-VsQm9o4bs`n zB9HaQfBhn-r$-G)O~sv=nd!uR{PYRE^XWoV=;;iOI_WKvC??$dx>II;?GZu-(GnC& zmXCAPjAJ6C@@eZMqs+?WWMnfY9WyiQ1^M~?Mg(U~f~oBsXNx99cUNi)FW5b7B7S~C z0Ik&PG=2LP{ttg#%_@)fr62?cR%+H@VPh8!yE_QxRqJ^N{ilCN!z5eT)>` z>OU{x;=)nW#g$?FMe3 zH-j-~nVA0WjwFQ_4(GV9%YOch_jn7j7)xh`gNJ{MgCk*U%TQ2IKs=hvcQivK==|6A z&q)i05l0Z|w?FwvsGYa@O$M;bx$dslgX|Wb8koO1xVY*ZHZV*r42=3ix?PTNscWFL zTi7|9Xf$iM;?vx_t9(x*9G;0ED@ozN{0(P02#p;t1+U%I8Bq1c67m0oumEc8?(Q0L z5P)37ASo&7ax@=Pmg^Zb zapTif^|C}z_|iFTupe)p4QDlwPbt%`Iw&8~7_)jaIWfGCEqdqzo&Sy{v>12YZAXpe z@TbYAF{v0BC_6dTX?ECx4V9+a7m2#Sc@6d;QXZ;SUm`eBOK(lsN)5$N5?Aj*cfQEB5~Rs=9L`iX~W7##ze-5 zGu|E6MgI9~t@_?Vz1&aI3-ZrA_ABt z<~=t~+)D;K_xa#|G+pF=nzB$w?ja%H?tYMz))^1-w0K`0N2sW(j^D1IZIh6cbb5L6d_y9H)(haG?&)+x*g(^0 z8sv|IKmRf3d50K`h<8AV6!wo;B2)lrS`?pCnz1(*dR`*AHv|BFrcPsK1#PI(W{!KZ z739VP)HxXih2$RxDg8Fm@qLDyphY#=>JLRD;!ED&w@ge*Y6I_MDm6Sj9Phr;8ua@E ziQgSj&-00XC@Up9v>e!H8=m)sz@qvwb@5PY=3|N_}3*I z&Y||2_pAlMqq1a;@6^9bb|@Xo|LVzjq5#&ES!{si`So0|r4q(CIaClsVv26zl7&>|n*#R{i}W4f=bF_g*2d#9~DU zOg-{mJtLH$k}*X~S(ul2ulm0}gFd)L-%RqdofANOg$%Y(zzxLb*mYoo6poamwC840 zTs-`=g%LJ9+7Un+vKZZ2oeFhRyTIsmwf_^9`ST6g13j%ej?VrPdv*#vq;I*og*KE7 z2S<0;|MfP0;ZJF4DVz6=Eexz+Sdi@55(+?rMz^PHAz#0;fyP{0N9X>u1Cq{VmpSUf zh=qdEXlmLSHe&i{ZIH}&&=#BNcGDvpxfJ;>N#L~R@*OBwXz!c9+AJIr9byr#in-mW z&dg#zJt%p5j6;ET|L0a~Ba2F_z7%wq8*Mm*?-NP2J57(>tC9HRCSmCBgos*nL`VeLL6tp$^>Z{`IDu zF&%&l+ZBz0)wY}#JHDQn0kD#2%Z_Zjkk=eKUTy?Cs$MwybH017mlQTrnrM8-)08#RsCV#mZOvZ)0%+ zZS_dxbAm=jI|iEVQhmOzo5DOEH%#JWghWz_sH-QBcYBSz<+O<6QOTzw;t^ScLv-4gnM6(W$Hw0b+!Mn>#5lkJ+DQ>2*fx%?Gj~ z`rSWzTa`6Tt=W$b?~n~+ju!Y+k4K1#r+s$5z8(F-#^pP+F5O2c>rmdSmS9awknCE+g4;p}*{nw4!0w|WZc;D)` zPP4}0s;NXs)0h`j3^sPBaQzD#)x#QTdI?l>iWgrngd5R>N@fG3ipT(a6BGo~a{GY` zc64-<*ZD6RJUl$WvRIgyB5G>bpldQY-yVEprTHD)Xkekh&yQe@ZdAIYeFy4B6%MB9MXO2vn$jFx=yVU@}|^l^scZ16t|+uU2kCjwl3 zHMO1EC2<@bJXT}$G9|r1J_4x-Bn|TVXGUnk8U%gMKcarGkB?7u@P|iPGV9QLjTaWBZyJe{IW@LD5snX-A+{>+k%u`~+^mFB~HL!YZ#{c(T8r zlxxs*Xpo$2xrSw6T>~GOoUFSSMj`;=y+X)IrIfR_^y|iTTw7YlTHKfoz>+m#ix|sl zNs&*xA~J@N4eETpQCaupM*Ki0BkRq0>W=N{`Ht)P2stz~)aR@Zk;xx&#b7iPtM_wm zeosdWX3_7zu~5{73^p@CDyliICF$f|KD}{+m&6~;e&=mN2@qOnhT+McZBBG1-PTRE zK-V(XfZwu`lAk_5w(GqW33`4yUh`RVLMH7ye=(Gkt7dgOe)M@dzvZ%nLrpjlp7&Mx zG}jAK$i>s8cf5vZ3L7n{#ZzJ_REd{Ji~SlPv>h{xJ_LhzFWezA&F30kP#8#ht=AE#8q}YEN;-Oy~o3wNT4Vof@I9RACtwplGZ zc+#nZYI6g8bsR*CiPM^#-iqHf)qk}O58PZ{dGgcmaM(q3b+fZ8^gcvOLHfH=dJVP>BH$bmCTB`U z#?`HsnC$hs-LG5XM|GstK?^1-Dyk&d1V%=J_`!o+Os`LKTUxr(%%-rePD?{+jaAOn z^c#cm(V+sD)gIx>Z#XzMQyCbOp_@|wR~~YTU}U6^Dr&PbVEwbR<&%@uo14U!8u#s9 zd4A*ydLvSiKhOXyv&DVbCPO>hPLYk@W%O7EYc?uU4NUxPYr@JRE&fHGi z;=4ss$PjRDZHanhK6ZxI7z+ysd{!DN)M(*eA=&{uchvhPIGCvFKh&|#^Pj;!FZW_` zSv;T@iNJpRa9=W+gfM&H&C z&{#_`uTWtAXK|oef*YV;lg53yEY1oGXtn$~>#kq-CddY=rM&bxFukt|n}B<0s0a)V&z3Kb=yy0L^o5;!Moej}`Yf&o?cI zygsc+7Sf$CPY(+Qs@fGv(x+1ef>5^PB?5CaeAwzl^C9lbC|ik-ifjR2|U$jjIzobQ1WA8SxkQ*(Rh)7=-`F8_{C*a$(LM?0Sr>PK1&xg;v1<+{Lnxl;`YsQ-bDZ0?fg$&ENAB6>ZWP zERu%veUJe10*CM8Pap>{92|7DT~5F)sn(JV<}Q=LheQ+E9Qc>0k_roxG%VRV0dx53K>Ty7BOHbF&!lv` z5=+=Hs*aXDH(7{!r8qw4uQuL2l%ZH63Ucy(VYE$DEbOATqiQ(N$;6d~V9HIUVD%C} zLpKl93)t``In0(0t(_9j91wh<@910aq7t|mCWaW$u#%to&L)`AkzaH> z`_m{Bxm^>3QC>_2^Uf#Qf>R<=Kb<3w$XE+-KDa`sH1Vpgxkp zj(GlyK0_%v}SU9%trR^DcU9?buL)LY@#*t!>Kd-45jb53?|Q zf1N23hEwA85BplFv`j#{`Jae6nDj{p>3&^l6h`z3P1|mRYB+9=e z!0PK$Mnq_ZG2&7;5pL9@r@*IY^ZYP$zceZ3N_%+y2%*R4{Svd9QCDZJl{&@igEVI5uMb$U~negq~KD77qYHy%CpRa8R-e-AU&y7HVK`3$A4mU+2S#O_q zJf5GlyxPrngOoXuU0&L@q@b%y3ybKMG&(lkrQq4N{`YrnO%D?Ve@C{af#B}0f(dLC zZpr2OP@L!74Pc459M;EvrO^M$5v`s&$P%ZLA$sXYz0KE<<{MaOdS%4g9MYB@E1Bg4 ztf)?Tg>|h_MS-}t==TfK)W7*5yXRRO$K(Q?&u|zv>{F`dEYh*b=etS#c6f9` zLP4NhvYE-D6iM6cvT@rz1V%?UJv~F3@q13YT1Zg;dy_WWG;i?x5X`E2Zit$gy*<;& z$Ov%+h8`_+zHf5p-L~e_c^slHF(#|2i~xZm+!V@PbGW*J!}em`=$pUE0N6#o+X3<@ zCa7%nr3L`Dx^L+Hne-PDGykha8XpMTk(6$EFrZdeF=c&3n5_wFHX8m+)Tc^n7Be|E zL9dV^4OD<)|6e}`z28p&8D*%?MwvH;ex=+Fk2#$geo!m(V_4ARlQW;IC%ch^OdP_U*g0W{wB$iXej5^oNETV8{%NjgfxB^S zhA+Le+(k;mGVg*r(xtd`Kkfp@La_m>Sh7gx4^S0O7wR;x?-1e0j; z;Goa;0J}a_D9q?q&fY|h$y~*!$WsU=th$Cqz0Cp>vHz1(jWJxW=Qgdo5cKHZM2!~z zl^+=qOVu_qx$SN+E6hr=uksK_4Q21NX2wgtRIBGs_P_P3HinNkdH2bfa+Py4K!TBr z&q29uMs@X*WN{={GdagzDwYG)Ac-;E7Dy3 zY2+B?r(eU@>#jsb``51L=aW*M+7-5{*XC{vOZh@0!-JV~Aq!ZbR7FN$5Sa!5ZJ5|= zpA6V6aQ>h)59v54T3qdShZm0YA-Mhh;3Byit6L>pE!Et?wwkhcs#Q)j55bkh{_&OS zqD)v3f~3_c7Iu9C1W({U08BA+r=La@?qch?Q(@unH$>EZIzb-ZCzctxzb@6mkW^Hx zfwJoa@ZobN$^_Aqv7_MClsK_7Jby54GmDEQhR}-#Q(~oNkZ{B?I<&75sWMtY2y*Y( z!*v|1u|(&>OWei9m-_np&Qt$0Y}kKv0MKDPpR;j@Il;65losR4WMpH$kCg1%{kj=J z_WcO{t!Gc#Q093_;@Xeaf$k27vfH{a48XB<$CSsXV-fTpv5-SDO7@u?U@gp}LKawu&i zaa^49H--1uU~r<4brlBvPV}U5WKkqh9N#23$4e>^??*U^X$hI|-gehZtyV{mFx*ZA zbOOpDi#wDa`GC7Sk6e#!WZ+Q{x3Vfl9>Ui~${2gZ&yG9etOwJp-$#mlq6;lE4pTzr^|Gj-M(?r?i25 zUas61c9MRuaRO|Kot-5hBkiS<3b_=%V=?)O_7#IfNj}Qq4SKn=v5ELnoe43dM>uWq zGiOy*>Ohj5^zC>e)Ctz8h)ZMU?MB|{ULJEYx7&l5PjFu^uoD5piqLgA`)cx>hyz(n zD!t|*uoL*#yH-*Wj=Rk%X;G^jbWi+-X4uej6MNpJq4?b8)hEe&utA%)F9WXjRS~)F z1ma*JfKBRnyY}JfP}BYK+BWa_*!JdhZM5EORN$+pcNCLZ0QZJZ5-?Yl9sKGH?4lL) zxg&@4_-A){Pc~M`HA8+n;WBR?g}1C9IT#_alVSm(Ga5hmbNkhV60c=@X(>X|NQhL? zx%Uzn5^x@T*Xu~#-8IeiI{eU+_Al#p`%(b{K~^dIn`PA5+XOtAS~AMd;U8EduICAkmN26lj03~aEEQ>ojjHJ7WvE%+EjA;QH7+O353mzUBX}nZ#=9l&6xJ2yJC)f=i zH6^79s#wA{30Ya!6$HhI@cG)CFy2STcmOoMq8&`Exzi*jBn%7QQZ5x+pOk+)7!7@Ht*evw;$OZ*D|)mf-rl2BX^a99K7-e}baX)JWx&n~-UHSjd-&mr#GgV~ zIL~gSnbmfYav0YYyUGIr+% z>L$HCKEglyz$kOiZUjy4{u#{BNjSisSXfx?ohL15|IBtbkc~-DTjagG_%MX-@(Xhq zg$qqu&G1CTtgJrhG~1GKa3sH@*H}G1bU^_@j?ZE!Qnq-#zMX0URVxGArSC8A5-*$p zIE$C(M_`hAx+)XyqAG3INrcwj8p~j(q^5R@DBM>Do#a`Z|5GqvA%W=!co+^DXTR!@ zQ-4H8Lx5draTv1XU~@bE4BS^w&E)e-A1mjI%gWfl><;TxPqd`K0om*yC!L*52+V>1 z#8`va`t$$5Pid5MDVdl~Q!ycOjykLXoB;D;!u1stU3&>yH?@!ImSd>_45_A~A}TMB z3Oqt*bd`tW19t52i$CVpZ~xy72TTqJYaQIak2lxW4aNLmteC{a_CIuibIsJkA}KMk z|L%MTpU2TKjWti$aYYVF69g>iU!BgkCFSJhBch{ScuqAc=MwYsl!0+Bh?Eow2G|&! zYWYC%xqEqpSXo;aR#(3PwmqP@JUW==tTtoyz5{kZf*2{>K7`=Dtz0lMVC=xwQrOm( z0S-WV-4^+*f`g2KK|@6qnx2jaTrqB=ADoB=dvf5;;Pu*`yehZ;=b9YHP _window_ + +[small]#Returns a _window_ handle to the newly created window.# + +[[glfw.destroy_window]] +* *glfw.destroy_window* (_window_) + +[[glfw.window_should_close]] +* *glfw.set_window_should_close* (_window_, _boolean_) + +*glfw.window_should_close* (_window_) + +-> _boolean_ + +[[glfw.set_window_title]] +* *glfw.set_window_title* (_window_, _title_) + +[[glfw.get_window_pos]] +* *glfw.set_window_pos* (_window_, _xpos_, _ypos_) + +*glfw.get_window_pos* (_window_) + +-> _xpos_, _ypos_ + +[[glfw.get_window_size]] +* *glfw.set_window_size* (_window_, _width_, _height_) + +*glfw.get_window_size* (_window_) + +-> _width_, _height_ + +[[glfw.get_framebuffer_size]] +* *glfw.get_framebuffer_size* (_window_) + +-> _width_, _height_ + +[[glfw.get_window_frame_size]] +* *glfw.get_window_frame_size* (_window_) + +-> _left_, _top_, _right_, _bottom_ + + +[[glfw.iconify_window]] +* *glfw.iconify_window* (_window_) + +*glfw.restore_window* (_window_) + +[[glfw.show_window]] +* *glfw.show_window* (_window_) + +*glfw.hide_window* (_window_) + +[[glfw.get_window_monitor]] +* *glfw.get_window_monitor* (_window_) + +-> _monitor_ (or _nil_) + +[[glfw.get_window_attribute]] +* *glfw.get_window_attribute* (_window_, _attrib_) + +-> _value_ + +[small]#_attrib_, _value_: see _target_ and _hint_ for the <>( ) function.# + +[[glfw.poll_events]] +* *glfw.poll_events* ( ) + +[[glfw.wait_events]] +* *glfw.wait_events* ( ) + +[[glfw.post_empty_event]] +* *glfw.post_empty_event* ( ) + +[[glfw.swap_buffers]] +* *glfw.swap_buffers* (_window_) + +All the following functions unregister the corresponding current callback when invoked with +_func_ = _nil_. + +[[glfw.set_window_pos_callback]] +* *glfw.set_window_pos_callback* (_window_ [, _func_]) + +[small]#The _func_ callback is executed as *_func(window, xpos, ypos)_*.# + +[[glfw.set_window_size_callback]] +* *glfw.set_window_size_callback* (_window_ [, _func_]) + +[small]#The _func_ callback is executed as *_func(window, width, height)_*.# + +[[glfw.set_window_close_callback]] +* *glfw.set_window_close_callback* (_window_ [, _func_]) + +[small]#The _func_ callback is executed as *_func(window)_*.# + +[[glfw.set_window_refresh_callback]] +* *glfw.set_window_refresh_callback* (_window_ [, _func_]) + +[small]#The _func_ callback is executed as *_func(window)_*.# + +[[glfw.set_window_focus_callback]] +* *glfw.set_window_focus_callback* (_window_ [, _func_]) + +[small]#The _func_ callback is executed as *_func(window, focused)_*, where _focused_ is a boolean.# + +[[glfw.set_window_iconify_callback]] +* *glfw.set_window_iconify_callback* (_window_ [, _func_]) + +[small]#The _func_ callback is executed as *_func(window, iconified)_*, where _iconified_ is a boolean.# + +[[glfw.set_framebuffer_size_callback]] +* *glfw.set_framebuffer_size_callback* (_window_ [, _func_]) + +[small]#The _func_ callback is executed as *_func(window, width, height)_*.# + +<<< diff --git a/examples/callbacks.lua b/examples/callbacks.lua new file mode 100644 index 0000000..82a670f --- /dev/null +++ b/examples/callbacks.lua @@ -0,0 +1,29 @@ +-- Script: callbacks.lua + +glfw = require("moonglfw") + +glfw.set_error_callback(function (ec, descr) + print("error", ec, descr) + os.exit() +end) + +w = glfw.create_window(640, 480, "Callbacks example") +glfw.set_window_pos_callback(w, function(...) print("WindowPos", table.unpack({...})) end) +glfw.set_window_size_callback(w, function(...) print("WindowSize", table.unpack({...})) end) +glfw.set_window_close_callback(w, function(...) print("WindowClose", table.unpack({...})) end) +glfw.set_window_refresh_callback(w, function(...) print("WindowRefresh", table.unpack({...})) end) +glfw.set_window_focus_callback(w, function(...) print("WindowFocus", table.unpack({...})) end) +glfw.set_window_iconify_callback(w, function(...) print("WindowIconify", table.unpack({...})) end) +glfw.set_framebuffer_size_callback(w, function(...) print("FramebufferSize", table.unpack({...})) end) +glfw.set_key_callback(w, function(...) print("Key", table.unpack({...})) end) +glfw.set_char_callback(w, function(...) print("Char", table.unpack({...})) end) +glfw.set_char_mods_callback(w, function(...) print("CharMods", table.unpack({...})) end) +glfw.set_mouse_button_callback(w, function(...) print("MouseButton", table.unpack({...})) end) +glfw.set_cursor_pos_callback(w, function(...) print("CursorPos", table.unpack({...})) end) +glfw.set_cursor_enter_callback(w, function(...) print("CursorEnter", table.unpack({...})) end) +glfw.set_scroll_callback(w, function(...) print("Scroll", table.unpack({...})) end) +glfw.set_drop_callback(w, function(...) print("Drop", table.unpack({...})) end) + +while not glfw.window_should_close(w) do + glfw.poll_events() +end diff --git a/examples/hello.lua b/examples/hello.lua new file mode 100644 index 0000000..65ddf4c --- /dev/null +++ b/examples/hello.lua @@ -0,0 +1,20 @@ +-- Script: hello.lua + +glfw = require("moonglfw") + +-- Create a window: +window = glfw.create_window(640, 480, "Hello world!") + +function my_callback(w, x, y) + assert(w == window) + print("cursor position:", x, y) +end + +-- Register a callback to track the cursor's position: +glfw.set_cursor_pos_callback(window, my_callback) + +-- Repeatedly poll for events: +while not glfw.window_should_close(window) do + glfw.poll_events() +end + diff --git a/src/Makefile b/src/Makefile new file mode 100644 index 0000000..c7806f1 --- /dev/null +++ b/src/Makefile @@ -0,0 +1,101 @@ + +# To override the defaults, do (for example): +# $ make V=5.4 +# $ make install V=5.4 PREFIX=/home/joe/local + +# Lua version: +V=5.3 +# Base install directory: +PREFIX = /usr/local +# Directory where to install Lua modules: +L_DIR = $(PREFIX)/share/lua/$(V) +# Directory where to install C modules: +C_DIR = $(PREFIX)/lib/lua/$(V) +# Directory where to install C headers: +H_DIR = $(PREFIX)/include +# Directory where to install C libraries: +S_DIR = $(PREFIX)/lib + +ifeq ("$(V)","") +$(error Missing Lua version) +endif + +ifeq ("$(PREFIX)","") +$(error Missing base install directory) +endif + +# Translates 5.3 into 503: +LUAVER=$(shell lua -e "print((string.gsub("$(V)",'%.','0')))") + +# Check the Lua version of the installed lua interpreter: +INSTLUAVER=$(shell lua -e "print(_VERSION:sub(5))") +ifneq ("$(V)","$(INSTLUAVER)") +#$(info $(V)) +$(warning Warning: using Lua $(V) but Lua interpreter version is $(INSTLUAVER)) +endif + +Tgt := moonglfw +Src := $(wildcard *.c) +Objs := $(Src:.c=.o) + +INCDIR = -I/usr/include +LIBDIR = -L/usr/lib + +LIBS := $(LIBDIR) +LIBS += -lglfw +#LIBS += -llua + +COPT += -O2 +#COPT += -O0 -g +COPT += -Wall -Wextra -Wpedantic +COPT += -fpic +COPT += -std=gnu99 +COPT += -DLUAVER=$(LUAVER) +ifeq ($(D),1) +COPT += -DDEBUG +COPT += -Wshadow -Wsign-compare -Wundef -Wwrite-strings +COPT += -Wdisabled-optimization -Wdeclaration-after-statement +COPT += -Wmissing-prototypes -Wstrict-prototypes -Wnested-externs +COPT += -Wc++-compat -Wold-style-definition +endif +COPT += $(INCDIR) + +override CFLAGS = $(COPT) $(INCDIR) + +default: build + +clean: + @-rm -f $(Tgt).so + @-rm -f $(Tgt).symbols + @-rm -f *~ + @-rm -f *.log + @-rm -f *.o *.err *.map *.S + +check: + @-echo $(Tgt)".so will be installed in "$(C_DIR) + @-echo $(Tgt)"/*.lua will be installed in "$(L_DIR)"/"$(Tgt) + @-echo $(Tgt)".h will be installed in "$(H_DIR) + @-echo lib$(Tgt)".so will be installed in "$(S_DIR) + @-echo + +install: + @-mkdir -pv $(H_DIR) + @-mkdir -pv $(C_DIR) + @-mkdir -pv $(S_DIR) + @-mkdir -pv $(L_DIR) + @-cp -fpv $(Tgt).h $(H_DIR) + @-cp -fpv $(Tgt).so $(C_DIR) + @-ln -fsv $(C_DIR)/$(Tgt).so $(S_DIR)/lib$(Tgt).so + @-cp -fpvr ../$(Tgt) $(L_DIR) + +build: clean $(Tgt) + +symbols: build + @objdump -T $(Tgt).so > $(Tgt).symbols + +$(Tgt): $(Objs) + @-$(CC) -shared -Wl,-soname,$(Tgt).so,$(LIBS) -o $(Tgt).so $(Objs) $(LIBS) +# @-$(CC) -shared -Wl,-soname,$(Tgt).so -o $(Tgt).so $(LIBS) $(Objs) + @-rm -f $(Objs) + @echo + diff --git a/src/_make b/src/_make new file mode 100755 index 0000000..51f67be --- /dev/null +++ b/src/_make @@ -0,0 +1 @@ +make D=$1 && sudo make install diff --git a/src/callbacks.c b/src/callbacks.c new file mode 100644 index 0000000..61c5e35 --- /dev/null +++ b/src/callbacks.c @@ -0,0 +1,370 @@ +/* The MIT License (MIT) + * + * Copyright (c) 2016 Stefano Trettel + * + * Software repository: MoonGLFW, https://github.com/stetre/moonglfw + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/**************************************************************************** + * Callback functions * + ****************************************************************************/ +#include "internal.h" + +static int PushMods(lua_State *L, int mods) + { + lua_pushboolean(L, mods & GLFW_MOD_SHIFT); + lua_pushboolean(L, mods & GLFW_MOD_CONTROL); + lua_pushboolean(L, mods & GLFW_MOD_ALT); + lua_pushboolean(L, mods & GLFW_MOD_SUPER); + return 4; + } + +static int MonitorId(GLFWmonitor *monitor) + { + mon_t *mon = mon_first(0); + while(mon) + { + if(mon->monitor == monitor) + return mon->id; + mon = mon_next(mon); + } + return -1; /* should not happen */ + } + + +/*--------------------------------------------------------------------------* + | Global callbacks execution | + *--------------------------------------------------------------------------*/ + +#define L moonglfw_L + +#define BEGIN(cb) /* retrieve the callback */ \ + int top = lua_gettop(L); \ +do { \ + if(lua_rawgeti(L, LUA_REGISTRYINDEX, cb) != LUA_TFUNCTION) \ + { luaL_error(L, UNEXPECTED_ERROR); return; } \ +} while(0) + +#define EXEC(nargs) do { \ + if(lua_pcall(L, (nargs), 0, 0) != LUA_OK) { lua_error(L); return; } \ + lua_settop(L, top); \ +} while(0) + +static int Error = LUA_NOREF; +static void ErrorCallback(int ec, const char* descr) + { + BEGIN(Error); + lua_pushinteger(L, ec); /* @@ farne un enum? */ + lua_pushstring(L, descr); + EXEC(2); + } + +//typedef void (* GLFWmonitorfun)(GLFWmonitor*,int); +//GLFWmonitorfun glfwSetMonitorCallback(GLFWmonitorfun cbfun); +static int Monitor = LUA_NOREF; +static void MonitorCallback(GLFWmonitor *monitor, int event) + { + BEGIN(Monitor); + lua_pushinteger(L, MonitorId(monitor)); + lua_pushstring(L, event==GLFW_CONNECTED ? "connected" : "disconnected"); + EXEC(2); + /* always call the default callback: */ + monitorCallback(monitor, event); + } + +#undef BEGIN +#undef EXEC +#undef L + +/*--------------------------------------------------------------------------* + | Global callbacks registration | + *--------------------------------------------------------------------------*/ + +#define REGISTER_FUNC(cb, func_index, defaultcb) \ +static int Set##cb##Callback(lua_State *L) \ + { \ + if(cb != LUA_NOREF) \ + { luaL_unref(L, LUA_REGISTRYINDEX, cb); cb = LUA_NOREF; } \ + if(lua_isnoneornil(L, func_index)) \ + { glfwSet##cb##Callback(defaultcb); return 0; } \ + if(!lua_isfunction(L, func_index)) \ + return luaL_argerror(L, func_index, "function expected"); \ + lua_pushvalue(L, func_index); \ + cb = luaL_ref(L, LUA_REGISTRYINDEX); \ + glfwSet##cb##Callback(cb##Callback); \ + return 0; \ + } + +REGISTER_FUNC(Error, 1, errorCallback) +REGISTER_FUNC(Monitor, 1, monitorCallback) + +#undef REGISTER_FUNC + +/*--------------------------------------------------------------------------* + | Window-specific callbacks execution | + *--------------------------------------------------------------------------*/ + +#define L moonglfw_L + +#define BEGIN(cb) /* retrieve the callback */ \ + int top = lua_gettop(L); \ +do { \ + int id = (intptr_t)glfwGetWindowUserPointer(window); \ + win_t *win = win_search(id); \ + if((!win) || (lua_rawgeti(L, LUA_REGISTRYINDEX, win->cb) != LUA_TFUNCTION)) \ + { unexpected(L); return; } \ + lua_pushinteger(L, id); \ +} while(0) + +#define EXEC(nargs) do { \ + if(lua_pcall(L, (nargs) + 1, 0, 0) != LUA_OK) { lua_error(L); return; } \ + lua_settop(L, top); \ +} while(0) + +#define RETURN do { \ + lua_settop(L, top); return; \ +} while(0) + +static void WindowPosCallback(GLFWwindow *window, int xpos, int ypos) + { + BEGIN(WindowPos); + lua_pushinteger(L, xpos); + lua_pushinteger(L, ypos); + EXEC(2); + } + +static void WindowSizeCallback(GLFWwindow *window, int width, int height) + { + BEGIN(WindowSize); + lua_pushinteger(L, width); + lua_pushinteger(L, height); + EXEC(2); + } + +static void WindowCloseCallback(GLFWwindow *window) + { + BEGIN(WindowClose); + EXEC(0); + } + +static void WindowRefreshCallback(GLFWwindow *window) + { + BEGIN(WindowRefresh); + EXEC(0); + } + +static void WindowFocusCallback(GLFWwindow *window, int focused) + { + BEGIN(WindowFocus); + lua_pushboolean(L, focused); + EXEC(1); + } + +static void WindowIconifyCallback(GLFWwindow *window, int iconified) + { + BEGIN(WindowIconify); + lua_pushboolean(L, iconified); + EXEC(1); + } + + +static void FramebufferSizeCallback(GLFWwindow *window, int width, int height) + { + BEGIN(FramebufferSize); + lua_pushinteger(L, width); + lua_pushinteger(L, height); + EXEC(2); + } + +//typedef void (* GLFWkeyfun)(GLFWwindow*,int,int,int,int); +//GLFWkeyfun glfwSetKeyCallback(GLFWwindow* window, GLFWkeyfun cbfun); +static void KeyCallback(GLFWwindow *window, int key, int scancode, int action, int mods) + { + int n = 3; + BEGIN(Key); + enumPush(L, key, enumKey()); + lua_pushinteger(L, scancode); + enumPush(L, action, enumAction()); + n += PushMods(L, mods); + EXEC(n); + } + + +//typedef void (* GLFWcharfun)(GLFWwindow*,unsigned int); +//GLFWcharfun glfwSetCharCallback(GLFWwindow* window, GLFWcharfun cbfun); +static void CharCallback(GLFWwindow *window, unsigned int codepoint) + { + BEGIN(Char); + lua_pushinteger(L, codepoint); + EXEC(1); + } + + +//typedef void (* GLFWcharmodsfun)(GLFWwindow*,unsigned int,int); +//GLFWcharmodsfun glfwSetCharModsCallback(GLFWwindow* window, GLFWcharmodsfun cbfun); +static void CharModsCallback(GLFWwindow *window, unsigned int codepoint, int mods) + { + int n = 1; + BEGIN(CharMods); + lua_pushinteger(L, codepoint); + n += PushMods(L, mods); + EXEC(n); + } + + +//typedef void (* GLFWmousebuttonfun)(GLFWwindow*,int,int,int); +//GLFWmousebuttonfun glfwSetMouseButtonCallback(GLFWwindow* window, GLFWmousebuttonfun cbfun); +static void MouseButtonCallback(GLFWwindow *window, int button, int action, int mods) + { + int n = 2; + BEGIN(MouseButton); + enumPush(L, button, enumButton()); + enumPush(L, action, enumAction()); + n += PushMods(L, mods); + EXEC(n); + } + + +//typedef void (* GLFWcursorposfun)(GLFWwindow*,double,double); +//GLFWcursorposfun glfwSetCursorPosCallback(GLFWwindow* window, GLFWcursorposfun cbfun); +static void CursorPosCallback(GLFWwindow *window, double xpos, double ypos) + { + BEGIN(CursorPos); + lua_pushnumber(L, xpos); + lua_pushnumber(L, ypos); + EXEC(2); + } + + +//typedef void (* GLFWcursorenterfun)(GLFWwindow*,int); +//GLFWcursorenterfun glfwSetCursorEnterCallback(GLFWwindow* window, GLFWcursorenterfun cbfun); +static void CursorEnterCallback(GLFWwindow *window, int entered) + { + BEGIN(CursorEnter); + lua_pushboolean(L, entered); + EXEC(1); + } + + +//typedef void (* GLFWscrollfun)(GLFWwindow*,double,double); +//GLFWscrollfun glfwSetScrollCallback(GLFWwindow* window, GLFWscrollfun cbfun); +static void ScrollCallback(GLFWwindow *window, double xoffset, double yoffset) + { + BEGIN(Scroll); + lua_pushnumber(L, xoffset); + lua_pushnumber(L, yoffset); + EXEC(2); + } + + +//typedef void (* GLFWdropfun)(GLFWwindow*,int,const char**); +//GLFWdropfun glfwSetDropCallback(GLFWwindow* window, GLFWdropfun cbfun); +static void DropCallback(GLFWwindow *window, int count, const char** paths) + { + int i; + BEGIN(Drop); + for(i = 0; icb == LUA_NOREF) return 0; /* nothing to do */ \ + CALLBACK_UNREF(win->cb); \ + glfwSet##cb##Callback(win->window, NULL); \ + return 0; \ + } \ + if(!lua_isfunction(L, 2)) \ + return luaL_argerror(L, 2, "function expected");\ + if(win->cb != LUA_NOREF) \ + luaL_unref(L, LUA_REGISTRYINDEX, win->cb); \ + lua_pushvalue(L, 2); \ + win->cb = luaL_ref(L, LUA_REGISTRYINDEX); \ + glfwSet##cb##Callback(win->window, cb##Callback); \ + return 0; \ + } + +REGISTER_FUNC(WindowPos) +REGISTER_FUNC(WindowSize) +REGISTER_FUNC(WindowClose) +REGISTER_FUNC(WindowRefresh) +REGISTER_FUNC(WindowFocus) +REGISTER_FUNC(WindowIconify) +REGISTER_FUNC(FramebufferSize) +REGISTER_FUNC(Key) +REGISTER_FUNC(Char) +REGISTER_FUNC(CharMods) +REGISTER_FUNC(MouseButton) +REGISTER_FUNC(CursorPos) +REGISTER_FUNC(CursorEnter) +REGISTER_FUNC(Scroll) +REGISTER_FUNC(Drop) + +#undef REGISTER_FUNC + +/*--------------------------------------------------------------------------* + | Functions registration | + *--------------------------------------------------------------------------*/ + +static const struct luaL_Reg Functions[] = + { + /* global */ + { "set_error_callback", SetErrorCallback }, + /* window specific */ + { "set_window_pos_callback", SetWindowPosCallback }, + { "set_window_size_callback", SetWindowSizeCallback }, + { "set_window_close_callback", SetWindowCloseCallback }, + { "set_window_refresh_callback", SetWindowRefreshCallback }, + { "set_window_focus_callback", SetWindowFocusCallback }, + { "set_window_iconify_callback", SetWindowIconifyCallback }, + { "set_framebuffer_size_callback", SetFramebufferSizeCallback }, + { "set_key_callback", SetKeyCallback }, + { "set_char_callback", SetCharCallback }, + { "set_char_mods_callback", SetCharModsCallback }, + { "set_mouse_button_callback", SetMouseButtonCallback }, + { "set_cursor_pos_callback", SetCursorPosCallback }, + { "set_cursor_enter_callback", SetCursorEnterCallback }, + { "set_scroll_callback", SetScrollCallback }, + { "set_drop_callback", SetDropCallback }, + { "set_monitor_callback", SetMonitorCallback }, + { NULL, NULL } /* sentinel */ + }; + +void moonglfw_open_callbacks(lua_State *L) + { + luaL_setfuncs(L, Functions, 0); + } + + diff --git a/src/context.c b/src/context.c new file mode 100644 index 0000000..0966e36 --- /dev/null +++ b/src/context.c @@ -0,0 +1,86 @@ +/* The MIT License (MIT) + * + * Copyright (c) 2016 Stefano Trettel + * + * Software repository: MoonGLFW, https://github.com/stetre/moonglfw + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "internal.h" + + +static int MakeContextCurrent(lua_State *L) + { + win_t * win = checkwindow(L, 1); + glfwMakeContextCurrent(win->window); + return 0; + } + +static int GetCurrentContext(lua_State *L) + { + GLFWwindow* window = glfwGetCurrentContext(); + lua_pushinteger(L, (intptr_t)glfwGetWindowUserPointer(window)); + return 1; + } + +static int SwapInterval(lua_State *L) + { + int interval = luaL_checkinteger(L, 1); + glfwSwapInterval(interval); + return 0; + } + +static int ExtensionSupported(lua_State *L) + { + const char* extension = luaL_checkstring(L, 1); + lua_pushboolean(L, glfwExtensionSupported(extension)); + return 1; + } + +#if 0 + { "get_proc_address", GetProcAddress }, +static int GetProcAddress(lua_State *L) //@@ + { +//GLFWglproc glfwGetProcAddress(const char* procname); + (void)L; + return 0; + } +#endif + + +/*------------------------------------------------------------------------------* + | Registration | + *------------------------------------------------------------------------------*/ + + +static const struct luaL_Reg Functions[] = + { + { "make_context_current", MakeContextCurrent }, + { "get_current_context", GetCurrentContext }, + { "swap_interval", SwapInterval }, + { "extension_supported", ExtensionSupported }, + { NULL, NULL } /* sentinel */ + }; + +void moonglfw_open_context(lua_State *L) + { + luaL_setfuncs(L, Functions, 0); + } + diff --git a/src/cur.c b/src/cur.c new file mode 100644 index 0000000..9813a97 --- /dev/null +++ b/src/cur.c @@ -0,0 +1,100 @@ +/* The MIT License (MIT) + * + * Copyright (c) 2016 Stefano Trettel + * + * Software repository: MoonGLFW, https://github.com/stetre/moonglfw + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "internal.h" + +static int cmp(cur_t *cur1, cur_t *cur2) /* the compare function */ + { return (cur1->id < cur2->id ? -1 : cur1->id > cur2->id); } + +static RB_HEAD(curtree_s, cur_s) Head = RB_INITIALIZER(&Head); + +RB_PROTOTYPE_STATIC(curtree_s, cur_s, entry, cmp) +RB_GENERATE_STATIC(curtree_s, cur_s, entry, cmp) + +static cur_t *cur_remove(cur_t *cur) + { return RB_REMOVE(curtree_s, &Head, cur); } +static cur_t *cur_insert(cur_t *cur) + { return RB_INSERT(curtree_s, &Head, cur); } +cur_t *cur_search(int id) + { cur_t tmp; tmp.id = id; return RB_FIND(curtree_s, &Head, &tmp); } +cur_t *cur_first(int id) + { cur_t tmp; tmp.id = id; return RB_NFIND(curtree_s, &Head, &tmp); } +cur_t *cur_next(cur_t *cur) + { return RB_NEXT(curtree_s, &Head, cur); } +#if 0 +cur_t *cur_prev(cur_t *cur) + { return RB_PREV(curtree_s, &Head, cur); } +cur_t *cur_min(void) + { return RB_MIN(curtree_s, &Head); } +cur_t *cur_max(void) + { return RB_MAX(curtree_s, &Head); } +cur_t *cur_root(void) + { return RB_ROOT(&Head); } +#endif +cur_t *cur_new(void) + { + cur_t *cur; + int id = id_new(); + if(id == -1) + return NULL; + if((cur = (cur_t*)malloc(sizeof(cur_t))) == NULL) + { id_free(id); return NULL; } + memset(cur, 0, sizeof(cur_t)); + cur->id = id; + if(cur_search(cur->id)) + { free(cur); id_free(id); return NULL; } + //cur->Zzz = LUA_NOREF; + cur_insert(cur); + return cur; + } + +void cur_free(cur_t* cur) + { + if(cur_search(cur->id) == cur) + { + /* release callback references */ + //CALLBACK_UNREF(cur->Zzz); + cur_remove(cur); + } + id_free(cur->id); + free(cur); + } + +void cur_free_all(void) + { + cur_t *cur; + while((cur = cur_first(0))) + cur_free(cur); + } + +cur_t* cur_check(lua_State *L, int arg) + { + int id = luaL_checkinteger(L, arg); + cur_t *cur = cur_search(id); + if(!cur) + luaL_error(L, "invalid cursor id"); + return cur; + } + diff --git a/src/enum.c b/src/enum.c new file mode 100644 index 0000000..33dc32e --- /dev/null +++ b/src/enum.c @@ -0,0 +1,379 @@ +/* The MIT License (MIT) + * + * Copyright (c) 2016 Stefano Trettel + * + * Software repository: MoonGLFW, https://github.com/stetre/moonglfw + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "internal.h" + +int enumCheck(lua_State *L, int arg, enum_t *e) + { return e->codes[checkoption(L, arg, NULL, e->strings)]; } + +int enumPush(lua_State *L, int code, enum_t *e) + { + size_t i; + for(i = 0; i < e->n; i++) + { if(e->codes[i]==code) + { + lua_pushstring(L, e->strings[i]); + return 1; + } + } + //return luaL_error(L, "invalid enum value %d", code); + lua_pushfstring(L, "%d???", code); + return 1; + } + +const char* enumToString(int code, enum_t *e) + { + size_t i; + for(i = 0; i < e->n; i++) + if(e->codes[i]==code) return e->strings[i]; + return NULL; + } + +int enumAssert(lua_State *L, enum_t *e, int code, const char *string) + { + const char *s = enumToString(code, e); + if( (s==NULL) || (strcmp(s, string) !=0)) + return unexpected(L); + return 0; + } + +int enumOrUint(lua_State *L, int arg, int *dst, enum_t *e, int def) +/* The element at the index arg on the Lua stack may be an enum (string), + * or an integer. In the first case the enum code is stored in 'code' and + * 'def' is returned. In the second case the integer value is returned. + */ + { + if(lua_isstring(L, arg)) + { + *dst = enumCheck(L, arg, e); + return def; + } + return (int)luaL_checkinteger(L, arg); + } + + + +ENUM_STRINGS(ActionStrings) = { + "press", + "repeat", + "release", + NULL +}; +ENUM_CODES(ActionCodes) = { + GLFW_PRESS, + GLFW_REPEAT, + GLFW_RELEASE, +}; +ENUM_T(ActionEnum, ActionStrings, ActionCodes) +#define CheckAction(L, arg) enumCheck((L), (arg), &ActionEnum) +#define PushAction(L, code) enumPush((L), (code), &ActionEnum) + +enum_t *enumAction(void) + { return &ActionEnum; } + +ENUM_STRINGS(ButtonStrings) = { + "left", + "right", + "middle", + "button 4", + "button 5", + "button 6", + "button 7", + "button 8", + NULL +}; +ENUM_CODES(ButtonCodes) = { + GLFW_MOUSE_BUTTON_1, + GLFW_MOUSE_BUTTON_2, + GLFW_MOUSE_BUTTON_3, + GLFW_MOUSE_BUTTON_4, + GLFW_MOUSE_BUTTON_5, + GLFW_MOUSE_BUTTON_6, + GLFW_MOUSE_BUTTON_7, + GLFW_MOUSE_BUTTON_8, +}; +ENUM_T(ButtonEnum, ButtonStrings, ButtonCodes) +#define CheckButton(L, arg) enumCheck((L), (arg), &ButtonEnum) +#define PushButton(L, code) enumPush((L), (code), &ButtonEnum) + +enum_t *enumButton(void) + { return &ButtonEnum; } + + +ENUM_STRINGS(KeyStrings) = { + "unknown", + "space", + "apostrophe", + "comma", + "minus", + "period", + "slash", + "0", + "1", + "2", + "3", + "4", + "5", + "6", + "7", + "8", + "9", + "semicolon", + "equal", + "a", + "b", + "c", + "d", + "e", + "f", + "g", + "h", + "i", + "j", + "k", + "l", + "m", + "n", + "o", + "p", + "q", + "r", + "s", + "t", + "u", + "v", + "w", + "x", + "y", + "z", + "left bracket", + "backslash", + "right bracket", + "grave accent", + "world 1", + "world 2", + "escape", + "enter", + "tab", + "backspace", + "insert", + "delete", + "right", + "left", + "down", + "up", + "page up", + "page down", + "home", + "end", + "caps lock", + "scroll lock", + "num lock", + "print screen", + "pause", + "f1", + "f2", + "f3", + "f4", + "f5", + "f6", + "f7", + "f8", + "f9", + "f10", + "f11", + "f12", + "f13", + "f14", + "f15", + "f16", + "f17", + "f18", + "f19", + "f20", + "f21", + "f22", + "f23", + "f24", + "f25", + "kp 0", + "kp 1", + "kp 2", + "kp 3", + "kp 4", + "kp 5", + "kp 6", + "kp 7", + "kp 8", + "kp 9", + "kp decimal", + "kp divide", + "kp multiply", + "kp subtract", + "kp add", + "kp enter", + "kp equal", + "left shift", + "left control", + "left alt", + "left super", + "right shift", + "right control", + "right alt", + "right super", + "menu", + NULL +}; +ENUM_CODES(KeyCodes) = { + GLFW_KEY_UNKNOWN, + GLFW_KEY_SPACE, + GLFW_KEY_APOSTROPHE, + GLFW_KEY_COMMA, + GLFW_KEY_MINUS, + GLFW_KEY_PERIOD, + GLFW_KEY_SLASH, + GLFW_KEY_0, + GLFW_KEY_1, + GLFW_KEY_2, + GLFW_KEY_3, + GLFW_KEY_4, + GLFW_KEY_5, + GLFW_KEY_6, + GLFW_KEY_7, + GLFW_KEY_8, + GLFW_KEY_9, + GLFW_KEY_SEMICOLON, + GLFW_KEY_EQUAL, + GLFW_KEY_A, + GLFW_KEY_B, + GLFW_KEY_C, + GLFW_KEY_D, + GLFW_KEY_E, + GLFW_KEY_F, + GLFW_KEY_G, + GLFW_KEY_H, + GLFW_KEY_I, + GLFW_KEY_J, + GLFW_KEY_K, + GLFW_KEY_L, + GLFW_KEY_M, + GLFW_KEY_N, + GLFW_KEY_O, + GLFW_KEY_P, + GLFW_KEY_Q, + GLFW_KEY_R, + GLFW_KEY_S, + GLFW_KEY_T, + GLFW_KEY_U, + GLFW_KEY_V, + GLFW_KEY_W, + GLFW_KEY_X, + GLFW_KEY_Y, + GLFW_KEY_Z, + GLFW_KEY_LEFT_BRACKET, + GLFW_KEY_BACKSLASH, + GLFW_KEY_RIGHT_BRACKET, + GLFW_KEY_GRAVE_ACCENT, + GLFW_KEY_WORLD_1, + GLFW_KEY_WORLD_2, + GLFW_KEY_ESCAPE, + GLFW_KEY_ENTER, + GLFW_KEY_TAB, + GLFW_KEY_BACKSPACE, + GLFW_KEY_INSERT, + GLFW_KEY_DELETE, + GLFW_KEY_RIGHT, + GLFW_KEY_LEFT, + GLFW_KEY_DOWN, + GLFW_KEY_UP, + GLFW_KEY_PAGE_UP, + GLFW_KEY_PAGE_DOWN, + GLFW_KEY_HOME, + GLFW_KEY_END, + GLFW_KEY_CAPS_LOCK, + GLFW_KEY_SCROLL_LOCK, + GLFW_KEY_NUM_LOCK, + GLFW_KEY_PRINT_SCREEN, + GLFW_KEY_PAUSE, + GLFW_KEY_F1, + GLFW_KEY_F2, + GLFW_KEY_F3, + GLFW_KEY_F4, + GLFW_KEY_F5, + GLFW_KEY_F6, + GLFW_KEY_F7, + GLFW_KEY_F8, + GLFW_KEY_F9, + GLFW_KEY_F10, + GLFW_KEY_F11, + GLFW_KEY_F12, + GLFW_KEY_F13, + GLFW_KEY_F14, + GLFW_KEY_F15, + GLFW_KEY_F16, + GLFW_KEY_F17, + GLFW_KEY_F18, + GLFW_KEY_F19, + GLFW_KEY_F20, + GLFW_KEY_F21, + GLFW_KEY_F22, + GLFW_KEY_F23, + GLFW_KEY_F24, + GLFW_KEY_F25, + GLFW_KEY_KP_0, + GLFW_KEY_KP_1, + GLFW_KEY_KP_2, + GLFW_KEY_KP_3, + GLFW_KEY_KP_4, + GLFW_KEY_KP_5, + GLFW_KEY_KP_6, + GLFW_KEY_KP_7, + GLFW_KEY_KP_8, + GLFW_KEY_KP_9, + GLFW_KEY_KP_DECIMAL, + GLFW_KEY_KP_DIVIDE, + GLFW_KEY_KP_MULTIPLY, + GLFW_KEY_KP_SUBTRACT, + GLFW_KEY_KP_ADD, + GLFW_KEY_KP_ENTER, + GLFW_KEY_KP_EQUAL, + GLFW_KEY_LEFT_SHIFT, + GLFW_KEY_LEFT_CONTROL, + GLFW_KEY_LEFT_ALT, + GLFW_KEY_LEFT_SUPER, + GLFW_KEY_RIGHT_SHIFT, + GLFW_KEY_RIGHT_CONTROL, + GLFW_KEY_RIGHT_ALT, + GLFW_KEY_RIGHT_SUPER, + GLFW_KEY_MENU, +}; +ENUM_T(KeyEnum, KeyStrings, KeyCodes) +#define CheckKey(L, arg) enumCheck((L), (arg), &KeyEnum) +#define PushKey(L, code) enumPush((L), (code), &KeyEnum) + +enum_t *enumKey(void) + { return &KeyEnum; } + + diff --git a/src/enum.h b/src/enum.h new file mode 100644 index 0000000..3f659f3 --- /dev/null +++ b/src/enum.h @@ -0,0 +1,105 @@ +/* The MIT License (MIT) + * + * Copyright (c) 2016 Stefano Trettel + * + * Software repository: MoonGLFW, https://github.com/stetre/moonglfw + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef enumDEFINED +#define enumDEFINED + +/*--------------------------------------------------------------------------* + | int <-> string mappings | + *--------------------------------------------------------------------------*/ + +#define enum_t moonglfw_enum_t +typedef struct { + const char **strings; + int *codes; + size_t n; +} enum_t; + +#define enumCheck moonglfw_enumCheck +int enumCheck(lua_State *L, int arg, enum_t *e); +#define enumPush moonglfw_enumPush +int enumPush(lua_State *L, int code, enum_t *e); +#define enumToString moonglfw_enumToString +const char* enumToString(int code, enum_t *e); +#define enumAssert moonglfw_enumAssert +int enumAssert(lua_State *L, enum_t *e, int code, const char *string); +#define enumOrUint moonglfw_enumOrUint +int enumOrUint(lua_State *L, int arg, int *dst, enum_t *e, int def); + +#define ENUM_STRINGS(strings) static const char* (strings) [] +#define ENUM_CODES(codes) static int (codes) [] +#define ENUM_T(name, strings, codes) \ + static enum_t name = { (strings), (codes), sizeof((codes))/sizeof(int) }; + +#define enumButton moonglfw_enumButton +enum_t *enumButton(void); +#define enumAction moonglfw_enumAction +enum_t *enumAction(void); +#define enumKey moonglfw_enumKey +enum_t *enumKey(void); + +#if 0 +#define enumZzz moonglfw_enumZzz +enum_t *enumZzz(void); +enum_t *enumZzz(void) + { return &ZzzEnum; } + + +#define moonglfw_ +#endif + +#if 0 /* @@ 11yy */ +ENUM_STRINGS(ZzzStrings) = { + "", + NULL +}; +ENUM_CODES(ZzzCodes) = { + GLFW_, +}; +ENUM_T(ZzzEnum, ZzzStrings, ZzzCodes) +#define CheckZzz(L, arg) enumCheck((L), (arg), &ZzzEnum) +#define PushZzz(L, code) enumPush((L), (code), &ZzzEnum) + +#define enumZzz moonglfw_enumZzz +enum_t *enumZzz(void); +enum_t *enumZzz(void) + { return &ZzzEnum; } + + +#define ToStringZzz(code) enumToString((code), &ZzzEnum) + +#define CheckZzzOrNnn(L, arg, dst) enumOrUint((L), (arg), (dst), &ZzzEnum, 0) + +enum_t *enumZzz(void) + { return &ZzzEnum; } + +#define ZzzEnum yyyZzz() +#define CheckZzz(L, arg) enumCheck((L), (arg), ZzzEnum) +#define PushZzz(L, code) enumPush((L), (code), ZzzEnum) +#define ToStringZzz(code) enumToString((code), ZzzEnum) + +#endif + +#endif /* enumDEFINED */ diff --git a/src/hint.c b/src/hint.c new file mode 100644 index 0000000..47dc1f7 --- /dev/null +++ b/src/hint.c @@ -0,0 +1,334 @@ +/* The MIT License (MIT) + * + * Copyright (c) 2016 Stefano Trettel + * + * Software repository: MoonGLFW, https://github.com/stetre/moonglfw + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "internal.h" + + +ENUM_STRINGS(TargetStrings) = { + "resizable", + "visible", + "decorated", + "focused", + "auto iconify", + "floating", + "red bits", + "green bits", + "blue bits", + "alpha bits", + "depth bits", + "stencil bits", + "accum red bits", + "accum green bits", + "accum blue bits", + "accum alpha bits", + "aux buffers", + "samples", + "refresh rate", + "stereo", + "srgb capable", + "doublebuffer", + "client api", + "context version major", + "context version minor", + "context robustness", + "context release behavior", + "opengl forward compat", + "opengl debug context", + "opengl profile", + /* attribute only */ + "iconified", + "context revision", + NULL +}; +ENUM_CODES(TargetCodes) = { + GLFW_RESIZABLE, + GLFW_VISIBLE, + GLFW_DECORATED, + GLFW_FOCUSED, + GLFW_AUTO_ICONIFY, + GLFW_FLOATING, + GLFW_RED_BITS, + GLFW_GREEN_BITS, + GLFW_BLUE_BITS, + GLFW_ALPHA_BITS, + GLFW_DEPTH_BITS, + GLFW_STENCIL_BITS, + GLFW_ACCUM_RED_BITS, + GLFW_ACCUM_GREEN_BITS, + GLFW_ACCUM_BLUE_BITS, + GLFW_ACCUM_ALPHA_BITS, + GLFW_AUX_BUFFERS, + GLFW_SAMPLES, + GLFW_REFRESH_RATE, + GLFW_STEREO, + GLFW_SRGB_CAPABLE, + GLFW_DOUBLEBUFFER, + GLFW_CLIENT_API, + GLFW_CONTEXT_VERSION_MAJOR, + GLFW_CONTEXT_VERSION_MINOR, + GLFW_CONTEXT_ROBUSTNESS, + GLFW_CONTEXT_RELEASE_BEHAVIOR, + GLFW_OPENGL_FORWARD_COMPAT, + GLFW_OPENGL_DEBUG_CONTEXT, + GLFW_OPENGL_PROFILE, + /* attribute only */ + GLFW_ICONIFIED, + GLFW_CONTEXT_REVISION, +}; +ENUM_T(TargetEnum, TargetStrings, TargetCodes) +#define CheckTarget(L, arg) enumCheck((L), (arg), &TargetEnum) +#define PushTarget(L, code) enumPush((L), (code), &TargetEnum) +#define CheckAttrib CheckTarget + + +ENUM_STRINGS(ApiStrings) = { + "opengl", + "opengl es", + NULL +}; +ENUM_CODES(ApiCodes) = { + GLFW_OPENGL_API, + GLFW_OPENGL_ES_API, +}; +ENUM_T(ApiEnum, ApiStrings, ApiCodes) +#define CheckApi(L, arg) enumCheck((L), (arg), &ApiEnum) +#define PushApi(L, code) enumPush((L), (code), &ApiEnum) + + +ENUM_STRINGS(RobustnessStrings) = { + "no robustness", + "no reset notification", + "lose context on reset", + NULL +}; +ENUM_CODES(RobustnessCodes) = { + GLFW_NO_ROBUSTNESS, + GLFW_NO_RESET_NOTIFICATION, + GLFW_LOSE_CONTEXT_ON_RESET, +}; +ENUM_T(RobustnessEnum, RobustnessStrings, RobustnessCodes) +#define CheckRobustness(L, arg) enumCheck((L), (arg), &RobustnessEnum) +#define PushRobustness(L, code) enumPush((L), (code), &RobustnessEnum) + + +ENUM_STRINGS(ReleaseBehaviorStrings) = { + "any", + "flush", + "none", + NULL +}; +ENUM_CODES(ReleaseBehaviorCodes) = { + GLFW_ANY_RELEASE_BEHAVIOR, + GLFW_RELEASE_BEHAVIOR_FLUSH, + GLFW_RELEASE_BEHAVIOR_NONE, +}; +ENUM_T(ReleaseBehaviorEnum, ReleaseBehaviorStrings, ReleaseBehaviorCodes) +#define CheckReleaseBehavior(L, arg) enumCheck((L), (arg), &ReleaseBehaviorEnum) +#define PushReleaseBehavior(L, code) enumPush((L), (code), &ReleaseBehaviorEnum) + +ENUM_STRINGS(ProfileStrings) = { + "any", + "core", + "compat", + NULL +}; +ENUM_CODES(ProfileCodes) = { + GLFW_OPENGL_ANY_PROFILE, + GLFW_OPENGL_CORE_PROFILE, + GLFW_OPENGL_COMPAT_PROFILE, +}; +ENUM_T(ProfileEnum, ProfileStrings, ProfileCodes) +#define CheckProfile(L, arg) enumCheck((L), (arg), &ProfileEnum) +#define PushProfile(L, code) enumPush((L), (code), &ProfileEnum) + + +/*------------------------------------------------------------------------------* + | Hints | + *------------------------------------------------------------------------------*/ + +static int DefaultWindowHints(lua_State *L) + { + (void)L; + glfwDefaultWindowHints(); + return 0; + } + +static int Boolean(lua_State *L, int target) + { + int hint = checkboolean(L, 2); + glfwWindowHint( target, hint); + return 0; + } + +static int Enum(lua_State *L, int target, enum_t *e) + { + int hint = enumCheck(L, 2, e); + glfwWindowHint( target, hint); + return 0; + } + + +static int Integer(lua_State *L, int target) + { + int hint = GLFW_DONT_CARE; + const char *s; + if(lua_isstring(L, 2)) + { + s = lua_tostring(L, 2); + if(strncmp(s, "don't care", strlen(s)) != 0) + return luaL_argerror(L, 2, "expected integer or \"don't care\""); + } + else + { + hint = luaL_checkinteger(L, 2); +#if 0 + if(hint < -1) + return luaL_argerror(L, 2, "invalid value"); +#endif + } + glfwWindowHint( target, hint); + return 0; + } + + +static int WindowHint(lua_State *L) + { + int target = CheckTarget(L, 1); + switch(target) + { + case GLFW_RESIZABLE: + case GLFW_VISIBLE: + case GLFW_DECORATED: + case GLFW_FOCUSED: + case GLFW_AUTO_ICONIFY: + case GLFW_FLOATING: return Boolean(L, target); + case GLFW_RED_BITS: + case GLFW_GREEN_BITS: + case GLFW_BLUE_BITS: + case GLFW_ALPHA_BITS: + case GLFW_DEPTH_BITS: + case GLFW_STENCIL_BITS: + case GLFW_ACCUM_RED_BITS: + case GLFW_ACCUM_GREEN_BITS: + case GLFW_ACCUM_BLUE_BITS: + case GLFW_ACCUM_ALPHA_BITS: + case GLFW_AUX_BUFFERS: + case GLFW_SAMPLES: + case GLFW_REFRESH_RATE: return Integer(L, target); + case GLFW_STEREO: + case GLFW_SRGB_CAPABLE: + case GLFW_DOUBLEBUFFER: return Boolean(L, target); + case GLFW_CLIENT_API: return Enum(L, target, &ApiEnum); + case GLFW_CONTEXT_VERSION_MAJOR: + case GLFW_CONTEXT_VERSION_MINOR: return Integer(L, target); + case GLFW_CONTEXT_ROBUSTNESS: return Enum(L, target, &RobustnessEnum); + case GLFW_CONTEXT_RELEASE_BEHAVIOR: return Enum(L, target, &ReleaseBehaviorEnum); + case GLFW_OPENGL_FORWARD_COMPAT: + case GLFW_OPENGL_DEBUG_CONTEXT: return Boolean(L, target); + case GLFW_OPENGL_PROFILE: return Enum(L, target, &ProfileEnum); + default: + return luaL_error(L, "invalid target '%s'", lua_tostring(L, 1)); + } + return 0; + } + + +/*------------------------------------------------------------------------------* + | Get window attributes | + *------------------------------------------------------------------------------*/ + +static int GetInt_(lua_State *L, GLFWwindow* window, int attrib, int boolean) +#define GetInteger(L, w, a) GetInt_((L), (w), (a), 0) +#define GetBoolean(L, w, a) GetInt_((L), (w), (a), 1) + { + int val = glfwGetWindowAttrib(window, attrib); + if(boolean) + lua_pushboolean(L, val); + else + lua_pushinteger(L, val); + return 1; + } + +static int GetEnum(lua_State *L, GLFWwindow* window, int attrib, enum_t *e) + { + int val = glfwGetWindowAttrib(window, attrib); + enumPush(L, val, e); + return 1; + } + + +static int GetWindowAttrib(lua_State *L) + { + win_t *win = checkwindow(L, 1); + int attrib = CheckAttrib(L, 2); + + switch(attrib) + { + case GLFW_FOCUSED: + case GLFW_ICONIFIED: + case GLFW_VISIBLE: + case GLFW_RESIZABLE: + case GLFW_DECORATED: + case GLFW_FLOATING: + return GetBoolean(L, win->window, attrib); + case GLFW_CLIENT_API: + return GetEnum(L, win->window, attrib, &ApiEnum); + case GLFW_CONTEXT_VERSION_MAJOR: + case GLFW_CONTEXT_VERSION_MINOR: + case GLFW_CONTEXT_REVISION: + return GetInteger(L, win->window, attrib); + case GLFW_OPENGL_FORWARD_COMPAT: + case GLFW_OPENGL_DEBUG_CONTEXT: + return GetBoolean(L, win->window, attrib); + case GLFW_OPENGL_PROFILE: + return GetEnum(L, win->window, attrib, &ProfileEnum); + case GLFW_CONTEXT_ROBUSTNESS: + return GetEnum(L, win->window, attrib, &RobustnessEnum); + case GLFW_CONTEXT_RELEASE_BEHAVIOR: + return GetEnum(L, win->window, attrib, &ReleaseBehaviorEnum); + default: + return luaL_error(L, "invalid attribute '%s'", lua_tostring(L, 2)); + } + return 0; + } + + +/*------------------------------------------------------------------------------* + | Registration | + *------------------------------------------------------------------------------*/ + +static const struct luaL_Reg Functions[] = + { + { "default_window_hints", DefaultWindowHints }, + { "window_hint", WindowHint }, + { "get_window_attrib", GetWindowAttrib }, + { NULL, NULL } /* sentinel */ + }; + +void moonglfw_open_hint(lua_State *L) + { + luaL_setfuncs(L, Functions, 0); + } + diff --git a/src/id.c b/src/id.c new file mode 100644 index 0000000..80ca095 --- /dev/null +++ b/src/id.c @@ -0,0 +1,114 @@ +/* The MIT License (MIT) + * + * Copyright (c) 2016 Stefano Trettel + * + * Software repository: MoonGLFW, https://github.com/stetre/moonglfw + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + +/**************************************************************************** + * Id reservation * + ****************************************************************************/ + +#include "internal.h" + +static id_t *id_search(int key); + +static int key_new(void) +/* returns a free key or -1 if none are found (unlikely) */ + { + static int keyfree = 0; + int guard = keyfree-1; + if((keyfree==-1)||(keyfree==0)||(keyfree==1)) + { keyfree=1; guard=-1; } + while(1) + { + if(keyfree==guard) /* we made a complete round */ + return -1; + if(keyfree==-1) keyfree=1; + if(id_search(keyfree)==NULL) return keyfree++; + keyfree++; + } + return -1; + } + +static int cmp(id_t *id1, id_t *id2) /* the compare function */ + { return (id1->key < id2->key ? -1 : id1->key > id2->key); } + +static RB_HEAD(idtree_s, id_s) Head = RB_INITIALIZER(&Head); + +RB_PROTOTYPE_STATIC(idtree_s, id_s, entry, cmp) +RB_GENERATE_STATIC(idtree_s, id_s, entry, cmp) + +static id_t *id_remove(id_t *id) + { return RB_REMOVE(idtree_s, &Head, id); } +static id_t *id_insert(id_t *id) + { return RB_INSERT(idtree_s, &Head, id); } +static id_t *id_search(int key) + { id_t tmp; tmp.key = key; return RB_FIND(idtree_s, &Head, &tmp); } +static id_t *id_first(int key) + { id_t tmp; tmp.key = key; return RB_NFIND(idtree_s, &Head, &tmp); } +#if 0 +id_t *id_next(id_t *id) + { return RB_NEXT(idtree_s, &Head, id); } +id_t *id_prev(id_t *id) + { return RB_PREV(idtree_s, &Head, id); } +id_t *id_min(void) + { return RB_MIN(idtree_s, &Head); } +id_t *id_max(void) + { return RB_MAX(idtree_s, &Head); } +id_t *id_root(void) + { return RB_ROOT(&Head); } +#endif + + +int id_new(void) + { + id_t *id; + int key = key_new(); /* allocate a free key */ + if(key == -1) + return -1; + if((id = (id_t*)malloc(sizeof(id_t))) == NULL) return -1; + id->key = key; + id_insert(id); + return id->key; + } + +void id_free(int key) + { + id_t* id = id_search(key); + if(id) + { + id_remove(id); + free(id); + } + } + +void id_free_all(void) + { + id_t *id; + while((id = id_first(0))) + { + id_remove(id); + free(id); + } + } + diff --git a/src/input.c b/src/input.c new file mode 100644 index 0000000..7b634af --- /dev/null +++ b/src/input.c @@ -0,0 +1,344 @@ +/* The MIT License (MIT) + * + * Copyright (c) 2016 Stefano Trettel + * + * Software repository: MoonGLFW, https://github.com/stetre/moonglfw + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "internal.h" + +ENUM_STRINGS(InputModeStrings) = { + "cursor", + "sticky keys", + "sticky mouse buttons", + NULL +}; +ENUM_CODES(InputModeCodes) = { + GLFW_CURSOR, + GLFW_STICKY_KEYS, + GLFW_STICKY_MOUSE_BUTTONS, +}; +ENUM_T(InputModeEnum, InputModeStrings, InputModeCodes) +#define CheckInputMode(L, arg) enumCheck((L), (arg), &InputModeEnum) +#define PushInputMode(L, code) enumPush((L), (code), &InputModeEnum) + +ENUM_STRINGS(CursorModeStrings) = { + "normal", + "hidden", + "disabled", + NULL +}; +ENUM_CODES(CursorModeCodes) = { + GLFW_CURSOR_NORMAL, + GLFW_CURSOR_HIDDEN, + GLFW_CURSOR_DISABLED, +}; +ENUM_T(CursorModeEnum, CursorModeStrings, CursorModeCodes) +#define CheckCursorMode(L, arg) enumCheck((L), (arg), &CursorModeEnum) +#define PushCursorMode(L, code) enumPush((L), (code), &CursorModeEnum) + +ENUM_STRINGS(CursorShapeStrings) = { + "arrow", + "ibeam", + "crosshair", + "hand", + "hresize", + "vresize", + NULL +}; +ENUM_CODES(CursorShapeCodes) = { + GLFW_ARROW_CURSOR, + GLFW_IBEAM_CURSOR, + GLFW_CROSSHAIR_CURSOR, + GLFW_HAND_CURSOR, + GLFW_HRESIZE_CURSOR, + GLFW_VRESIZE_CURSOR, +}; +ENUM_T(CursorShapeEnum, CursorShapeStrings, CursorShapeCodes) +#define CheckCursorShape(L, arg) enumCheck((L), (arg), &CursorShapeEnum) +#define PushCursorShape(L, code) enumPush((L), (code), &CursorShapeEnum) + +/*------------------------------------------------------------------------------* + | | + *------------------------------------------------------------------------------*/ + + +static int GetInputMode(lua_State *L) + { + int val; + win_t *win = checkwindow(L, 1); + int mode = CheckInputMode(L, 2); + val = glfwGetInputMode(win->window,mode); + switch(mode) + { + case GLFW_CURSOR: PushCursorMode(L, val); return 1; + case GLFW_STICKY_KEYS: + case GLFW_STICKY_MOUSE_BUTTONS: lua_pushboolean(L, val); return 1; + default: + return unexpected(L); + } + return 0; + } + +static int SetInputMode(lua_State *L) + { + int value; + win_t *win = checkwindow(L, 1); + int mode = CheckInputMode(L, 2); + switch(mode) + { + case GLFW_CURSOR: value = CheckCursorMode(L, 3); break; + case GLFW_STICKY_KEYS: + case GLFW_STICKY_MOUSE_BUTTONS: value = checkboolean(L, 3); break; + default: + return unexpected(L); + } + glfwSetInputMode(win->window, mode, value); + return 0; + } + +#define CheckKey(L, arg) enumCheck((L), (arg), enumKey()) + +static int GetKey(lua_State *L) + { + win_t *win = checkwindow(L, 1); + int key = CheckKey(L, 2); + int state = glfwGetKey(win->window, key); + lua_pushstring(L, state==GLFW_PRESS ? "press" : "release"); + return 1; + } + + +/*------------------------------------------------------------------------------* + | Mouse | + *------------------------------------------------------------------------------*/ + +#define CheckButton(L, arg) enumCheck((L), (arg), enumButton()) + +static int GetMouseButton(lua_State *L) + { + win_t *win = checkwindow(L, 1); + int button = CheckButton(L, 2); + int state = glfwGetMouseButton(win->window, button); + lua_pushstring(L, state==GLFW_PRESS ? "press" : "release"); + return 1; + } + +static int GetCursorPos(lua_State *L) + { + double xpos, ypos; + win_t *win = checkwindow(L, 1); + glfwGetCursorPos(win->window, &xpos, &ypos); + lua_pushnumber(L, xpos); + lua_pushnumber(L, ypos); + return 2; + } + +static int SetCursorPos(lua_State *L) + { + win_t *win = checkwindow(L, 1); + double xpos = luaL_checknumber(L, 2); + double ypos = luaL_checknumber(L, 3); + glfwSetCursorPos(win->window, xpos, ypos); + return 0; + } + +static int CreateCursor(lua_State *L) +/* create_cursor(image_width, image_height, image_pixels, xhot, yhot) + * -> cursor handle + */ + { + size_t len; + int xhot, yhot; + GLFWimage image; + cur_t *cur; + image.width = luaL_checkinteger(L, 1); + image.height = luaL_checkinteger(L, 2); + image.pixels = (unsigned char*)luaL_checklstring(L, 3, &len); /* yeah, it's const... */ + xhot = luaL_checkinteger(L, 4); + yhot = luaL_checkinteger(L, 5); + + cur = cur_new(); + if(!cur) + return luaL_error(L, "cannot create cursor"); + + cur->cursor = glfwCreateCursor(&image, xhot, yhot); + if(!cur->cursor) + { + cur_free(cur); + return luaL_error(L, "cannot create cursor"); + } + lua_pushinteger(L, cur->id); + return 1; + } + +static int CreateStandardCursor(lua_State *L) + { + int shape = CheckCursorShape(L, 1); + cur_t *cur = cur_new(); + if(!cur) + return luaL_error(L, "cannot create cursor"); + + cur->cursor = glfwCreateStandardCursor(shape); + if(!cur->cursor) + { + cur_free(cur); + return luaL_error(L, "cannot create cursor"); + } + lua_pushinteger(L, cur->id); + return 1; + } + +static int DestroyCursor(lua_State *L) + { + cur_t *cur = checkcursor(L, 1); + glfwDestroyCursor(cur->cursor); + cur_free(cur); + return 0; + } + +static int SetCursor(lua_State *L) + { + win_t *win = checkwindow(L, 1); + cur_t *cur = checkcursor(L, 2); + glfwSetCursor(win->window, cur->cursor); + return 0; + } + + +/*------------------------------------------------------------------------------* + | Joystick | + *------------------------------------------------------------------------------*/ + +#define CheckJoystick(L, arg) luaL_checkinteger((L), (arg)) + 1 /* 1,2, ..., 16 */ + +static int JoystickPresent(lua_State *L) + { + int joy = CheckJoystick(L, 1); + int val = glfwJoystickPresent(joy); + lua_pushboolean(L, val); + return 1; + } + +static int GetJoystickAxes(lua_State *L) + { + int i, count; + int joy = CheckJoystick(L, 1); + const float *axis = glfwGetJoystickAxes(joy, &count); + if(!axis) + return 0; + for(i=0; i< count; i++) + lua_pushnumber(L, axis[i]); + return count; + } + +static int GetJoystickButtons(lua_State *L) + { + int i, count; + int joy = CheckJoystick(L, 1); + const unsigned char *state = glfwGetJoystickButtons(joy, &count); + if(!state) + return 0; + for(i=0; i< count; i++) + lua_pushstring(L, state[i]==GLFW_PRESS ? "press" : "release"); + return count; + } + +static int GetJoystickName(lua_State *L) + { + int joy = CheckJoystick(L, 1); + const char *name = glfwGetJoystickName(joy); + lua_pushstring(L, name ? name : "???"); + return 1; + } + + +/*------------------------------------------------------------------------------* + | Clipboard | + *------------------------------------------------------------------------------*/ + +static int SetClipboardString(lua_State *L) + { + win_t *win = checkwindow(L, 1); + const char* string = luaL_checkstring(L, 2); + glfwSetClipboardString(win->window, string); + return 0; + } + +static int GetClipboardString(lua_State *L) + { + win_t *win = checkwindow(L, 1); + const char* string = glfwGetClipboardString(win->window); + lua_pushstring(L, string); + return 1; + } + +/*------------------------------------------------------------------------------* + | Time | + *------------------------------------------------------------------------------*/ + + +static int GetTime(lua_State *L) + { + lua_pushnumber(L, glfwGetTime()); + return 1; + } + +static int SetTime(lua_State *L) + { + double time = luaL_checknumber(L, 1); + glfwSetTime(time); + return 0; + } + + +/*------------------------------------------------------------------------------* + | Registration | + *------------------------------------------------------------------------------*/ + +static const struct luaL_Reg Functions[] = + { + { "get_input_mode", GetInputMode }, + { "set_input_mode", SetInputMode }, + { "get_key", GetKey}, + { "get_mouse_button", GetMouseButton }, + { "get_cursor_pos", GetCursorPos }, + { "set_cursor_pos", SetCursorPos }, + { "create_cursor", CreateCursor }, + { "create_standard_cursor", CreateStandardCursor }, + { "destroy_cursor", DestroyCursor }, + { "set_cursor", SetCursor }, + { "joystick_present", JoystickPresent }, + { "get_joystick_axes", GetJoystickAxes }, + { "get_joystick_buttons", GetJoystickButtons }, + { "get_joystick_name", GetJoystickName }, + { "set_clipboard_string", SetClipboardString }, + { "get_clipboard_string", GetClipboardString }, + { "get_time", GetTime }, + { "set_time", SetTime }, + { NULL, NULL } /* sentinel */ + }; + +void moonglfw_open_input(lua_State *L) + { + luaL_setfuncs(L, Functions, 0); + } + diff --git a/src/internal.h b/src/internal.h new file mode 100644 index 0000000..9bf613a --- /dev/null +++ b/src/internal.h @@ -0,0 +1,231 @@ +/* The MIT License (MIT) + * + * Copyright (c) 2016 Stefano Trettel + * + * Software repository: MoonGLFW, https://github.com/stetre/moonglfw + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/******************************************************************************** + * internal common header * + ********************************************************************************/ + +#ifndef internalDEFINED +#define internalDEFINED + +#include +#include +#include "moonglfw.h" +#include "tree.h" + +#define TOSTR_(x) #x +#define TOSTR(x) TOSTR_(x) + +/* Note: all the dynamic symbols of this library (should) start with 'moonglfw_' . + * The only exception is the luaopen_moonglfw() function, which is searched for + * with that name by Lua. + * MoonGLFW's string references on the Lua registry also start with 'moonglfw_'. + */ + +#if LUA_VERSION_NUM < 503 /* defined in lua.h */ +#error "MoonGLFW requires Lua v5.3 or greater" +#endif + +#if (LUAVER != LUA_VERSION_NUM) +#pragma message ("lua.h version is "TOSTR(LUA_VERSION_NUM)) +#error "Lua version mismatch" +#endif + +#include "structs.h" +#include "enum.h" + +extern lua_State *moonglfw_L; /* the global Lua state */ + +#if 0 +/* .c */ +#define moonglfw_ +#endif + +/* utils.c */ +#define noprintf moonglfw_noprintf +int noprintf(const char *fmt, ...); +#define notavailable moonglfw_notavailable +int notavailable(lua_State *L, ...); +#define checkoption_hint moonglfw_checkoption_hint +int checkoption_hint(lua_State *L, int arg, const char *def, const char *const lst[]); +#define checkboolean moonglfw_checkboolean +GLboolean checkboolean(lua_State *L, int arg); +#define testwindow moonglfw_testwindow +int testwindow(lua_State *L, int arg, win_t **win_); +#define checkwindow moonglfw_checkwindow +win_t *checkwindow(lua_State *L, int arg); +#define testmonitor moonglfw_testmonitor +int testmonitor(lua_State *L, int arg, mon_t **mon_); +#define checkmonitor moonglfw_checkmonitor +mon_t *checkmonitor(lua_State *L, int arg); +#define testcursor moonglfw_testcursor +int testcursor(lua_State *L, int arg, cur_t **cur_); +#define checkcursor moonglfw_checkcursor +cur_t *checkcursor(lua_State *L, int arg); +#define pushvidmode moonglfw_pushvidmode +int pushvidmode(lua_State *L, const GLFWvidmode *mode); +#define pushgammaramp moonglfw_pushgammaramp +int pushgammaramp(lua_State *L, const GLFWgammaramp *ramp); +#define checkgammaramp moonglfw_checkgammaramp +int checkgammaramp(lua_State *L, int arg, GLFWgammaramp *ramp); + +/* id.c */ +#define id_free_all moonglfw_id_free_all +int id_new(void); +#define id_free_all moonglfw_id_free_all +void id_free(int key); +#define id_free_all moonglfw_id_free_all +void id_free_all(void); + +/* mon.c */ +#define mon_search moonglfw_mon_search +mon_t *mon_search(int id); +#define mon_first moonglfw_mon_first +mon_t *mon_first(int id); +#define mon_next moonglfw_mon_next +mon_t *mon_next(mon_t *mon); +#define mon_new moonglfw_mon_new +mon_t *mon_new(void); +#define mon_free moonglfw_mon_free +void mon_free(mon_t* mon); +#define mon_free_all moonglfw_mon_free_all +void mon_free_all(void); +#define mon_check moonglfw_mon_check +mon_t* mon_check(lua_State *L, int arg); + + +/* win.c */ +#define win_search moonglfw_win_search +win_t *win_search(int id); +#define win_first moonglfw_win_first +win_t *win_first(int id); +#define win_next moonglfw_win_next +win_t *win_next(win_t *win); +#define win_new moonglfw_win_new +win_t *win_new(void); +#define win_free moonglfw_win_free +void win_free(win_t* win); +#define win_free_all moonglfw_win_free_all +void win_free_all(void); +#define win_check moonglfw_win_check +win_t* win_check(lua_State *L, int arg); + +/* cur.c */ +#define cur_search moonglfw_cur_search +cur_t *cur_search(int id); +#define cur_first moonglfw_cur_first +cur_t *cur_first(int id); +#define cur_next moonglfw_cur_next +cur_t *cur_next(cur_t *cur); +#define cur_new moonglfw_cur_new +cur_t *cur_new(void); +#define cur_free moonglfw_cur_free +void cur_free(cur_t* cur); +#define cur_free_all moonglfw_cur_free_all +void cur_free_all(void); +#define cur_check moonglfw_cur_check +cur_t* cur_check(lua_State *L, int arg); + + +/* monitor.c */ +#define monitorAdd moonglfw_monitorAdd +int monitorAdd(lua_State *L, GLFWmonitor *monitor); +#define monitorCallback moonglfw_monitorCallback +void monitorCallback(GLFWmonitor *monitor, int event); + + +/* main.c */ +#define errorCallback moonglfw_errorCallback +void errorCallback(int ec, const char *descr); +int luaopen_moonglfw(lua_State *L); +void moonglfw_open_window(lua_State *L); +void moonglfw_open_hint(lua_State *L); +void moonglfw_open_monitor(lua_State *L); +void moonglfw_open_callbacks(lua_State *L); +void moonglfw_open_input(lua_State *L); +void moonglfw_open_context(lua_State *L); + +/*------------------------------------------------------------------------------* + | Debug and other utilities | + *------------------------------------------------------------------------------*/ + +/* If this is printed, it denotes a suspect bug: */ +#define UNEXPECTED_ERROR "unexpected error (%s, %d)", __FILE__, __LINE__ +#define unexpected(L) luaL_error((L), UNEXPECTED_ERROR) +#define NOT_AVAILABLE do { return luaL_error(L, "function not available"); } while(0) + + +#define NOT_IMPLEMENTED(func) \ +static int func(lua_State *L) \ + { \ + luaL_error(L, "function "#func" is not implemented"); \ + return 0; \ + } + +#define NOT_SUPPORTED(func) \ +static int func(lua_State *L) \ + { \ + luaL_error(L, "function "#func" is not supported"); \ + return 0; \ + } + +#if defined(DEBUG) + +#define checkoption checkoption_hint +#define DBG printf + +#define TR() do { \ + printf("trace %s %d\n",__FILE__,__LINE__); \ +} while(0) + +#define BK() do { \ + printf("break %s %d\n",__FILE__,__LINE__); \ + getchar(); \ +} while(0) + +#else + +#define checkoption luaL_checkoption +#define DBG noprintf +#define TR() +#define BK() + +#endif /* DEBUG */ + +/*------------------------------------------------------------------------------* + | Code generators | + *------------------------------------------------------------------------------*/ + +#define CALLBACK_UNREF(cb) do { \ + if((cb) != LUA_NOREF) { \ + luaL_unref(moonglfw_L, LUA_REGISTRYINDEX, (cb)); \ + (cb) = LUA_NOREF; } \ +} while(0) + +#define VOID_FUNC(func) \ + static int func(lua_State *L) { (void)L; glfw##func(); return 0; } + + +#endif /* internalDEFINED */ diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..792f9f1 --- /dev/null +++ b/src/main.c @@ -0,0 +1,123 @@ +/* The MIT License (MIT) + * + * Copyright (c) 2016 Stefano Trettel + * + * Software repository: MoonGLFW, https://github.com/stetre/moonglfw + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "internal.h" + + +static void AddVersions(lua_State *L) +/* Add version strings to the glfw table */ + { + int major, minor, rev; + lua_pushstring(L, "_VERSION"); + lua_pushstring(L, "MoonGLFW "MOONGLFW_VERSION); + lua_settable(L, -3); + + lua_pushstring(L, "_GLFW_VERSION"); + glfwGetVersion(&major, &minor, &rev); + lua_pushfstring(L, "GLFW %d.%d.%d", major, minor, rev); +#if 0 + lua_pushfstring(L, "GLFW %d.%d.%d release %d", + GLFW_VERSION_MAJOR, GLFW_VERSION_MINOR, GLFW_VERSION_REVISION, GLFW_RELEASE); +#endif + lua_settable(L, -3); + } + +static int GetVersion(lua_State *L) + { + int major, minor, rev; + glfwGetVersion(&major, &minor, &rev); + lua_pushinteger(L, major); + lua_pushinteger(L, minor); + lua_pushinteger(L, rev); + return 3; + } + +static int GetVersionString(lua_State *L) + { + lua_pushstring(L, glfwGetVersionString()); + return 1; + } + + +lua_State *moonglfw_L = NULL; + +static void AtExit(void) + { + if(moonglfw_L) + { + cur_free_all(); + mon_free_all(); + win_free_all(); + id_free_all(); + glfwTerminate(); + moonglfw_L = NULL; + } + } + +void errorCallback(int ec, const char *descr) + { + if(moonglfw_L) + luaL_error(moonglfw_L, "GLFW error: '%s' (code = %d)", descr, ec); + else + printf("GLFW error: '%s' (code = %d)\n", descr, ec); + } + +/*------------------------------------------------------------------------------* + | Registration | + *------------------------------------------------------------------------------*/ + +static const struct luaL_Reg Functions[] = + { + { "get_version", GetVersion }, + { "get_version_string", GetVersionString }, + { NULL, NULL } /* sentinel */ + }; + + +int luaopen_moonglfw(lua_State *L) +/* Lua calls this function to load the module */ + { + moonglfw_L = L; + + lua_newtable(L); /* the glfw table */ + AddVersions(L); + + if(glfwInit() != GL_TRUE) + return luaL_error(L, "glfwInit() failed"); + atexit(AtExit); + glfwSetErrorCallback(errorCallback); + + /* add glfw functions: */ + luaL_setfuncs(L, Functions, 0); + moonglfw_open_window(L); + moonglfw_open_hint(L); + moonglfw_open_monitor(L); + moonglfw_open_callbacks(L); + moonglfw_open_input(L); + moonglfw_open_context(L); + + return 1; + } + diff --git a/src/mon.c b/src/mon.c new file mode 100644 index 0000000..56036a4 --- /dev/null +++ b/src/mon.c @@ -0,0 +1,100 @@ +/* The MIT License (MIT) + * + * Copyright (c) 2016 Stefano Trettel + * + * Software repository: MoonGLFW, https://github.com/stetre/moonglfw + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "internal.h" + +static int cmp(mon_t *mon1, mon_t *mon2) /* the compare function */ + { return (mon1->id < mon2->id ? -1 : mon1->id > mon2->id); } + +static RB_HEAD(montree_s, mon_s) Head = RB_INITIALIZER(&Head); + +RB_PROTOTYPE_STATIC(montree_s, mon_s, entry, cmp) +RB_GENERATE_STATIC(montree_s, mon_s, entry, cmp) + +static mon_t *mon_remove(mon_t *mon) + { return RB_REMOVE(montree_s, &Head, mon); } +static mon_t *mon_insert(mon_t *mon) + { return RB_INSERT(montree_s, &Head, mon); } +mon_t *mon_search(int id) + { mon_t tmp; tmp.id = id; return RB_FIND(montree_s, &Head, &tmp); } +mon_t *mon_first(int id) + { mon_t tmp; tmp.id = id; return RB_NFIND(montree_s, &Head, &tmp); } +mon_t *mon_next(mon_t *mon) + { return RB_NEXT(montree_s, &Head, mon); } +#if 0 +mon_t *mon_prev(mon_t *mon) + { return RB_PREV(montree_s, &Head, mon); } +mon_t *mon_min(void) + { return RB_MIN(montree_s, &Head); } +mon_t *mon_max(void) + { return RB_MAX(montree_s, &Head); } +mon_t *mon_root(void) + { return RB_ROOT(&Head); } +#endif +mon_t *mon_new(void) + { + mon_t *mon; + int id = id_new(); + if(id == -1) + return NULL; + if((mon = (mon_t*)malloc(sizeof(mon_t))) == NULL) + { id_free(id); return NULL; } + memset(mon, 0, sizeof(mon_t)); + mon->id = id; + if(mon_search(mon->id)) + { free(mon); id_free(id); return NULL; } + //mon->Monitor = LUA_NOREF; + mon_insert(mon); + return mon; + } + +void mon_free(mon_t* mon) + { + if(mon_search(mon->id) == mon) + { + /* release callback references */ + //CALLBACK_UNREF(mon->Monitor); + mon_remove(mon); + } + id_free(mon->id); + free(mon); + } + +void mon_free_all(void) + { + mon_t *mon; + while((mon = mon_first(0))) + mon_free(mon); + } + +mon_t* mon_check(lua_State *L, int arg) + { + int id = luaL_checkinteger(L, arg); + mon_t *mon = mon_search(id); + if(!mon) + luaL_error(L, "invalid monitor id"); + return mon; + } + diff --git a/src/monitor.c b/src/monitor.c new file mode 100644 index 0000000..2d73d46 --- /dev/null +++ b/src/monitor.c @@ -0,0 +1,202 @@ +/* The MIT License (MIT) + * + * Copyright (c) 2016 Stefano Trettel + * + * Software repository: MoonGLFW, https://github.com/stetre/moonglfw + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "internal.h" + +int monitorAdd(lua_State *L, GLFWmonitor *monitor) + { + mon_t *mon = mon_first(0); + while(mon) + { + if(mon->monitor == monitor) /* already in */ + return mon->id; + mon = mon_next(mon); + } + /* not found */ + mon = mon_new(); + if(!mon) + return luaL_error(L, "cannot create monitor entry"); + mon->monitor = monitor; + return mon->id; + } + +#if 0 +static void Delete(GLFWmonitor *monitor) + { + mon_t *mon = mon_first(0); + while(mon) + { + if(mon->monitor == monitor) /* already in */ + { mon_free(mon); return; } + mon = mon_next(mon); + } + } +#endif + +void monitorCallback(GLFWmonitor *monitor, int event) + { + (void)monitor; + (void)event; +#if 0 + switch(event) + { + case GLFW_CONNECTED: /* ignore */ return; + case GLFW_DISCONNECTED: Delete(monitor); return; + } +#endif + } + +static int GetPrimaryMonitor(lua_State *L) + { + int id; + GLFWmonitor* monitor = glfwGetPrimaryMonitor(); + if(!monitor) + return 0; + id = monitorAdd(L, monitor); + lua_pushinteger(L, id); + return 1; + } + +static int GetMonitors(lua_State *L) + { + int i, id, count; + GLFWmonitor** monitor; + /* no mon_free_all(); */ + monitor = glfwGetMonitors(&count); + if(!monitor) + return 0; + for(i=0; imonitor, &xpos, &ypos); + lua_pushinteger(L, xpos); + lua_pushinteger(L, ypos); + return 2; + } + +static int GetMonitorPhysicalSize(lua_State *L) + { + int widthmm, heightmm; + mon_t *mon = checkmonitor(L, 1); + glfwGetMonitorPhysicalSize(mon->monitor, &widthmm, &heightmm); + lua_pushinteger(L, widthmm); + lua_pushinteger(L, heightmm); + return 2; + } + +static int GetMonitorName(lua_State *L) + { + mon_t *mon = checkmonitor(L, 1); + const char* name = glfwGetMonitorName(mon->monitor); + lua_pushstring(L, name ? name : "???"); + return 1; + } + +static int GetVideoModes(lua_State *L) + { + int i, count; + mon_t *mon = checkmonitor(L, 1); + const GLFWvidmode *mode = glfwGetVideoModes(mon->monitor, &count); + if(!mode) + return 0; + for(i=0; imonitor); + if(!mode) + return 0; + pushvidmode(L, mode); + return 1; + } + +static int SetGamma(lua_State *L) + { + mon_t *mon = checkmonitor(L, 1); + float gamma = luaL_checknumber(L, 2); + glfwSetGamma(mon->monitor, gamma); + return 0; + } + +static int GetGammaRamp(lua_State *L) + { + mon_t *mon = checkmonitor(L, 1); + const GLFWgammaramp *ramp = glfwGetGammaRamp(mon->monitor); + if(!ramp) + return 0; + return pushgammaramp(L, ramp); + } + +static int SetGammaRamp(lua_State *L) + { + GLFWgammaramp ramp; + mon_t *mon = checkmonitor(L, 1); + checkgammaramp(L, 2, &ramp); + glfwSetGammaRamp(mon->monitor, &ramp); + free(ramp.red); + free(ramp.green); + free(ramp.blue); + return 0; + } + +/*------------------------------------------------------------------------------* + | Registration | + *------------------------------------------------------------------------------*/ + +static const struct luaL_Reg Functions[] = + { + { "get_primary_monitor", GetPrimaryMonitor }, + { "get_monitors", GetMonitors }, + { "get_monitor_pos", GetMonitorPos }, + { "get_monitor_physical_size", GetMonitorPhysicalSize }, + { "get_monitor_name", GetMonitorName }, + { "get_video_modes", GetVideoModes }, + { "get_video_mode", GetVideoMode }, + { "set_gamma", SetGamma }, + { "get_gamma_ramp", GetGammaRamp }, + { "set_gamma_ramp", SetGammaRamp }, + { NULL, NULL } /* sentinel */ + }; + +void moonglfw_open_monitor(lua_State *L) + { + luaL_setfuncs(L, Functions, 0); + glfwSetMonitorCallback(monitorCallback); + } + diff --git a/src/moonglfw.h b/src/moonglfw.h new file mode 100644 index 0000000..8828439 --- /dev/null +++ b/src/moonglfw.h @@ -0,0 +1,41 @@ +/* The MIT License (MIT) + * + * Copyright (c) 2016 Stefano Trettel + * + * Software repository: MoonGLFW, https://github.com/stetre/moonglfw + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/**************************************************************************** + * MoonGLFW library - C API * + ****************************************************************************/ + +#ifndef moonglfwDEFINED +#define moonglfwDEFINED + +#include +#include "lualib.h" +#include "lauxlib.h" +#include + +#define MOONGLFW_VERSION "0.1" + +#endif /* moonglfwDEFINED */ + diff --git a/src/structs.h b/src/structs.h new file mode 100644 index 0000000..20cf1f5 --- /dev/null +++ b/src/structs.h @@ -0,0 +1,89 @@ +/* The MIT License (MIT) + * + * Copyright (c) 2016 Stefano Trettel + * + * Software repository: MoonGLFW, https://github.com/stetre/moonglfw + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/******************************************************************************** + * Structs definitions * + ********************************************************************************/ + +#ifndef structsDEFINED +#define structsDEFINED + +/* Types redefinitions (I know, I know... ) */ +#define id_t moonglfw_id_t +#define id_s moonglfw_id_s +#define win_t moonglfw_win_t +#define win_s moonglfw_win_s +#define mon_t moonglfw_mon_t +#define mon_s moonglfw_mon_s +#define cur_t moonglfw_cur_t +#define cur_s moonglfw_cur_s + +#define moonglfw_id_t struct moonglfw_id_s +struct moonglfw_id_s { + RB_ENTRY(moonglfw_id_s) entry; + int key; /* search key */ +}; + +#define moonglfw_win_t struct moonglfw_win_s +struct moonglfw_win_s { + RB_ENTRY(moonglfw_win_s) entry; + int id; /* window id (search key) */ + GLFWwindow *window; /* self */ + int share_id; /* share window id */ + /* references for callbacks on the Lua registry */ + int WindowPos; + int WindowSize; + int WindowClose; + int WindowRefresh; + int WindowFocus; + int WindowIconify; + int FramebufferSize; + int Key; + int Char; + int CharMods; + int MouseButton; + int CursorPos; + int CursorEnter; + int Scroll; + int Drop; +}; + +#define moonglfw_mon_t struct moonglfw_mon_s +struct moonglfw_mon_s { + RB_ENTRY(moonglfw_mon_s) entry; + int id; /* monitor id (search key) */ + GLFWmonitor *monitor; /* self */ + /* references for callbacks on the Lua registry */ + //int Monitor; +}; + +#define moonglfw_cur_t struct moonglfw_cur_s +struct moonglfw_cur_s { + RB_ENTRY(moonglfw_cur_s) entry; + int id; /* cursor id (search key) */ + GLFWcursor *cursor; /* self */ +}; + +#endif /* structsDEFINED */ diff --git a/src/tree.h b/src/tree.h new file mode 100644 index 0000000..ce47a63 --- /dev/null +++ b/src/tree.h @@ -0,0 +1,748 @@ +/* $OpenBSD: tree.h,v 1.14 2015/05/25 03:07:49 deraadt Exp $ */ +/* + * Copyright 2002 Niels Provos + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + */ + +#ifndef _SYS_TREE_H_ +#define _SYS_TREE_H_ + +/* + * This file defines data structures for different types of trees: + * splay trees and red-black trees. + * + * A splay tree is a self-organizing data structure. Every operation + * on the tree causes a splay to happen. The splay moves the requested + * node to the root of the tree and partly rebalances it. + * + * This has the benefit that request locality causes faster lookups as + * the requested nodes move to the top of the tree. On the other hand, + * every lookup causes memory writes. + * + * The Balance Theorem bounds the total access time for m operations + * and n inserts on an initially empty tree as O((m + n)lg n). The + * amortized cost for a sequence of m accesses to a splay tree is O(lg n); + * + * A red-black tree is a binary search tree with the node color as an + * extra attribute. It fulfills a set of conditions: + * - every search path from the root to a leaf consists of the + * same number of black nodes, + * - each red node (except for the root) has a black parent, + * - each leaf node is black. + * + * Every operation on a red-black tree is bounded as O(lg n). + * The maximum height of a red-black tree is 2lg (n+1). + */ + +#define SPLAY_HEAD(name, type) \ +struct name { \ + struct type *sph_root; /* root of the tree */ \ +} + +#define SPLAY_INITIALIZER(root) \ + { NULL } + +#define SPLAY_INIT(root) do { \ + (root)->sph_root = NULL; \ +} while (0) + +#define SPLAY_ENTRY(type) \ +struct { \ + struct type *spe_left; /* left element */ \ + struct type *spe_right; /* right element */ \ +} + +#define SPLAY_LEFT(elm, field) (elm)->field.spe_left +#define SPLAY_RIGHT(elm, field) (elm)->field.spe_right +#define SPLAY_ROOT(head) (head)->sph_root +#define SPLAY_EMPTY(head) (SPLAY_ROOT(head) == NULL) + +/* SPLAY_ROTATE_{LEFT,RIGHT} expect that tmp hold SPLAY_{RIGHT,LEFT} */ +#define SPLAY_ROTATE_RIGHT(head, tmp, field) do { \ + SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(tmp, field); \ + SPLAY_RIGHT(tmp, field) = (head)->sph_root; \ + (head)->sph_root = tmp; \ +} while (0) + +#define SPLAY_ROTATE_LEFT(head, tmp, field) do { \ + SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(tmp, field); \ + SPLAY_LEFT(tmp, field) = (head)->sph_root; \ + (head)->sph_root = tmp; \ +} while (0) + +#define SPLAY_LINKLEFT(head, tmp, field) do { \ + SPLAY_LEFT(tmp, field) = (head)->sph_root; \ + tmp = (head)->sph_root; \ + (head)->sph_root = SPLAY_LEFT((head)->sph_root, field); \ +} while (0) + +#define SPLAY_LINKRIGHT(head, tmp, field) do { \ + SPLAY_RIGHT(tmp, field) = (head)->sph_root; \ + tmp = (head)->sph_root; \ + (head)->sph_root = SPLAY_RIGHT((head)->sph_root, field); \ +} while (0) + +#define SPLAY_ASSEMBLE(head, node, left, right, field) do { \ + SPLAY_RIGHT(left, field) = SPLAY_LEFT((head)->sph_root, field); \ + SPLAY_LEFT(right, field) = SPLAY_RIGHT((head)->sph_root, field);\ + SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(node, field); \ + SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(node, field); \ +} while (0) + +/* Generates prototypes and inline functions */ + +#define SPLAY_PROTOTYPE(name, type, field, cmp) \ +void name##_SPLAY(struct name *, struct type *); \ +void name##_SPLAY_MINMAX(struct name *, int); \ +struct type *name##_SPLAY_INSERT(struct name *, struct type *); \ +struct type *name##_SPLAY_REMOVE(struct name *, struct type *); \ + \ +/* Finds the node with the same key as elm */ \ +static __inline struct type * \ +name##_SPLAY_FIND(struct name *head, struct type *elm) \ +{ \ + if (SPLAY_EMPTY(head)) \ + return(NULL); \ + name##_SPLAY(head, elm); \ + if ((cmp)(elm, (head)->sph_root) == 0) \ + return (head->sph_root); \ + return (NULL); \ +} \ + \ +static __inline struct type * \ +name##_SPLAY_NEXT(struct name *head, struct type *elm) \ +{ \ + name##_SPLAY(head, elm); \ + if (SPLAY_RIGHT(elm, field) != NULL) { \ + elm = SPLAY_RIGHT(elm, field); \ + while (SPLAY_LEFT(elm, field) != NULL) { \ + elm = SPLAY_LEFT(elm, field); \ + } \ + } else \ + elm = NULL; \ + return (elm); \ +} \ + \ +static __inline struct type * \ +name##_SPLAY_MIN_MAX(struct name *head, int val) \ +{ \ + name##_SPLAY_MINMAX(head, val); \ + return (SPLAY_ROOT(head)); \ +} + +/* Main splay operation. + * Moves node close to the key of elm to top + */ +#define SPLAY_GENERATE(name, type, field, cmp) \ +struct type * \ +name##_SPLAY_INSERT(struct name *head, struct type *elm) \ +{ \ + if (SPLAY_EMPTY(head)) { \ + SPLAY_LEFT(elm, field) = SPLAY_RIGHT(elm, field) = NULL; \ + } else { \ + int __comp; \ + name##_SPLAY(head, elm); \ + __comp = (cmp)(elm, (head)->sph_root); \ + if(__comp < 0) { \ + SPLAY_LEFT(elm, field) = SPLAY_LEFT((head)->sph_root, field);\ + SPLAY_RIGHT(elm, field) = (head)->sph_root; \ + SPLAY_LEFT((head)->sph_root, field) = NULL; \ + } else if (__comp > 0) { \ + SPLAY_RIGHT(elm, field) = SPLAY_RIGHT((head)->sph_root, field);\ + SPLAY_LEFT(elm, field) = (head)->sph_root; \ + SPLAY_RIGHT((head)->sph_root, field) = NULL; \ + } else \ + return ((head)->sph_root); \ + } \ + (head)->sph_root = (elm); \ + return (NULL); \ +} \ + \ +struct type * \ +name##_SPLAY_REMOVE(struct name *head, struct type *elm) \ +{ \ + struct type *__tmp; \ + if (SPLAY_EMPTY(head)) \ + return (NULL); \ + name##_SPLAY(head, elm); \ + if ((cmp)(elm, (head)->sph_root) == 0) { \ + if (SPLAY_LEFT((head)->sph_root, field) == NULL) { \ + (head)->sph_root = SPLAY_RIGHT((head)->sph_root, field);\ + } else { \ + __tmp = SPLAY_RIGHT((head)->sph_root, field); \ + (head)->sph_root = SPLAY_LEFT((head)->sph_root, field);\ + name##_SPLAY(head, elm); \ + SPLAY_RIGHT((head)->sph_root, field) = __tmp; \ + } \ + return (elm); \ + } \ + return (NULL); \ +} \ + \ +void \ +name##_SPLAY(struct name *head, struct type *elm) \ +{ \ + struct type __node, *__left, *__right, *__tmp; \ + int __comp; \ +\ + SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\ + __left = __right = &__node; \ +\ + while ((__comp = (cmp)(elm, (head)->sph_root))) { \ + if (__comp < 0) { \ + __tmp = SPLAY_LEFT((head)->sph_root, field); \ + if (__tmp == NULL) \ + break; \ + if ((cmp)(elm, __tmp) < 0){ \ + SPLAY_ROTATE_RIGHT(head, __tmp, field); \ + if (SPLAY_LEFT((head)->sph_root, field) == NULL)\ + break; \ + } \ + SPLAY_LINKLEFT(head, __right, field); \ + } else if (__comp > 0) { \ + __tmp = SPLAY_RIGHT((head)->sph_root, field); \ + if (__tmp == NULL) \ + break; \ + if ((cmp)(elm, __tmp) > 0){ \ + SPLAY_ROTATE_LEFT(head, __tmp, field); \ + if (SPLAY_RIGHT((head)->sph_root, field) == NULL)\ + break; \ + } \ + SPLAY_LINKRIGHT(head, __left, field); \ + } \ + } \ + SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \ +} \ + \ +/* Splay with either the minimum or the maximum element \ + * Used to find minimum or maximum element in tree. \ + */ \ +void name##_SPLAY_MINMAX(struct name *head, int __comp) \ +{ \ + struct type __node, *__left, *__right, *__tmp; \ +\ + SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\ + __left = __right = &__node; \ +\ + while (1) { \ + if (__comp < 0) { \ + __tmp = SPLAY_LEFT((head)->sph_root, field); \ + if (__tmp == NULL) \ + break; \ + if (__comp < 0){ \ + SPLAY_ROTATE_RIGHT(head, __tmp, field); \ + if (SPLAY_LEFT((head)->sph_root, field) == NULL)\ + break; \ + } \ + SPLAY_LINKLEFT(head, __right, field); \ + } else if (__comp > 0) { \ + __tmp = SPLAY_RIGHT((head)->sph_root, field); \ + if (__tmp == NULL) \ + break; \ + if (__comp > 0) { \ + SPLAY_ROTATE_LEFT(head, __tmp, field); \ + if (SPLAY_RIGHT((head)->sph_root, field) == NULL)\ + break; \ + } \ + SPLAY_LINKRIGHT(head, __left, field); \ + } \ + } \ + SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \ +} + +#define SPLAY_NEGINF -1 +#define SPLAY_INF 1 + +#define SPLAY_INSERT(name, x, y) name##_SPLAY_INSERT(x, y) +#define SPLAY_REMOVE(name, x, y) name##_SPLAY_REMOVE(x, y) +#define SPLAY_FIND(name, x, y) name##_SPLAY_FIND(x, y) +#define SPLAY_NEXT(name, x, y) name##_SPLAY_NEXT(x, y) +#define SPLAY_MIN(name, x) (SPLAY_EMPTY(x) ? NULL \ + : name##_SPLAY_MIN_MAX(x, SPLAY_NEGINF)) +#define SPLAY_MAX(name, x) (SPLAY_EMPTY(x) ? NULL \ + : name##_SPLAY_MIN_MAX(x, SPLAY_INF)) + +#define SPLAY_FOREACH(x, name, head) \ + for ((x) = SPLAY_MIN(name, head); \ + (x) != NULL; \ + (x) = SPLAY_NEXT(name, head, x)) + +/* Macros that define a red-black tree */ +#define RB_HEAD(name, type) \ +struct name { \ + struct type *rbh_root; /* root of the tree */ \ +} + +#define RB_INITIALIZER(root) \ + { NULL } + +#define RB_INIT(root) do { \ + (root)->rbh_root = NULL; \ +} while (0) + +#define RB_BLACK 0 +#define RB_RED 1 +#define RB_ENTRY(type) \ +struct { \ + struct type *rbe_left; /* left element */ \ + struct type *rbe_right; /* right element */ \ + struct type *rbe_parent; /* parent element */ \ + int rbe_color; /* node color */ \ +} + +#define RB_LEFT(elm, field) (elm)->field.rbe_left +#define RB_RIGHT(elm, field) (elm)->field.rbe_right +#define RB_PARENT(elm, field) (elm)->field.rbe_parent +#define RB_COLOR(elm, field) (elm)->field.rbe_color +#define RB_ROOT(head) (head)->rbh_root +#define RB_EMPTY(head) (RB_ROOT(head) == NULL) + +#define RB_SET(elm, parent, field) do { \ + RB_PARENT(elm, field) = parent; \ + RB_LEFT(elm, field) = RB_RIGHT(elm, field) = NULL; \ + RB_COLOR(elm, field) = RB_RED; \ +} while (0) + +#define RB_SET_BLACKRED(black, red, field) do { \ + RB_COLOR(black, field) = RB_BLACK; \ + RB_COLOR(red, field) = RB_RED; \ +} while (0) + +#ifndef RB_AUGMENT +#define RB_AUGMENT(x) do {} while (0) +#endif + +#define RB_ROTATE_LEFT(head, elm, tmp, field) do { \ + (tmp) = RB_RIGHT(elm, field); \ + if ((RB_RIGHT(elm, field) = RB_LEFT(tmp, field))) { \ + RB_PARENT(RB_LEFT(tmp, field), field) = (elm); \ + } \ + RB_AUGMENT(elm); \ + if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field))) { \ + if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \ + RB_LEFT(RB_PARENT(elm, field), field) = (tmp); \ + else \ + RB_RIGHT(RB_PARENT(elm, field), field) = (tmp); \ + } else \ + (head)->rbh_root = (tmp); \ + RB_LEFT(tmp, field) = (elm); \ + RB_PARENT(elm, field) = (tmp); \ + RB_AUGMENT(tmp); \ + if ((RB_PARENT(tmp, field))) \ + RB_AUGMENT(RB_PARENT(tmp, field)); \ +} while (0) + +#define RB_ROTATE_RIGHT(head, elm, tmp, field) do { \ + (tmp) = RB_LEFT(elm, field); \ + if ((RB_LEFT(elm, field) = RB_RIGHT(tmp, field))) { \ + RB_PARENT(RB_RIGHT(tmp, field), field) = (elm); \ + } \ + RB_AUGMENT(elm); \ + if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field))) { \ + if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \ + RB_LEFT(RB_PARENT(elm, field), field) = (tmp); \ + else \ + RB_RIGHT(RB_PARENT(elm, field), field) = (tmp); \ + } else \ + (head)->rbh_root = (tmp); \ + RB_RIGHT(tmp, field) = (elm); \ + RB_PARENT(elm, field) = (tmp); \ + RB_AUGMENT(tmp); \ + if ((RB_PARENT(tmp, field))) \ + RB_AUGMENT(RB_PARENT(tmp, field)); \ +} while (0) + +/* Generates prototypes and inline functions */ +#define RB_PROTOTYPE(name, type, field, cmp) \ + RB_PROTOTYPE_INTERNAL(name, type, field, cmp,) +#define RB_PROTOTYPE_STATIC(name, type, field, cmp) \ + RB_PROTOTYPE_INTERNAL(name, type, field, cmp, __attribute__((__unused__)) static) +#define RB_PROTOTYPE_INTERNAL(name, type, field, cmp, attr) \ +attr void name##_RB_INSERT_COLOR(struct name *, struct type *); \ +attr void name##_RB_REMOVE_COLOR(struct name *, struct type *, struct type *);\ +attr struct type *name##_RB_REMOVE(struct name *, struct type *); \ +attr struct type *name##_RB_INSERT(struct name *, struct type *); \ +attr struct type *name##_RB_FIND(struct name *, struct type *); \ +attr struct type *name##_RB_NFIND(struct name *, struct type *); \ +attr struct type *name##_RB_NEXT(struct type *); \ +attr struct type *name##_RB_PREV(struct type *); \ +attr struct type *name##_RB_MINMAX(struct name *, int); \ + \ + +/* Main rb operation. + * Moves node close to the key of elm to top + */ +#define RB_GENERATE(name, type, field, cmp) \ + RB_GENERATE_INTERNAL(name, type, field, cmp,) +#define RB_GENERATE_STATIC(name, type, field, cmp) \ + RB_GENERATE_INTERNAL(name, type, field, cmp, __attribute__((__unused__)) static) +#define RB_GENERATE_INTERNAL(name, type, field, cmp, attr) \ +attr void \ +name##_RB_INSERT_COLOR(struct name *head, struct type *elm) \ +{ \ + struct type *parent, *gparent, *tmp; \ + while ((parent = RB_PARENT(elm, field)) && \ + RB_COLOR(parent, field) == RB_RED) { \ + gparent = RB_PARENT(parent, field); \ + if (parent == RB_LEFT(gparent, field)) { \ + tmp = RB_RIGHT(gparent, field); \ + if (tmp && RB_COLOR(tmp, field) == RB_RED) { \ + RB_COLOR(tmp, field) = RB_BLACK; \ + RB_SET_BLACKRED(parent, gparent, field);\ + elm = gparent; \ + continue; \ + } \ + if (RB_RIGHT(parent, field) == elm) { \ + RB_ROTATE_LEFT(head, parent, tmp, field);\ + tmp = parent; \ + parent = elm; \ + elm = tmp; \ + } \ + RB_SET_BLACKRED(parent, gparent, field); \ + RB_ROTATE_RIGHT(head, gparent, tmp, field); \ + } else { \ + tmp = RB_LEFT(gparent, field); \ + if (tmp && RB_COLOR(tmp, field) == RB_RED) { \ + RB_COLOR(tmp, field) = RB_BLACK; \ + RB_SET_BLACKRED(parent, gparent, field);\ + elm = gparent; \ + continue; \ + } \ + if (RB_LEFT(parent, field) == elm) { \ + RB_ROTATE_RIGHT(head, parent, tmp, field);\ + tmp = parent; \ + parent = elm; \ + elm = tmp; \ + } \ + RB_SET_BLACKRED(parent, gparent, field); \ + RB_ROTATE_LEFT(head, gparent, tmp, field); \ + } \ + } \ + RB_COLOR(head->rbh_root, field) = RB_BLACK; \ +} \ + \ +attr void \ +name##_RB_REMOVE_COLOR(struct name *head, struct type *parent, struct type *elm) \ +{ \ + struct type *tmp; \ + while ((elm == NULL || RB_COLOR(elm, field) == RB_BLACK) && \ + elm != RB_ROOT(head)) { \ + if (RB_LEFT(parent, field) == elm) { \ + tmp = RB_RIGHT(parent, field); \ + if (RB_COLOR(tmp, field) == RB_RED) { \ + RB_SET_BLACKRED(tmp, parent, field); \ + RB_ROTATE_LEFT(head, parent, tmp, field);\ + tmp = RB_RIGHT(parent, field); \ + } \ + if ((RB_LEFT(tmp, field) == NULL || \ + RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) &&\ + (RB_RIGHT(tmp, field) == NULL || \ + RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) {\ + RB_COLOR(tmp, field) = RB_RED; \ + elm = parent; \ + parent = RB_PARENT(elm, field); \ + } else { \ + if (RB_RIGHT(tmp, field) == NULL || \ + RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK) {\ + struct type *oleft; \ + if ((oleft = RB_LEFT(tmp, field)))\ + RB_COLOR(oleft, field) = RB_BLACK;\ + RB_COLOR(tmp, field) = RB_RED; \ + RB_ROTATE_RIGHT(head, tmp, oleft, field);\ + tmp = RB_RIGHT(parent, field); \ + } \ + RB_COLOR(tmp, field) = RB_COLOR(parent, field);\ + RB_COLOR(parent, field) = RB_BLACK; \ + if (RB_RIGHT(tmp, field)) \ + RB_COLOR(RB_RIGHT(tmp, field), field) = RB_BLACK;\ + RB_ROTATE_LEFT(head, parent, tmp, field);\ + elm = RB_ROOT(head); \ + break; \ + } \ + } else { \ + tmp = RB_LEFT(parent, field); \ + if (RB_COLOR(tmp, field) == RB_RED) { \ + RB_SET_BLACKRED(tmp, parent, field); \ + RB_ROTATE_RIGHT(head, parent, tmp, field);\ + tmp = RB_LEFT(parent, field); \ + } \ + if ((RB_LEFT(tmp, field) == NULL || \ + RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) &&\ + (RB_RIGHT(tmp, field) == NULL || \ + RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) {\ + RB_COLOR(tmp, field) = RB_RED; \ + elm = parent; \ + parent = RB_PARENT(elm, field); \ + } else { \ + if (RB_LEFT(tmp, field) == NULL || \ + RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) {\ + struct type *oright; \ + if ((oright = RB_RIGHT(tmp, field)))\ + RB_COLOR(oright, field) = RB_BLACK;\ + RB_COLOR(tmp, field) = RB_RED; \ + RB_ROTATE_LEFT(head, tmp, oright, field);\ + tmp = RB_LEFT(parent, field); \ + } \ + RB_COLOR(tmp, field) = RB_COLOR(parent, field);\ + RB_COLOR(parent, field) = RB_BLACK; \ + if (RB_LEFT(tmp, field)) \ + RB_COLOR(RB_LEFT(tmp, field), field) = RB_BLACK;\ + RB_ROTATE_RIGHT(head, parent, tmp, field);\ + elm = RB_ROOT(head); \ + break; \ + } \ + } \ + } \ + if (elm) \ + RB_COLOR(elm, field) = RB_BLACK; \ +} \ + \ +attr struct type * \ +name##_RB_REMOVE(struct name *head, struct type *elm) \ +{ \ + struct type *child, *parent, *old = elm; \ + int color; \ + if (RB_LEFT(elm, field) == NULL) \ + child = RB_RIGHT(elm, field); \ + else if (RB_RIGHT(elm, field) == NULL) \ + child = RB_LEFT(elm, field); \ + else { \ + struct type *left; \ + elm = RB_RIGHT(elm, field); \ + while ((left = RB_LEFT(elm, field))) \ + elm = left; \ + child = RB_RIGHT(elm, field); \ + parent = RB_PARENT(elm, field); \ + color = RB_COLOR(elm, field); \ + if (child) \ + RB_PARENT(child, field) = parent; \ + if (parent) { \ + if (RB_LEFT(parent, field) == elm) \ + RB_LEFT(parent, field) = child; \ + else \ + RB_RIGHT(parent, field) = child; \ + RB_AUGMENT(parent); \ + } else \ + RB_ROOT(head) = child; \ + if (RB_PARENT(elm, field) == old) \ + parent = elm; \ + (elm)->field = (old)->field; \ + if (RB_PARENT(old, field)) { \ + if (RB_LEFT(RB_PARENT(old, field), field) == old)\ + RB_LEFT(RB_PARENT(old, field), field) = elm;\ + else \ + RB_RIGHT(RB_PARENT(old, field), field) = elm;\ + RB_AUGMENT(RB_PARENT(old, field)); \ + } else \ + RB_ROOT(head) = elm; \ + RB_PARENT(RB_LEFT(old, field), field) = elm; \ + if (RB_RIGHT(old, field)) \ + RB_PARENT(RB_RIGHT(old, field), field) = elm; \ + if (parent) { \ + left = parent; \ + do { \ + RB_AUGMENT(left); \ + } while ((left = RB_PARENT(left, field))); \ + } \ + goto color; \ + } \ + parent = RB_PARENT(elm, field); \ + color = RB_COLOR(elm, field); \ + if (child) \ + RB_PARENT(child, field) = parent; \ + if (parent) { \ + if (RB_LEFT(parent, field) == elm) \ + RB_LEFT(parent, field) = child; \ + else \ + RB_RIGHT(parent, field) = child; \ + RB_AUGMENT(parent); \ + } else \ + RB_ROOT(head) = child; \ +color: \ + if (color == RB_BLACK) \ + name##_RB_REMOVE_COLOR(head, parent, child); \ + return (old); \ +} \ + \ +/* Inserts a node into the RB tree */ \ +attr struct type * \ +name##_RB_INSERT(struct name *head, struct type *elm) \ +{ \ + struct type *tmp; \ + struct type *parent = NULL; \ + int comp = 0; \ + tmp = RB_ROOT(head); \ + while (tmp) { \ + parent = tmp; \ + comp = (cmp)(elm, parent); \ + if (comp < 0) \ + tmp = RB_LEFT(tmp, field); \ + else if (comp > 0) \ + tmp = RB_RIGHT(tmp, field); \ + else \ + return (tmp); \ + } \ + RB_SET(elm, parent, field); \ + if (parent != NULL) { \ + if (comp < 0) \ + RB_LEFT(parent, field) = elm; \ + else \ + RB_RIGHT(parent, field) = elm; \ + RB_AUGMENT(parent); \ + } else \ + RB_ROOT(head) = elm; \ + name##_RB_INSERT_COLOR(head, elm); \ + return (NULL); \ +} \ + \ +/* Finds the node with the same key as elm */ \ +attr struct type * \ +name##_RB_FIND(struct name *head, struct type *elm) \ +{ \ + struct type *tmp = RB_ROOT(head); \ + int comp; \ + while (tmp) { \ + comp = cmp(elm, tmp); \ + if (comp < 0) \ + tmp = RB_LEFT(tmp, field); \ + else if (comp > 0) \ + tmp = RB_RIGHT(tmp, field); \ + else \ + return (tmp); \ + } \ + return (NULL); \ +} \ + \ +/* Finds the first node greater than or equal to the search key */ \ +attr struct type * \ +name##_RB_NFIND(struct name *head, struct type *elm) \ +{ \ + struct type *tmp = RB_ROOT(head); \ + struct type *res = NULL; \ + int comp; \ + while (tmp) { \ + comp = cmp(elm, tmp); \ + if (comp < 0) { \ + res = tmp; \ + tmp = RB_LEFT(tmp, field); \ + } \ + else if (comp > 0) \ + tmp = RB_RIGHT(tmp, field); \ + else \ + return (tmp); \ + } \ + return (res); \ +} \ + \ +/* ARGSUSED */ \ +attr struct type * \ +name##_RB_NEXT(struct type *elm) \ +{ \ + if (RB_RIGHT(elm, field)) { \ + elm = RB_RIGHT(elm, field); \ + while (RB_LEFT(elm, field)) \ + elm = RB_LEFT(elm, field); \ + } else { \ + if (RB_PARENT(elm, field) && \ + (elm == RB_LEFT(RB_PARENT(elm, field), field))) \ + elm = RB_PARENT(elm, field); \ + else { \ + while (RB_PARENT(elm, field) && \ + (elm == RB_RIGHT(RB_PARENT(elm, field), field)))\ + elm = RB_PARENT(elm, field); \ + elm = RB_PARENT(elm, field); \ + } \ + } \ + return (elm); \ +} \ + \ +/* ARGSUSED */ \ +attr struct type * \ +name##_RB_PREV(struct type *elm) \ +{ \ + if (RB_LEFT(elm, field)) { \ + elm = RB_LEFT(elm, field); \ + while (RB_RIGHT(elm, field)) \ + elm = RB_RIGHT(elm, field); \ + } else { \ + if (RB_PARENT(elm, field) && \ + (elm == RB_RIGHT(RB_PARENT(elm, field), field))) \ + elm = RB_PARENT(elm, field); \ + else { \ + while (RB_PARENT(elm, field) && \ + (elm == RB_LEFT(RB_PARENT(elm, field), field)))\ + elm = RB_PARENT(elm, field); \ + elm = RB_PARENT(elm, field); \ + } \ + } \ + return (elm); \ +} \ + \ +attr struct type * \ +name##_RB_MINMAX(struct name *head, int val) \ +{ \ + struct type *tmp = RB_ROOT(head); \ + struct type *parent = NULL; \ + while (tmp) { \ + parent = tmp; \ + if (val < 0) \ + tmp = RB_LEFT(tmp, field); \ + else \ + tmp = RB_RIGHT(tmp, field); \ + } \ + return (parent); \ +} + +#define RB_NEGINF -1 +#define RB_INF 1 + +#define RB_INSERT(name, x, y) name##_RB_INSERT(x, y) +#define RB_REMOVE(name, x, y) name##_RB_REMOVE(x, y) +#define RB_FIND(name, x, y) name##_RB_FIND(x, y) +#define RB_NFIND(name, x, y) name##_RB_NFIND(x, y) +#define RB_NEXT(name, x, y) name##_RB_NEXT(y) +#define RB_PREV(name, x, y) name##_RB_PREV(y) +#define RB_MIN(name, x) name##_RB_MINMAX(x, RB_NEGINF) +#define RB_MAX(name, x) name##_RB_MINMAX(x, RB_INF) + +#define RB_FOREACH(x, name, head) \ + for ((x) = RB_MIN(name, head); \ + (x) != NULL; \ + (x) = name##_RB_NEXT(x)) + +#define RB_FOREACH_SAFE(x, name, head, y) \ + for ((x) = RB_MIN(name, head); \ + ((x) != NULL) && ((y) = name##_RB_NEXT(x), 1); \ + (x) = (y)) + +#define RB_FOREACH_REVERSE(x, name, head) \ + for ((x) = RB_MAX(name, head); \ + (x) != NULL; \ + (x) = name##_RB_PREV(x)) + +#define RB_FOREACH_REVERSE_SAFE(x, name, head, y) \ + for ((x) = RB_MAX(name, head); \ + ((x) != NULL) && ((y) = name##_RB_PREV(x), 1); \ + (x) = (y)) + +#endif /* _SYS_TREE_H_ */ diff --git a/src/utils.c b/src/utils.c new file mode 100644 index 0000000..e3ffbe0 --- /dev/null +++ b/src/utils.c @@ -0,0 +1,219 @@ +/* The MIT License (MIT) + * + * Copyright (c) 2016 Stefano Trettel + * + * Software repository: MoonGLFW, https://github.com/stetre/moonglfw + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "internal.h" + +int noprintf(const char *fmt, ...) + { (void)fmt; return 0; } + +int notavailable(lua_State *L, ...) + { NOT_AVAILABLE; } + + +/*------------------------------------------------------------------------------* + | Custom luaL_checkxxx() style functions | + *------------------------------------------------------------------------------*/ + +int checkoption_hint(lua_State *L, int arg, const char *def, const char *const lst[]) +/* Variant of luaL_checkoption(), with an added hint in the error message */ + { + const char *hint = NULL; + const char *name = (def) ? luaL_optstring(L, arg, def) : luaL_checkstring(L, arg); + int i; + for (i=0; lst[i]; i++) + if (strcmp(lst[i], name) == 0) return i; + + if(lua_checkstack(L, i*2)) + { + for(i=0; lst[i]; i++) + { + lua_pushfstring(L, "'%s'", lst[i]); + lua_pushstring(L, "|"); + } + i = i*2; + if(i>0) + { + lua_pop(L, 1); /* the last separator */ + lua_concat(L, i-1); + hint = lua_tostring(L, -1); + } + } + if(hint) + return luaL_argerror(L, arg, lua_pushfstring(L, + "invalid option '%s', valid options are: %s", name, hint)); + return luaL_argerror(L, arg, lua_pushfstring(L, "invalid option '%s'", name)); + } + + +GLboolean checkboolean(lua_State *L, int arg) + { + if(!lua_isboolean(L, arg)) + return (GLboolean)luaL_argerror(L, arg, "boolean expected"); + return lua_toboolean(L, arg) ? GL_TRUE : GL_FALSE; + } + +int testwindow(lua_State *L, int arg, win_t **win_) + { + int id; + win_t *win; + if(lua_isnoneornil(L, arg)) + return 0; + id = luaL_checkinteger(L, arg); + win = win_search(id); + if(!win) + luaL_error(L, "invalid window id"); + if(win_) *win_ = win; + return 1; + } + +win_t *checkwindow(lua_State *L, int arg) + { + int id = luaL_checkinteger(L, arg); + win_t *win = win_search(id); + if(!win) + luaL_error(L, "invalid window id"); + return win; + } + +int testmonitor(lua_State *L, int arg, mon_t **mon_) + { + int id; + mon_t *mon; + if(lua_isnoneornil(L, arg)) + return 0; + id = luaL_checkinteger(L, arg); + mon = mon_search(id); + if(!mon) + luaL_error(L, "invalid monitor id"); + if(mon_) *mon_ = mon; + return 1; + } + + +mon_t *checkmonitor(lua_State *L, int arg) + { + int id = luaL_checkinteger(L, arg); + mon_t *mon = mon_search(id); + if(!mon) + luaL_error(L, "invalid monitor id"); + return mon; + } + + +int testcursor(lua_State *L, int arg, cur_t **cur_) + { + int id; + cur_t *cur; + if(lua_isnoneornil(L, arg)) + return 0; + id = luaL_checkinteger(L, arg); + cur = cur_search(id); + if(!cur) + luaL_error(L, "invalid cursor id"); + if(cur_) *cur_ = cur; + return 1; + } + + +cur_t *checkcursor(lua_State *L, int arg) + { + int id = luaL_checkinteger(L, arg); + cur_t *cur = cur_search(id); + if(!cur) + luaL_error(L, "invalid cursor id"); + return cur; + } + + +int pushvidmode(lua_State *L, const GLFWvidmode *mode) + { + + int table; + lua_newtable(L); + table = lua_gettop(L); +#define Setfield(x, name) \ + do { lua_pushinteger(L, mode->x); lua_setfield(L, table, name); } while(0) + Setfield(width, "width"); + Setfield(height, "height"); + Setfield(redBits,"red_bits"); + Setfield(greenBits,"green_bits"); + Setfield(blueBits,"blue_bits"); + Setfield(refreshRate,"refresh_rate"); +#undef Setfield + return 1; + } + +int pushgammaramp(lua_State *L, const GLFWgammaramp *ramp) + { + unsigned int i; + int table; +#define Setfield(x, name) do { \ + lua_newtable(L); \ + table = lua_gettop(L); \ + for(i=0; isize; i++) \ + { \ + lua_pushinteger(L, ramp->x[i]); \ + lua_seti(L, table, i+1); \ + } \ +} while(0) + Setfield(red,"red"); + Setfield(green,"green"); + Setfield(blue,"blue"); +#undef Setfield + return 3; + } + +int checkgammaramp(lua_State *L, int arg, GLFWgammaramp *ramp) + { + unsigned short i; +#define R arg +#define G arg+1 +#define B arg+2 + if(!lua_istable(L,R)) + return luaL_argerror(L, R, "table expected"); + if(!lua_istable(L,G)) + return luaL_argerror(L, G, "table expected"); + if(!lua_istable(L,B)) + return luaL_argerror(L, B, "table expected"); + ramp->size = luaL_len(L, R); + if(ramp->size == 0) + return luaL_argerror(L, R, "empty array"); + if( (luaL_len(L, G) != ramp->size) || (luaL_len(L, B) != ramp->size)) + return luaL_argerror(L, R, "red, green and blue arrays do not have the same length"); + ramp->red = (unsigned short*)malloc(ramp->size * sizeof(unsigned short)); + ramp->green = (unsigned short*)malloc(ramp->size * sizeof(unsigned short)); + ramp->blue = (unsigned short*)malloc(ramp->size * sizeof(unsigned short)); + for(i=0; i < ramp->size; i++) + { + lua_geti(L, R, i+1); ramp->red[i] = luaL_checkinteger(L, -1); lua_pop(L, 1); + lua_geti(L, G, i+1); ramp->green[i] = luaL_checkinteger(L, -1); lua_pop(L, 1); + lua_geti(L, B, i+1); ramp->blue[i] = luaL_checkinteger(L, -1); lua_pop(L, 1); + } + return 0; +#undef R +#undef G +#undef B + } + diff --git a/src/win.c b/src/win.c new file mode 100644 index 0000000..e583a44 --- /dev/null +++ b/src/win.c @@ -0,0 +1,145 @@ +/* The MIT License (MIT) + * + * Copyright (c) 2016 Stefano Trettel + * + * Software repository: MoonGLFW, https://github.com/stetre/moonglfw + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + +/**************************************************************************** + * Window database * + ****************************************************************************/ + +#include "internal.h" + +static int cmp(win_t *win1, win_t *win2) /* the compare function */ + { return (win1->id < win2->id ? -1 : win1->id > win2->id); } + +static RB_HEAD(wintree_s, win_s) Head = RB_INITIALIZER(&Head); + +RB_PROTOTYPE_STATIC(wintree_s, win_s, entry, cmp) +RB_GENERATE_STATIC(wintree_s, win_s, entry, cmp) + +static win_t *win_remove(win_t *win) + { return RB_REMOVE(wintree_s, &Head, win); } +static win_t *win_insert(win_t *win) + { return RB_INSERT(wintree_s, &Head, win); } +win_t *win_search(int id) + { win_t tmp; tmp.id = id; return RB_FIND(wintree_s, &Head, &tmp); } +win_t *win_first(int id) + { win_t tmp; tmp.id = id; return RB_NFIND(wintree_s, &Head, &tmp); } +win_t *win_next(win_t *win) + { return RB_NEXT(wintree_s, &Head, win); } +#if 0 +win_t *win_prev(win_t *win) + { return RB_PREV(wintree_s, &Head, win); } +win_t *win_min(void) + { return RB_MIN(wintree_s, &Head); } +win_t *win_max(void) + { return RB_MAX(wintree_s, &Head); } +win_t *win_root(void) + { return RB_ROOT(&Head); } +#endif +win_t *win_new(void) + { + win_t *win; + int id = id_new(); + if(id == -1) + return NULL; + if((win = (win_t*)malloc(sizeof(win_t))) == NULL) + { id_free(id); return NULL; } + memset(win, 0, sizeof(win_t)); + win->id = id; + if(win_search(win->id)) + { free(win); id_free(id); return NULL; } + win->WindowPos = LUA_NOREF; + win->WindowSize = LUA_NOREF; + win->WindowClose = LUA_NOREF; + win->WindowRefresh = LUA_NOREF; + win->WindowFocus = LUA_NOREF; + win->WindowIconify = LUA_NOREF; + win->FramebufferSize = LUA_NOREF; + win->Key = LUA_NOREF; + win->Char = LUA_NOREF; + win->CharMods = LUA_NOREF; + win->MouseButton = LUA_NOREF; + win->CursorPos = LUA_NOREF; + win->CursorEnter = LUA_NOREF; + win->Scroll = LUA_NOREF; + win->Drop = LUA_NOREF; + win_insert(win); + return win; + } + +void win_free(win_t* win) + { + if(win_search(win->id) == win) + { + /* release callback references */ + CALLBACK_UNREF(win->WindowPos); + CALLBACK_UNREF(win->WindowSize); + CALLBACK_UNREF(win->WindowClose); + CALLBACK_UNREF(win->WindowRefresh); + CALLBACK_UNREF(win->WindowFocus); + CALLBACK_UNREF(win->WindowIconify); + CALLBACK_UNREF(win->FramebufferSize); + CALLBACK_UNREF(win->Key); + CALLBACK_UNREF(win->Char); + CALLBACK_UNREF(win->CharMods); + CALLBACK_UNREF(win->MouseButton); + CALLBACK_UNREF(win->CursorPos); + CALLBACK_UNREF(win->CursorEnter); + CALLBACK_UNREF(win->Scroll); + CALLBACK_UNREF(win->Drop); + win_remove(win); + } + id_free(win->id); + free(win); + } + +void win_free_all(void) + { + win_t *win; + while((win = win_first(0))) + win_free(win); + } + +win_t* win_check(lua_State *L, int arg) + { + int id = luaL_checkinteger(L, arg); + win_t *win = win_search(id); + if(!win) + luaL_error(L, "invalid window id"); + return win; + } + +/* +win_t *win_current(lua_State *L) + { + win_t *win; + int id; + if((id = glfwGetWindow()) < 1) + luaL_error(L, "no current window"); + if((win = win_search(id)) == NULL) + luaL_error(L, "unknown current window"); + return win; + } +*/ diff --git a/src/window.c b/src/window.c new file mode 100644 index 0000000..03e6400 --- /dev/null +++ b/src/window.c @@ -0,0 +1,252 @@ +/* The MIT License (MIT) + * + * Copyright (c) 2016 Stefano Trettel + * + * Software repository: MoonGLFW, https://github.com/stetre/moonglfw + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "internal.h" + +static int CreateWindow(lua_State *L) + { + win_t *win, *share_win=NULL; + mon_t *mon; + intptr_t id; + int width = luaL_checkinteger(L, 1); + int height = luaL_checkinteger(L, 2); + const char* title = luaL_optstring(L, 3, ""); + GLFWmonitor* monitor = testmonitor(L, 4, &mon) ? mon->monitor : NULL; + GLFWwindow* share = testwindow(L, 5, &share_win) ? share_win->window : NULL; + + win = win_new(); + if(!win) + return luaL_error(L, "cannot create window"); + + win->window = glfwCreateWindow(width, height, title, monitor, share); + if(win->window == NULL) + { + win_free(win); + return luaL_error(L, "cannot create window"); + } + /* this will allow us to retrieve the win_t* from the GLFWwindow*: */ + id = win->id; + win->share_id = share_win ? share_win->id : -1; + glfwSetWindowUserPointer(win->window, (void*)id); + lua_pushinteger(L, win->id); + return 1; + } + +static int DestroyWindow(lua_State *L) + { + win_t *win = checkwindow(L, 1); + glfwDestroyWindow(win->window); + win_free(win); + return 0; + } + +static int PollEvents(lua_State *L) + { + (void)L; + glfwPollEvents(); + return 0; + } + +static int WaitEvents(lua_State *L) + { + (void)L; + glfwWaitEvents(); + return 0; + } + +static int PostEmptyEvent(lua_State *L) + { + (void)L; + glfwPostEmptyEvent(); + return 0; + } + +static int SwapBuffers(lua_State *L) + { + win_t *win = checkwindow(L, 1); + glfwSwapBuffers(win->window); + return 0; + } + +static int WindowShouldClose(lua_State *L) + { + win_t *win = checkwindow(L, 1); + lua_pushboolean(L, glfwWindowShouldClose(win->window)); + return 1; + } + + +static int SetWindowShouldClose(lua_State *L) + { + win_t *win = checkwindow(L, 1); + int value = checkboolean(L, 2); + glfwSetWindowShouldClose(win->window, value); + return 0; + } + +static int SetWindowTitle(lua_State *L) + { + win_t *win = checkwindow(L, 1); + const char *title = luaL_optstring(L, 2, ""); + glfwSetWindowTitle(win->window, title); + return 0; + } + +static int GetWindowPos(lua_State *L) + { + int xpos, ypos; + win_t *win = checkwindow(L, 1); + glfwGetWindowPos(win->window, &xpos, &ypos); + lua_pushinteger(L, xpos); + lua_pushinteger(L, ypos); + return 2; + } + +static int SetWindowPos(lua_State *L) + { + win_t *win = checkwindow(L, 1); + int xpos = luaL_checkinteger(L, 2); + int ypos = luaL_checkinteger(L, 3); + glfwSetWindowPos(win->window, xpos, ypos); + return 0; + } + +static int GetWindowSize(lua_State *L) + { + int width, height; + win_t *win = checkwindow(L, 1); + glfwGetWindowSize(win->window, &width, &height); + lua_pushinteger(L, width); + lua_pushinteger(L, height); + return 2; + } + +static int SetWindowSize(lua_State *L) + { + win_t *win = checkwindow(L, 1); + int width = luaL_checkinteger(L, 2); + int height = luaL_checkinteger(L, 3); + glfwSetWindowSize(win->window, width, height); + return 0; + } + +static int GetFramebufferSize(lua_State *L) + { + int width, height; + win_t *win = checkwindow(L, 1); + glfwGetFramebufferSize(win->window, &width, &height); + lua_pushinteger(L, width); + lua_pushinteger(L, height); + return 2; + } + +static int GetWindowFrameSize(lua_State *L) + { + int left, top, right, bottom; + win_t *win = checkwindow(L, 1); + (void)L; + glfwGetWindowFrameSize(win->window, &left, &top, &right, &bottom); + lua_pushinteger(L, left); + lua_pushinteger(L, top); + lua_pushinteger(L, right); + lua_pushinteger(L, bottom); + return 4; + } + +static int IconifyWindow(lua_State *L) + { + win_t *win = checkwindow(L, 1); + glfwIconifyWindow(win->window); + return 0; + } + +static int RestoreWindow(lua_State *L) + { + win_t *win = checkwindow(L, 1); + glfwRestoreWindow(win->window); + return 0; + } + +static int ShowWindow(lua_State *L) + { + win_t *win = checkwindow(L, 1); + glfwShowWindow(win->window); + return 0; + } + +static int HideWindow(lua_State *L) + { + win_t *win = checkwindow(L, 1); + glfwHideWindow(win->window); + return 0; + } + +static int GetWindowMonitor(lua_State *L) + { + int id; + win_t *win = checkwindow(L, 1); + GLFWmonitor *monitor = glfwGetWindowMonitor(win->window); + if(!monitor) + return 0; + id = monitorAdd(L, monitor); + lua_pushinteger(L, id); + return 1; + } + + +/*------------------------------------------------------------------------------* + | Registration | + *------------------------------------------------------------------------------*/ + +static const struct luaL_Reg Functions[] = + { + { "create_window", CreateWindow }, + { "destroy_window", DestroyWindow }, + { "poll_events", PollEvents }, + { "wait_events", WaitEvents }, + { "post_empty_event", PostEmptyEvent }, + { "swap_buffers", SwapBuffers }, + { "window_should_close", WindowShouldClose }, + { "set_window_should_close", SetWindowShouldClose }, + { "set_window_title", SetWindowTitle }, + { "get_window_pos", GetWindowPos }, + { "set_window_pos", SetWindowPos }, + { "get_window_size", GetWindowSize }, + { "set_window_size", SetWindowSize }, + { "get_framebuffer_size", GetFramebufferSize }, + { "get_window_frame_size", GetWindowFrameSize }, + { "iconify_window", IconifyWindow }, + { "restore_window", RestoreWindow }, + { "show_window", ShowWindow }, + { "hide_window", HideWindow }, + { "get_window_monitor", GetWindowMonitor }, + { NULL, NULL } /* sentinel */ + }; + +void moonglfw_open_window(lua_State *L) + { + luaL_setfuncs(L, Functions, 0); + } + diff --git a/thirdparty/asciidoctor-styles-license b/thirdparty/asciidoctor-styles-license new file mode 100644 index 0000000..704a811 --- /dev/null +++ b/thirdparty/asciidoctor-styles-license @@ -0,0 +1,55 @@ +The CSS used for the MoonGLFW Reference Manual is taken from the +Asciidoctor styles project +(https://github.com/asciidoctor/asciidoctor-stylesheet-factory ). + +Below is a copy of the Asciidoctor styles copyright notice. + +Stefano Trettel + +======================================================================== + +Asciidoctor styles +------------------ + +Copyright (c) 2013 Dan Allen + +MIT License + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +Other licensed work +------------------- + +- Foundation 4 by Zurb, on which the themes are built, is licensed under the + Apache License, v2.0: + + http://apache.org/licenses/LICENSE-2.0 + http://foundation.zurb.com + +- The riak theme is derived from the Riak documentation theme by Basho, + licensed under the Creative Commons Attribution 3.0 Unported License: + + http://creativecommons.org/licenses/by/3.0/us + http://docs.basho.org + +- The iconic theme is inspired by O'Reilly typography and Atlas manual. + + http://oreilly.com diff --git a/thirdparty/openbsd-tree-license b/thirdparty/openbsd-tree-license new file mode 100644 index 0000000..c6f79f4 --- /dev/null +++ b/thirdparty/openbsd-tree-license @@ -0,0 +1,33 @@ +The src/tree.h module is taken from: +http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/sys/sys/tree.h + +Below is a copy of the copyright notice included in the module. + +Stefano Trettel + +=========================================================================== +/* + * Copyright 2002 Niels Provos + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + */ + diff --git a/thirdparty/powered-by-lua-license b/thirdparty/powered-by-lua-license new file mode 100644 index 0000000..2ead0f1 --- /dev/null +++ b/thirdparty/powered-by-lua-license @@ -0,0 +1,20 @@ +The 'powered by Lua' logo (doc/powered-by-lua.gif ) is taken from: +http://www.lua.org/images . + +Below is a copy of the copyright notice from the same web-page. + +Stefano Trettel + +=========================================================================== +Copyright © 1998 Lua.org. Graphic design by Alexandre Nakonechnyj. + +Permission is hereby granted, without written agreement and without license +or royalty fees, to use, copy, and distribute this logo for any purpose, +including commercial applications, subject to the following conditions: + +- The origin of this logo must not be misrepresented; you must not claim that +you drew the original logo. +- The only modification you can make is to adapt the orbiting text to your +product name. +- The logo can be used in any scale as long as the relative proportions of its +elements are maintained.