├── _doc ├── static ├── form ├── slider ├── spinbox ├── winstatic ├── main ├── export │ ├── weightlist3.sh │ ├── writewidths.c │ ├── weightlist1.sh │ ├── weightlist2.sh │ ├── coretext │ ├── writewidths.processed │ ├── writewidths.out │ ├── ttfixedtest.go │ ├── writewidths.s │ └── ctwidthscombined ├── mainsteps ├── areahandler ├── windowmovesize ├── drawtext └── names.md ├── _abort ├── oldhaiku.tgz └── windowevents │ ├── ui.h │ └── page15.c ├── _notes ├── cplusplus ├── highDPI ├── dialogs ├── textSelections ├── caretWidths ├── winARM64 ├── windowsPrinting ├── tableNotes ├── winflags ├── darwinNSAlertIcons ├── rebarstuff ├── darwinAutoLayout ├── i18n ├── macosAlternateHiDPI ├── windowsHighDPI └── OS2 ├── _future ├── verticaltext │ ├── common_attrlist.c │ ├── ui.h │ ├── attrstr_unix.c │ ├── attrstr_windows.cpp │ ├── drawtext_example.c │ ├── README │ └── attrstr_darwin.m ├── textlanguageattr │ ├── common_attrlist.c │ ├── ui.h │ ├── README │ ├── attrstr_unix.c │ ├── attrstr_windows.cpp │ ├── attrstr_darwin.m │ └── drawtext_example.c └── unittest │ └── checklist_attrstr ├── _wip ├── examples_drawtext │ ├── httext.gz │ └── drawtext.h ├── rules.unix ├── rules.darwin ├── examples_drawtext_CMakeLists.txt ├── attrstr_metrics │ ├── common_OLD_uipriv_attrstr.h │ └── numlinesbyterange ├── sv │ ├── sourcelist.nots │ ├── normal.nots │ ├── outlineview.nots │ ├── tableview.nots │ ├── textview.nots │ ├── sourcelist │ ├── normal │ ├── outlineview │ ├── tableview │ └── textview └── table │ ├── ui.h │ ├── test_page9.c │ └── unix_table.c ├── examples ├── controlgallery │ ├── unix.png │ ├── darwin.png │ └── windows.png ├── resources.rc ├── example.manifest ├── example.static.manifest ├── timer │ └── main.c ├── meson.build └── cpp-multithread │ └── main.cpp ├── test ├── images │ ├── andlabs_16x16test_24june2016.png │ ├── andlabs_32x32test_24june2016.png │ ├── tango-icon-theme-0.8.90_16x16_x-office-spreadsheet.png │ ├── tango-icon-theme-0.8.90_32x32_x-office-spreadsheet.png │ └── gen.go ├── resources.rc ├── page7.c ├── test.manifest ├── page8.c ├── meson.build ├── test.static.manifest ├── page11.c ├── page12.c ├── page7b.c ├── page3.c ├── test.h └── page5.c ├── windows ├── notes ├── resources.rc ├── _uipriv_migrate.hpp ├── _rc2bin │ ├── build.bat │ ├── resources.hpp │ ├── libui.manifest │ ├── main.cpp │ └── winapi.hpp ├── draw.hpp ├── areautil.cpp ├── resources.hpp ├── libui.manifest ├── opentype.cpp ├── area.hpp ├── label.cpp ├── alloc.cpp ├── winpublic.cpp ├── separator.cpp ├── winapi.hpp ├── graphemes.cpp └── sizing.cpp ├── azure-pipelines ├── setup-python3.yml ├── linux-install-gtk-dev.yml ├── build.yml ├── configure.yml ├── install-latest-meson-ninja.yml ├── darwin-install-ninja.yml ├── windows-install-ninja.yml ├── vs2015-install-python3.yml ├── collapse.awk ├── linux-386-install-gtk-dev.yml ├── artifacts.yml └── windows-artifacts.yml ├── darwin ├── draw.h ├── text.m ├── debug.m ├── table.h ├── util.m ├── label.m ├── separator.m ├── undocumented.m ├── OLD_table.m ├── map.m ├── meson.build ├── graphemes.m ├── progressbar.m ├── future.m ├── scrollview.m └── alloc.m ├── common ├── userbugs.c ├── meson.build ├── shouldquit.c ├── OLD_table.c ├── debug.c ├── table.h ├── controlsigs.h ├── matrix.c ├── tablemodel.c ├── attrstr.h ├── tablevalue.c └── control.c ├── unix ├── util.c ├── text.c ├── draw.h ├── debug.c ├── control.c ├── label.c ├── separator.c ├── opentype.c ├── table.h ├── attrstr.h ├── button.c ├── meson.build ├── combobox.c ├── slider.c ├── graphemes.c ├── spinbox.c ├── progressbar.c ├── checkbox.c ├── colorbutton.c ├── future.c ├── fontbutton.c ├── stddialogs.c ├── alloc.c ├── editablecombo.c ├── uipriv_unix.h ├── tab.c └── entry.c ├── LICENSE └── stats.osxdrawtext /_doc/static: -------------------------------------------------------------------------------- 1 | comctl6 2 | libui.res 3 | -------------------------------------------------------------------------------- /_doc/form: -------------------------------------------------------------------------------- 1 | hiding a control also hides its label 2 | -------------------------------------------------------------------------------- /_doc/slider: -------------------------------------------------------------------------------- 1 | if min >= max then they are swapped 2 | -------------------------------------------------------------------------------- /_doc/spinbox: -------------------------------------------------------------------------------- 1 | if min >= max then they are swapped 2 | -------------------------------------------------------------------------------- /_doc/winstatic: -------------------------------------------------------------------------------- 1 | libui uses resources starting at 29000 2 | -------------------------------------------------------------------------------- /_abort/oldhaiku.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andlabs/libui/HEAD/_abort/oldhaiku.tgz -------------------------------------------------------------------------------- /_notes/cplusplus: -------------------------------------------------------------------------------- 1 | https://blogs.msdn.microsoft.com/oldnewthing/20181226-00/?p=100565 2 | -------------------------------------------------------------------------------- /_doc/main: -------------------------------------------------------------------------------- 1 | after uiQuit or if uiShouldQuit returns nonzero, uiQueueMain's effect is undefined 2 | -------------------------------------------------------------------------------- /_notes/highDPI: -------------------------------------------------------------------------------- 1 | High DPI Displays | Qt 5.5 http://doc.qt.io/qt-5/highdpi.html bottom of page(?) 2 | -------------------------------------------------------------------------------- /_doc/export/weightlist3.sh: -------------------------------------------------------------------------------- 1 | # 21 october 2017 2 | sort -t$'\t' -k1,1 -k2,2 "$@" | 3 | column -t -s$'\t' 4 | -------------------------------------------------------------------------------- /_future/verticaltext/common_attrlist.c: -------------------------------------------------------------------------------- 1 | case uiAttributeVerticalForms: 2 | return boolsEqual(attr, spec); 3 | -------------------------------------------------------------------------------- /_wip/examples_drawtext/httext.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andlabs/libui/HEAD/_wip/examples_drawtext/httext.gz -------------------------------------------------------------------------------- /examples/controlgallery/unix.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andlabs/libui/HEAD/examples/controlgallery/unix.png -------------------------------------------------------------------------------- /examples/controlgallery/darwin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andlabs/libui/HEAD/examples/controlgallery/darwin.png -------------------------------------------------------------------------------- /_doc/export/writewidths.c: -------------------------------------------------------------------------------- 1 | // 22 october 2017 2 | extern int realMain(void); 3 | int main(void) { return realMain(); } 4 | -------------------------------------------------------------------------------- /_future/verticaltext/ui.h: -------------------------------------------------------------------------------- 1 | // TODO rename to uiAttributeVertical? 2 | uiAttributeVerticalForms, // 0 = off, 1 = on 3 | -------------------------------------------------------------------------------- /_wip/rules.unix: -------------------------------------------------------------------------------- 1 | every rule in ui_unix.h 2 | SetParent must be followed by SetContainer 3 | TODO can child cache it? 4 | -------------------------------------------------------------------------------- /examples/controlgallery/windows.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andlabs/libui/HEAD/examples/controlgallery/windows.png -------------------------------------------------------------------------------- /test/images/andlabs_16x16test_24june2016.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andlabs/libui/HEAD/test/images/andlabs_16x16test_24june2016.png -------------------------------------------------------------------------------- /test/images/andlabs_32x32test_24june2016.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andlabs/libui/HEAD/test/images/andlabs_32x32test_24june2016.png -------------------------------------------------------------------------------- /_doc/mainsteps: -------------------------------------------------------------------------------- 1 | the function passed to mainsteps must not return until uiQuit itself has been called; otherwise the results are undefined 2 | -------------------------------------------------------------------------------- /windows/notes: -------------------------------------------------------------------------------- 1 | DIALOGS 2 | do not accelerate OK and Cancel buttons in dialogs 3 | http://blogs.msdn.com/b/oldnewthing/archive/2008/05/08/8467905.aspx 4 | -------------------------------------------------------------------------------- /_future/textlanguageattr/common_attrlist.c: -------------------------------------------------------------------------------- 1 | case uiAttributeLanguage: 2 | return asciiStringsEqualCaseFold((char *) (attr->spec.Value), (char *) (spec->Value)); 3 | -------------------------------------------------------------------------------- /azure-pipelines/setup-python3.yml: -------------------------------------------------------------------------------- 1 | # 4 april 2019 2 | 3 | steps: 4 | - task: UsePythonVersion@0 5 | inputs: 6 | versionSpec: '3.6' 7 | architecture: 'x64' 8 | -------------------------------------------------------------------------------- /azure-pipelines/linux-install-gtk-dev.yml: -------------------------------------------------------------------------------- 1 | # 7 april 2019 2 | 3 | steps: 4 | - script: | 5 | sudo apt-get install libgtk-3-dev 6 | displayName: 'Install GTK+ Dev Files' 7 | -------------------------------------------------------------------------------- /test/images/tango-icon-theme-0.8.90_16x16_x-office-spreadsheet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andlabs/libui/HEAD/test/images/tango-icon-theme-0.8.90_16x16_x-office-spreadsheet.png -------------------------------------------------------------------------------- /test/images/tango-icon-theme-0.8.90_32x32_x-office-spreadsheet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andlabs/libui/HEAD/test/images/tango-icon-theme-0.8.90_32x32_x-office-spreadsheet.png -------------------------------------------------------------------------------- /_notes/dialogs: -------------------------------------------------------------------------------- 1 | https://github.com/kusti8/proton-native/issues/47#issuecomment-373068947 2 | https://blogs.kde.org/2009/03/26/how-crash-almost-every-qtkde-application-and-how-fix-it-0 3 | -------------------------------------------------------------------------------- /_doc/export/weightlist1.sh: -------------------------------------------------------------------------------- 1 | # 21 october 2017 2 | gawk ' 3 | BEGIN { FS = "\t+" } 4 | !/float..as/ { next } 5 | { i = 0; if ($1 == "") i++ } 6 | (NF-i) != 2 { next } 7 | { print } 8 | ' "$@" 9 | -------------------------------------------------------------------------------- /_notes/textSelections: -------------------------------------------------------------------------------- 1 | http://www.catch22.net/tuts/transparent-text 2 | https://msdn.microsoft.com/en-us/library/windows/desktop/ms724371(v=vs.85).aspx 3 | TODO which color did I want from this list 4 | -------------------------------------------------------------------------------- /_notes/caretWidths: -------------------------------------------------------------------------------- 1 | UWP has this (TODO check its implementation to see if it matches ours) https://docs.microsoft.com/en-us/uwp/api/windows.ui.viewmanagement.uisettings#Windows_UI_ViewManagement_UISettings_CaretWidth 2 | -------------------------------------------------------------------------------- /_notes/winARM64: -------------------------------------------------------------------------------- 1 | http://www.os2museum.com/wp/windows-10-arm64-on-qemu/ 2 | https://docs.microsoft.com/en-us/windows/uwp/porting/apps-on-arm 3 | http://pete.akeo.ie/2017/05/compiling-desktop-arm-applications-with.html 4 | -------------------------------------------------------------------------------- /darwin/draw.h: -------------------------------------------------------------------------------- 1 | // 6 january 2017 2 | 3 | // TODO why do we still have this file; should we just split draw.m or not 4 | 5 | struct uiDrawContext { 6 | CGContextRef c; 7 | CGFloat height; // needed for text; see below 8 | }; 9 | -------------------------------------------------------------------------------- /common/userbugs.c: -------------------------------------------------------------------------------- 1 | // 22 may 2016 2 | #include "../ui.h" 3 | #include "uipriv.h" 4 | 5 | void uiUserBugCannotSetParentOnToplevel(const char *type) 6 | { 7 | uiprivUserBug("You cannot make a %s a child of another uiControl,", type); 8 | } 9 | -------------------------------------------------------------------------------- /_doc/export/weightlist2.sh: -------------------------------------------------------------------------------- 1 | # 21 october 2017 2 | gawk ' 3 | { 4 | gsub(/float..as\(/, "") 5 | gsub(/,/, "", $(NF - 1)) 6 | gsub(/\)$/, "") 7 | split($0, parts, /:/) 8 | print $(NF - 1) "\t" $NF "\t" parts[1] 9 | } 10 | ' "$@" 11 | -------------------------------------------------------------------------------- /_doc/areahandler: -------------------------------------------------------------------------------- 1 | Yes, you keep ownership of the uiAreaHandler. libui only cares about the address you give uiNewArea(); it doesn't copy anything. You can even use the same uiAreaHandler on multiple uiAreas, which is why you get the uiArea as a parameter in each function. 2 | -------------------------------------------------------------------------------- /azure-pipelines/build.yml: -------------------------------------------------------------------------------- 1 | # 5 april 2019 2 | 3 | parameters: 4 | beforeBuild: '' 5 | afterBuild: '' 6 | 7 | steps: 8 | - script: | 9 | ${{ parameters.beforeBuild }} 10 | ninja -C build -v 11 | ${{ parameters.afterBuild }} 12 | displayName: 'Build' 13 | -------------------------------------------------------------------------------- /unix/util.c: -------------------------------------------------------------------------------- 1 | // 18 april 2015 2 | #include "uipriv_unix.h" 3 | 4 | void uiprivSetMargined(GtkContainer *c, int margined) 5 | { 6 | if (margined) 7 | gtk_container_set_border_width(c, uiprivGTKXMargin); 8 | else 9 | gtk_container_set_border_width(c, 0); 10 | } 11 | -------------------------------------------------------------------------------- /_doc/windowmovesize: -------------------------------------------------------------------------------- 1 | you should never need to use these functions 2 | they are provided only for the cases when ABSOLUTELY NECESSARY 3 | the operating system may ignore your requests, for instance, if you are giving it invalid numbers or a size too small to fit; this is all system-defined 4 | -------------------------------------------------------------------------------- /_future/verticaltext/attrstr_unix.c: -------------------------------------------------------------------------------- 1 | PangoGravity gravity; 2 | 3 | case uiAttributeVerticalForms: 4 | gravity = PANGO_GRAVITY_SOUTH; 5 | if (spec->Value != 0) 6 | gravity = PANGO_GRAVITY_EAST; 7 | addattr(p, start, end, 8 | pango_attr_gravity_new(gravity)); 9 | break; 10 | -------------------------------------------------------------------------------- /unix/text.c: -------------------------------------------------------------------------------- 1 | // 9 april 2015 2 | #include "uipriv_unix.h" 3 | 4 | char *uiUnixStrdupText(const char *t) 5 | { 6 | return g_strdup(t); 7 | } 8 | 9 | void uiFreeText(char *t) 10 | { 11 | g_free(t); 12 | } 13 | 14 | int uiprivStricmp(const char *a, const char *b) 15 | { 16 | return strcasecmp(a, b); 17 | } 18 | -------------------------------------------------------------------------------- /_future/textlanguageattr/ui.h: -------------------------------------------------------------------------------- 1 | after UnderlineColor, before feature tags 2 | 3 | // TODO document that this will also enable language-specific font features (TODO on DirectWrite too?) 4 | // TODO document that this should be strict BCP 47 form (A-Z, a-z, 0-9, and -) for maximum compatibility 5 | uiAttributeLanguage, // BCP 47 string 6 | -------------------------------------------------------------------------------- /azure-pipelines/configure.yml: -------------------------------------------------------------------------------- 1 | # 5 april 2019 2 | 3 | parameters: 4 | beforeConfigure: '' 5 | defaultLibrary: 'must-be-set' 6 | 7 | steps: 8 | - script: | 9 | ${{ parameters.beforeConfigure }} 10 | meson setup build --buildtype=release --default-library=${{ parameters.defaultLibrary }} 11 | displayName: 'Configure' 12 | -------------------------------------------------------------------------------- /_abort/windowevents/ui.h: -------------------------------------------------------------------------------- 1 | // uiWindowSetTitle 2 | _UI_EXTERN void uiWindowPosition(uiWindow *w, int *x, int *y); 3 | _UI_EXTERN void uiWindowSetPosition(uiWindow *w, int x, int y); 4 | _UI_EXTERN void uiWindowCenter(uiWindow *w); 5 | _UI_EXTERN void uiWindowOnPositionChanged(uiWindow *w, void (*f)(uiWindow *, void *), void *data); 6 | // uiWindowContentSize 7 | -------------------------------------------------------------------------------- /_wip/rules.darwin: -------------------------------------------------------------------------------- 1 | every rule in ui_darwin.h 2 | SetParent must be followed by SetSuperview and SyncEnableState 3 | TODO can child cache it? 4 | adding a child must be followed by a call to SyncEnableState 5 | SyncEnableState() must call ShouldStopSyncEnableState() first thing 6 | Enable() and Disable() must call SyncEnableState() AFTER CHANGING WHAT Enabled() WILL RETURN 7 | -------------------------------------------------------------------------------- /azure-pipelines/install-latest-meson-ninja.yml: -------------------------------------------------------------------------------- 1 | # 4 april 2019 2 | 3 | # TODO remove ninja installation from non-Linux OSs and make the same ninja via pip change in the AppVeyor script 4 | 5 | steps: 6 | - script: | 7 | python -m pip install --upgrade pip setuptools wheel 8 | pip install meson ninja 9 | displayName: 'Install Latest Meson and Ninja' 10 | -------------------------------------------------------------------------------- /unix/draw.h: -------------------------------------------------------------------------------- 1 | // 5 may 2016 2 | 3 | // draw.c 4 | struct uiDrawContext { 5 | cairo_t *cr; 6 | GtkStyleContext *style; 7 | }; 8 | 9 | // drawpath.c 10 | extern void uiprivRunPath(uiDrawPath *p, cairo_t *cr); 11 | extern uiDrawFillMode uiprivPathFillMode(uiDrawPath *path); 12 | 13 | // drawmatrix.c 14 | extern void uiprivM2C(uiDrawMatrix *m, cairo_matrix_t *c); 15 | -------------------------------------------------------------------------------- /_future/textlanguageattr/README: -------------------------------------------------------------------------------- 1 | Removed because proper support on OS X doesn't come until 10.9 unless we use a font with an ltag table; none of the fonts I have come with ltag tables (none of the fonts on OS X do, or at least don't come with a sr entry in their ltag table, and OpenType has replaced ltag with what appears to be custom sub-tables of the GPOS and GSUB tables.) 2 | -------------------------------------------------------------------------------- /_doc/export/coretext: -------------------------------------------------------------------------------- 1 | font features are not provided by the collection and have to be added when asking for a font 2 | it does preserve when going from CTFont to CTFontDescriptor 3 | feature 17 has no flags in the header but can also hold small caps info 4 | if a feature is present, it is ignored; other features will still show up 5 | at least in the case of kLetterCaseTrait and kLowerCaseTrait 6 | -------------------------------------------------------------------------------- /common/meson.build: -------------------------------------------------------------------------------- 1 | # 23 march 2019 2 | 3 | libui_sources += [ 4 | 'common/attribute.c', 5 | 'common/attrlist.c', 6 | 'common/attrstr.c', 7 | 'common/areaevents.c', 8 | 'common/control.c', 9 | 'common/debug.c', 10 | 'common/matrix.c', 11 | 'common/opentype.c', 12 | 'common/shouldquit.c', 13 | 'common/tablemodel.c', 14 | 'common/tablevalue.c', 15 | 'common/userbugs.c', 16 | 'common/utf.c', 17 | ] 18 | -------------------------------------------------------------------------------- /unix/debug.c: -------------------------------------------------------------------------------- 1 | // 13 may 2016 2 | #include "uipriv_unix.h" 3 | 4 | // LONGTERM don't halt on release builds 5 | 6 | void uiprivRealBug(const char *file, const char *line, const char *func, const char *prefix, const char *format, va_list ap) 7 | { 8 | char *a, *b; 9 | 10 | a = g_strdup_printf("[libui] %s:%s:%s() %s", file, line, func, prefix); 11 | b = g_strdup_vprintf(format, ap); 12 | g_critical("%s%s", a, b); 13 | G_BREAKPOINT(); 14 | } 15 | -------------------------------------------------------------------------------- /_future/textlanguageattr/attrstr_unix.c: -------------------------------------------------------------------------------- 1 | PangoLanguage *lang; 2 | 3 | // language strings are specified as BCP 47: https://developer.gnome.org/pango/1.30/pango-Scripts-and-Languages.html#pango-language-from-string https://www.ietf.org/rfc/rfc3066.txt 4 | case uiAttributeLanguage: 5 | lang = pango_language_from_string((const char *) (spec->Value)); 6 | addattr(p, start, end, 7 | pango_attr_language_new(lang)); 8 | // lang *cannot* be freed 9 | break; 10 | -------------------------------------------------------------------------------- /_wip/examples_drawtext_CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # 3 june 2016 2 | 3 | _add_example(drawtext 4 | drawtext/attributes.c 5 | drawtext/basic.c 6 | drawtext/emptystr_hittest.c 7 | drawtext/hittest.c 8 | drawtext/main.c 9 | ${_EXAMPLE_RESOURCES_RC} 10 | ) 11 | target_include_directories(drawtext 12 | PRIVATE drawtext) 13 | 14 | _add_example(opentype 15 | opentype/main.c 16 | ${_EXAMPLE_RESOURCES_RC} 17 | ) 18 | target_include_directories(opentype 19 | PRIVATE opentype) 20 | -------------------------------------------------------------------------------- /_future/verticaltext/attrstr_windows.cpp: -------------------------------------------------------------------------------- 1 | uint32_t vertval; 2 | 3 | case uiAttributeVerticalForms: 4 | // LONGTERM 8 and/or 8.1 add other methods for vertical text 5 | op.p = p; 6 | op.start = start; 7 | op.end = end; 8 | vertval = 0; 9 | if (spec->Value != 0) 10 | vertval = 1; 11 | doOpenType("vert", vertval, &op); 12 | doOpenType("vrt2", vertval, &op); 13 | doOpenType("vkrn", vertval, &op); 14 | doOpenType("vrtr", vertval, &op); 15 | break; 16 | -------------------------------------------------------------------------------- /azure-pipelines/darwin-install-ninja.yml: -------------------------------------------------------------------------------- 1 | # 5 april 2019 2 | # because brew install is also slow (it runs an update task first) 3 | 4 | steps: 5 | - script: | 6 | sudo mkdir -p /opt/ninja 7 | pushd /opt/ninja 8 | sudo wget https://github.com/ninja-build/ninja/releases/download/v1.9.0/ninja-mac.zip 9 | sudo unzip ninja-mac.zip 10 | sudo chmod a+rx ninja 11 | popd 12 | echo '##vso[task.prependpath]/opt/ninja' 13 | displayName: 'Install Ninja' 14 | -------------------------------------------------------------------------------- /test/resources.rc: -------------------------------------------------------------------------------- 1 | // 30 may 2015 2 | 3 | // this is a UTF-8 file 4 | #pragma code_page(65001) 5 | 6 | // this is the Common Controls 6 manifest 7 | // TODO set up the string values here 8 | // 1 is the value of CREATEPROCESS_MANIFEST_RESOURCE_ID and 24 is the value of RT_MANIFEST; we use it directly to avoid needing to share winapi.h with the tests and examples 9 | #ifndef _UI_STATIC 10 | 1 24 "test.manifest" 11 | #else 12 | 1 24 "test.static.manifest" 13 | #endif 14 | -------------------------------------------------------------------------------- /unix/control.c: -------------------------------------------------------------------------------- 1 | // 16 august 2015 2 | #include "uipriv_unix.h" 3 | 4 | void uiUnixControlSetContainer(uiUnixControl *c, GtkContainer *container, gboolean remove) 5 | { 6 | (*(c->SetContainer))(c, container, remove); 7 | } 8 | 9 | #define uiUnixControlSignature 0x556E6978 10 | 11 | uiUnixControl *uiUnixAllocControl(size_t n, uint32_t typesig, const char *typenamestr) 12 | { 13 | return uiUnixControl(uiAllocControl(n, uiUnixControlSignature, typesig, typenamestr)); 14 | } 15 | -------------------------------------------------------------------------------- /examples/resources.rc: -------------------------------------------------------------------------------- 1 | // 30 may 2015 2 | 3 | // this is a UTF-8 file 4 | #pragma code_page(65001) 5 | 6 | // this is the Common Controls 6 manifest 7 | // TODO set up the string values here 8 | // 1 is the value of CREATEPROCESS_MANIFEST_RESOURCE_ID and 24 is the value of RT_MANIFEST; we use it directly to avoid needing to share winapi.h with the tests and examples 9 | #ifndef _UI_STATIC 10 | 1 24 "example.manifest" 11 | #else 12 | 1 24 "example.static.manifest" 13 | #endif 14 | -------------------------------------------------------------------------------- /darwin/text.m: -------------------------------------------------------------------------------- 1 | // 10 april 2015 2 | #import "uipriv_darwin.h" 3 | 4 | char *uiDarwinNSStringToText(NSString *s) 5 | { 6 | char *out; 7 | 8 | out = strdup([s UTF8String]); 9 | if (out == NULL) { 10 | fprintf(stderr, "memory exhausted in uiDarwinNSStringToText()\n"); 11 | abort(); 12 | } 13 | return out; 14 | } 15 | 16 | void uiFreeText(char *s) 17 | { 18 | free(s); 19 | } 20 | 21 | int uiprivStricmp(const char *a, const char *b) 22 | { 23 | return strcasecmp(a, b); 24 | } 25 | -------------------------------------------------------------------------------- /_future/textlanguageattr/attrstr_windows.cpp: -------------------------------------------------------------------------------- 1 | WCHAR *localeName; 2 | 3 | // locale names are specified as BCP 47: https://msdn.microsoft.com/en-us/library/windows/desktop/dd373814(v=vs.85).aspx https://www.ietf.org/rfc/rfc4646.txt 4 | case uiAttributeLanguage: 5 | localeName = toUTF16((char *) (spec->Value)); 6 | hr = p->layout->SetLocaleName(localeName, range); 7 | if (hr != S_OK) 8 | logHRESULT(L"error applying locale name attribute", hr); 9 | uiFree(localeName); 10 | break; -------------------------------------------------------------------------------- /windows/resources.rc: -------------------------------------------------------------------------------- 1 | // 30 may 2015 2 | #include "winapi.hpp" 3 | #include "resources.hpp" 4 | 5 | // this is a UTF-8 file 6 | #pragma code_page(65001) 7 | 8 | // this is the Common Controls 6 manifest 9 | // we only define it in a shared build; static builds have to include the appropriate parts of the manifest in the output executable 10 | // LONGTERM set up the string values here 11 | #ifndef _UI_STATIC 12 | ISOLATIONAWARE_MANIFEST_RESOURCE_ID RT_MANIFEST "libui.manifest" 13 | #endif 14 | -------------------------------------------------------------------------------- /common/shouldquit.c: -------------------------------------------------------------------------------- 1 | // 9 may 2015 2 | #include "../ui.h" 3 | #include "uipriv.h" 4 | 5 | static int defaultOnShouldQuit(void *data) 6 | { 7 | return 0; 8 | } 9 | 10 | static int (*onShouldQuit)(void *) = defaultOnShouldQuit; 11 | static void *onShouldQuitData = NULL; 12 | 13 | void uiOnShouldQuit(int (*f)(void *), void *data) 14 | { 15 | onShouldQuit = f; 16 | onShouldQuitData = data; 17 | } 18 | 19 | int uiprivShouldQuit(void) 20 | { 21 | return (*onShouldQuit)(onShouldQuitData); 22 | } 23 | -------------------------------------------------------------------------------- /common/OLD_table.c: -------------------------------------------------------------------------------- 1 | // 21 june 2016 2 | #include "../ui.h" 3 | #include "uipriv.h" 4 | 5 | void *uiTableModelGiveInt(int i) 6 | { 7 | return (void *) ((intptr_t) i); 8 | } 9 | 10 | int uiTableModelTakeInt(void *v) 11 | { 12 | return (int) ((intptr_t) v); 13 | } 14 | 15 | uiTableColumn *uiTableAppendTextColumn(uiTable *t, const char *name, int modelColumn) 16 | { 17 | uiTableColumn *tc; 18 | 19 | tc = uiTableAppendColumn(t, name); 20 | uiTableColumnAppendTextPart(tc, modelColumn, 1); 21 | return tc; 22 | } 23 | -------------------------------------------------------------------------------- /windows/_uipriv_migrate.hpp: -------------------------------------------------------------------------------- 1 | 2 | // menu.c 3 | extern HMENU makeMenubar(void); 4 | extern const uiMenuItem *menuIDToItem(UINT_PTR); 5 | extern void runMenuEvent(WORD, uiWindow *); 6 | extern void freeMenubar(HMENU); 7 | extern void uninitMenus(void); 8 | 9 | // draw.c 10 | extern HRESULT initDraw(void); 11 | extern void uninitDraw(void); 12 | extern ID2D1HwndRenderTarget *makeHWNDRenderTarget(HWND hwnd); 13 | extern uiDrawContext *newContext(ID2D1RenderTarget *); 14 | extern void freeContext(uiDrawContext *); 15 | -------------------------------------------------------------------------------- /_wip/attrstr_metrics/common_OLD_uipriv_attrstr.h: -------------------------------------------------------------------------------- 1 | 2 | 3 | // TODO split these into a separate header file? 4 | 5 | // drawtext.c 6 | struct caretDrawParams { 7 | double r; 8 | double g; 9 | double b; 10 | double a; 11 | double xoff; 12 | double width; 13 | }; 14 | extern void caretDrawParams(uiDrawContext *c, double height, struct caretDrawParams *p); 15 | extern void drawTextBackground(uiDrawContext *c, double x, double y, uiDrawTextLayout *layout, size_t start, size_t end, uiDrawBrush *brush, int isSelection); 16 | -------------------------------------------------------------------------------- /windows/_rc2bin/build.bat: -------------------------------------------------------------------------------- 1 | @rem 2 may 2018 2 | @echo off 3 | 4 | cl /nologo /TP /GR /EHsc /MDd /Ob0 /Od /RTC1 /W4 /wd4100 /bigobj /RTC1 /RTCs /RTCu /FS -c main.cpp 5 | if errorlevel 1 goto out 6 | rc -foresources.res resources.rc 7 | if errorlevel 1 goto out 8 | link /nologo main.obj resources.res /out:main.exe /LARGEADDRESSAWARE /NOLOGO /INCREMENTAL:NO /MANIFEST:NO /debug user32.lib kernel32.lib gdi32.lib comctl32.lib uxtheme.lib msimg32.lib comdlg32.lib d2d1.lib dwrite.lib ole32.lib oleaut32.lib oleacc.lib uuid.lib 9 | 10 | :out 11 | -------------------------------------------------------------------------------- /test/page7.c: -------------------------------------------------------------------------------- 1 | // 13 october 2015 2 | #include "test.h" 3 | 4 | uiBox *makePage7(void) 5 | { 6 | uiBox *page7; 7 | uiGroup *group; 8 | uiBox *box2; 9 | 10 | page7 = newHorizontalBox(); 11 | 12 | group = makePage7a(); 13 | uiBoxAppend(page7, uiControl(group), 1); 14 | 15 | box2 = newVerticalBox(); 16 | uiBoxAppend(page7, uiControl(box2), 1); 17 | 18 | group = makePage7b(); 19 | uiBoxAppend(box2, uiControl(group), 1); 20 | 21 | group = makePage7c(); 22 | uiBoxAppend(box2, uiControl(group), 1); 23 | 24 | return page7; 25 | } 26 | -------------------------------------------------------------------------------- /windows/draw.hpp: -------------------------------------------------------------------------------- 1 | // 5 may 2016 2 | 3 | // TODO resolve overlap between this and the other hpp files (some functions leaked into uipriv_windows.hpp) 4 | 5 | // draw.cpp 6 | extern ID2D1Factory *d2dfactory; 7 | struct uiDrawContext { 8 | ID2D1RenderTarget *rt; 9 | // TODO find out how this works 10 | std::vector *states; 11 | ID2D1PathGeometry *currentClip; 12 | }; 13 | 14 | // drawpath.cpp 15 | extern ID2D1PathGeometry *pathGeometry(uiDrawPath *p); 16 | 17 | // drawmatrix.cpp 18 | extern void m2d(uiDrawMatrix *m, D2D1_MATRIX_3X2_F *d); 19 | -------------------------------------------------------------------------------- /_doc/export/writewidths.processed: -------------------------------------------------------------------------------- 1 | -0.1 0xbfb9999999999998 unregistered OS2 4 2 | -0.2 0xbfc999999999999a unregistered OS2 3 3 | -0.3 0xbfd3333333333333 unregistered OS2 2 4 | -0.4 0xbfd999999999999a unregistered OS2 1 5 | -0.5 0xbfe0000000000000 unregistered OS2 0 6 | 0 0x0000000000000000 unregistered OS2 5 7 | 0.1 0x3fb9999999999998 unregistered OS2 6 8 | 0.2 0x3fc9999999999998 unregistered OS2 7 9 | 0.3 0x3fd3333333333334 unregistered OS2 8 10 | 0.4 0x3fd999999999999a unregistered OS2 9 11 | 0.5 0x3fe0000000000000 unregistered OS2 10 12 | -------------------------------------------------------------------------------- /_doc/drawtext: -------------------------------------------------------------------------------- 1 | on some unix systems, alpha blending fonts may not be available; this depends on your installed version of pango and is determined at runtime by libui 2 | 3 | uiDrawTextLayoutExtents: document that the extent width can be greater than the requested width if the requested width is small enough that only one character can fit 4 | 5 | 6 | font matching is closest match but the search method is OS defined 7 | 8 | 9 | weight names in libui do not necessarily line up with their OS names 10 | 11 | 12 | uiDrawFontHandle() may not return a unique handle per instance 13 | 14 | -------------------------------------------------------------------------------- /_notes/windowsPrinting: -------------------------------------------------------------------------------- 1 | https://msdn.microsoft.com/en-us/library/windows/desktop/ff686805(v=vs.85).aspx 2 | https://msdn.microsoft.com/en-us/library/windows/desktop/dn495653(v=vs.85).aspx 3 | https://msdn.microsoft.com/en-us/library/windows/desktop/hh448422(v=vs.85).aspx 4 | https://msdn.microsoft.com/en-us/library/windows/desktop/dd316975(v=vs.85).aspx 5 | https://msdn.microsoft.com/en-us/library/windows/desktop/dd372919(v=vs.85).aspx 6 | https://msdn.microsoft.com/en-us/library/windows/desktop/ee264335(v=vs.85).aspx 7 | https://msdn.microsoft.com/en-us/library/windows/desktop/dd145198(v=vs.85).aspx 8 | -------------------------------------------------------------------------------- /azure-pipelines/windows-install-ninja.yml: -------------------------------------------------------------------------------- 1 | # 4 april 2019 2 | # why this? because choco isn't available on the VS2015 image and is extremely slow on the VS2017 one (it should not take 2.5 minutes to install just ninja!) 3 | 4 | steps: 5 | - script: | 6 | powershell -Command "Invoke-WebRequest https://github.com/ninja-build/ninja/releases/download/v1.9.0/ninja-win.zip -OutFile C:\ninja-win.zip" 7 | mkdir C:\ninja 8 | powershell -Command "Expand-Archive -LiteralPath C:\ninja-win.zip -DestinationPath C:\ninja" 9 | @echo ##vso[task.prependpath]C:\ninja 10 | displayName: 'Install Ninja' 11 | -------------------------------------------------------------------------------- /_notes/tableNotes: -------------------------------------------------------------------------------- 1 | https://developer.apple.com/library/mac/documentation/Cocoa/Reference/ApplicationKit/Protocols/NSOutlineViewDataSource_Protocol/index.html#//apple_ref/occ/intfm/NSOutlineViewDataSource/outlineView:child:ofItem: 2 | https://developer.apple.com/library/mac/documentation/Cocoa/Reference/NSOutlineViewDelegate_Protocol/index.html#//apple_ref/occ/intfm/NSOutlineViewDelegate/outlineView:didAddRowView:forRow: 3 | https://developer.apple.com/documentation/appkit/nsoutlineviewdelegate/1528320-outlineview?language=objc 4 | https://github.com/mity/mctrl/blob/master/mctrl/treelist.c around treelist_set_subitem() 5 | -------------------------------------------------------------------------------- /common/debug.c: -------------------------------------------------------------------------------- 1 | // 13 may 2016 2 | #include "../ui.h" 3 | #include "uipriv.h" 4 | 5 | void uiprivDoImplBug(const char *file, const char *line, const char *func, const char *format, ...) 6 | { 7 | va_list ap; 8 | 9 | va_start(ap, format); 10 | uiprivRealBug(file, line, func, "POSSIBLE IMPLEMENTATION BUG; CONTACT ANDLABS:\n", format, ap); 11 | va_end(ap); 12 | } 13 | 14 | void uiprivDoUserBug(const char *file, const char *line, const char *func, const char *format, ...) 15 | { 16 | va_list ap; 17 | 18 | va_start(ap, format); 19 | uiprivRealBug(file, line, func, "You have a bug: ", format, ap); 20 | va_end(ap); 21 | } 22 | -------------------------------------------------------------------------------- /_notes/winflags: -------------------------------------------------------------------------------- 1 | # TODO is there a -Wno-switch equivalent? 2 | # TODO /sdl turns C4996 into an ERROR 3 | # don't use /analyze; that requires us to write annotations everywhere 4 | # TODO undecided flags from qo? 5 | # the RTC flags are only supplied in debug builds because they are only supposed to be used by debug builds (see "This is because run-time error checks are not valid in a release (optimized) build." in https://docs.microsoft.com/cpp/build/reference/rtc-run-time-error-checks) 6 | # /RTCc is not supplied because it's discouraged as of VS2015; see https://www.reddit.com/r/cpp/comments/46mhne/rtcc_rejects_conformant_code_with_visual_c_2015/d06auq5 7 | -------------------------------------------------------------------------------- /_doc/export/writewidths.out: -------------------------------------------------------------------------------- 1 | unregistered OS2 0: float64as(-0.5, 0xbfe0000000000000) 2 | unregistered OS2 1: float64as(-0.4, 0xbfd999999999999a) 3 | unregistered OS2 2: float64as(-0.3, 0xbfd3333333333333) 4 | unregistered OS2 3: float64as(-0.2, 0xbfc999999999999a) 5 | unregistered OS2 4: float64as(-0.1, 0xbfb9999999999998) 6 | unregistered OS2 5: float64as(0, 0x0000000000000000) 7 | unregistered OS2 6: float64as(0.1, 0x3fb9999999999998) 8 | unregistered OS2 7: float64as(0.2, 0x3fc9999999999998) 9 | unregistered OS2 8: float64as(0.3, 0x3fd3333333333334) 10 | unregistered OS2 9: float64as(0.4, 0x3fd999999999999a) 11 | unregistered OS2 10: float64as(0.5, 0x3fe0000000000000) 12 | -------------------------------------------------------------------------------- /azure-pipelines/vs2015-install-python3.yml: -------------------------------------------------------------------------------- 1 | # 4 april 2019 2 | # see https://github.com/Microsoft/azure-pipelines-image-generation/issues/374 for context and source 3 | 4 | steps: 5 | - script: | 6 | powershell -Command "Invoke-WebRequest https://www.python.org/ftp/python/3.7.1/python-3.7.1-amd64-webinstall.exe -OutFile C:\py3-setup.exe" 7 | C:\py3-setup.exe /quiet PrependPath=0 InstallAllUsers=0 Include_launcher=0 InstallLauncherAllUsers=0 Include_test=0 Include_doc=0 Include_dev=0 Include_debug=0 Include_tcltk=0 TargetDir=C:\Python37 8 | @echo ##vso[task.prependpath]C:\Python37 9 | @echo ##vso[task.prependpath]C:\Python37\Scripts 10 | displayName: 'Install Python 3' 11 | -------------------------------------------------------------------------------- /darwin/debug.m: -------------------------------------------------------------------------------- 1 | // 13 may 2016 2 | #import "uipriv_darwin.h" 3 | 4 | // LONGTERM don't halt on release builds 5 | 6 | void uiprivRealBug(const char *file, const char *line, const char *func, const char *prefix, const char *format, va_list ap) 7 | { 8 | NSMutableString *str; 9 | NSString *formatted; 10 | 11 | str = [NSMutableString new]; 12 | [str appendString:[NSString stringWithFormat:@"[libui] %s:%s:%s() %s", file, line, func, prefix]]; 13 | formatted = [[NSString alloc] initWithFormat:[NSString stringWithUTF8String:format] arguments:ap]; 14 | [str appendString:formatted]; 15 | [formatted release]; 16 | NSLog(@"%@", str); 17 | [str release]; 18 | __builtin_trap(); 19 | } 20 | -------------------------------------------------------------------------------- /darwin/table.h: -------------------------------------------------------------------------------- 1 | // 3 june 2018 2 | #import "../common/table.h" 3 | 4 | // table.m 5 | // TODO get rid of forward declaration 6 | @class uiprivTableModel; 7 | struct uiTableModel { 8 | uiTableModelHandler *mh; 9 | uiprivTableModel *m; 10 | NSMutableArray *tables; 11 | }; 12 | struct uiTable { 13 | uiDarwinControl c; 14 | NSScrollView *sv; 15 | NSTableView *tv; 16 | uiprivScrollViewData *d; 17 | int backgroundColumn; 18 | uiTableModel *m; 19 | }; 20 | 21 | // tablecolumn.m 22 | @interface uiprivTableCellView : NSTableCellView 23 | - (void)uiprivUpdate:(NSInteger)row; 24 | @end 25 | @interface uiprivTableColumn : NSTableColumn 26 | - (uiprivTableCellView *)uiprivMakeCellView; 27 | @end 28 | -------------------------------------------------------------------------------- /darwin/util.m: -------------------------------------------------------------------------------- 1 | // 7 april 2015 2 | #import "uipriv_darwin.h" 3 | 4 | // LONGTERM do we really want to do this? make it an option? 5 | // TODO figure out why we removed this from window.m 6 | void uiprivDisableAutocorrect(NSTextView *tv) 7 | { 8 | [tv setEnabledTextCheckingTypes:0]; 9 | [tv setAutomaticDashSubstitutionEnabled:NO]; 10 | // don't worry about automatic data detection; it won't change stringValue (thanks pretty_function in irc.freenode.net/#macdev) 11 | [tv setAutomaticSpellingCorrectionEnabled:NO]; 12 | [tv setAutomaticTextReplacementEnabled:NO]; 13 | [tv setAutomaticQuoteSubstitutionEnabled:NO]; 14 | [tv setAutomaticLinkDetectionEnabled:NO]; 15 | [tv setSmartInsertDeleteEnabled:NO]; 16 | } 17 | -------------------------------------------------------------------------------- /_wip/examples_drawtext/drawtext.h: -------------------------------------------------------------------------------- 1 | // 20 january 2017 2 | #include 3 | #include 4 | #include 5 | #include "../../ui.h" 6 | 7 | struct example { 8 | const char *name; 9 | uiControl *panel; 10 | void (*draw)(uiAreaDrawParams *p); 11 | void (*mouse)(uiAreaMouseEvent *e); 12 | int (*key)(uiAreaKeyEvent *e); 13 | // TODO key? 14 | }; 15 | 16 | // main.c 17 | extern void redraw(void); 18 | 19 | // basic.c 20 | extern struct example *mkBasicExample(void); 21 | 22 | // hittest.c 23 | extern struct example *mkHitTestExample(void); 24 | 25 | // attributes.c 26 | extern struct example *mkAttributesExample(void); 27 | 28 | // emptystr_hittest.c 29 | extern struct example *mkEmptyStringExample(void); 30 | -------------------------------------------------------------------------------- /_notes/darwinNSAlertIcons: -------------------------------------------------------------------------------- 1 | https://www.google.com/search?q=nsalert+error+icon&client=firefox-b&tbm=isch&source=iu&ictx=1&fir=2iRctS5fJByN0M%253A%252Cw324MTzjHa1bAM%252C_&usg=__x3wpwdNN1L8VI2kHtkKAXFMtpj4%3D&sa=X&ved=0ahUKEwjJzpjN2qDZAhVjw1kKHfOHDoQQ9QEIMTAB#imgrc=2iRctS5fJByN0M: 2 | http://0xced.blogspot.com/2009/11/clalert-nsalert-done-right.html 3 | https://gist.github.com/0xced/228140 4 | http://editra.org/uploads/code/artmac.html 5 | http://mirror.informatimago.com/next/developer.apple.com/documentation/Carbon/Reference/IconServices/index.html 6 | http://www.cocoabuilder.com/archive/cocoa/15427-iconref-to-nsimage.html 7 | https://github.com/lukakerr/Swift-NSUserNotificationPrivate 8 | https://stackoverflow.com/questions/32943220/the-sidebar-icon-image-name-in-osx 9 | -------------------------------------------------------------------------------- /unix/label.c: -------------------------------------------------------------------------------- 1 | // 11 june 2015 2 | #include "uipriv_unix.h" 3 | 4 | struct uiLabel { 5 | uiUnixControl c; 6 | GtkWidget *widget; 7 | GtkMisc *misc; 8 | GtkLabel *label; 9 | }; 10 | 11 | uiUnixControlAllDefaults(uiLabel) 12 | 13 | char *uiLabelText(uiLabel *l) 14 | { 15 | return uiUnixStrdupText(gtk_label_get_text(l->label)); 16 | } 17 | 18 | void uiLabelSetText(uiLabel *l, const char *text) 19 | { 20 | gtk_label_set_text(l->label, text); 21 | } 22 | 23 | uiLabel *uiNewLabel(const char *text) 24 | { 25 | uiLabel *l; 26 | 27 | uiUnixNewControl(uiLabel, l); 28 | 29 | l->widget = gtk_label_new(text); 30 | l->misc = GTK_MISC(l->widget); 31 | l->label = GTK_LABEL(l->widget); 32 | 33 | gtk_misc_set_alignment(l->misc, 0, 0); 34 | 35 | return l; 36 | } 37 | -------------------------------------------------------------------------------- /unix/separator.c: -------------------------------------------------------------------------------- 1 | // 11 june 2015 2 | #include "uipriv_unix.h" 3 | 4 | struct uiSeparator { 5 | uiUnixControl c; 6 | GtkWidget *widget; 7 | GtkSeparator *separator; 8 | }; 9 | 10 | uiUnixControlAllDefaults(uiSeparator) 11 | 12 | uiSeparator *uiNewHorizontalSeparator(void) 13 | { 14 | uiSeparator *s; 15 | 16 | uiUnixNewControl(uiSeparator, s); 17 | 18 | s->widget = gtk_separator_new(GTK_ORIENTATION_HORIZONTAL); 19 | s->separator = GTK_SEPARATOR(s->widget); 20 | 21 | return s; 22 | } 23 | 24 | uiSeparator *uiNewVerticalSeparator(void) 25 | { 26 | uiSeparator *s; 27 | 28 | uiUnixNewControl(uiSeparator, s); 29 | 30 | s->widget = gtk_separator_new(GTK_ORIENTATION_VERTICAL); 31 | s->separator = GTK_SEPARATOR(s->widget); 32 | 33 | return s; 34 | } 35 | -------------------------------------------------------------------------------- /_notes/rebarstuff: -------------------------------------------------------------------------------- 1 | https://docs.microsoft.com/en-us/windows/desktop/uxguide/cmd-toolbars 2 | https://docs.microsoft.com/en-us/windows/desktop/controls/cc-faq-iemenubar 3 | https://docs.microsoft.com/en-us/windows/desktop/controls/cc-faq-ietoolbar 4 | https://docs.microsoft.com/en-us/windows/desktop/controls/create-rebar-controls 5 | https://docs.microsoft.com/en-us/windows/desktop/controls/create-toolbars 6 | https://docs.microsoft.com/en-us/windows/desktop/controls/handle-drop-down-buttons 7 | https://docs.microsoft.com/en-us/windows/desktop/controls/tb-buttonstructsize 8 | https://www.google.com/search?q=winapi+toolbar+dropdown+position&ie=utf-8&oe=utf-8&client=firefox-b-1 9 | https://www.google.com/search?q=winapi+toolbar+dropdown+arrow+position&ie=utf-8&oe=utf-8&client=firefox-b-1 10 | -------------------------------------------------------------------------------- /_future/textlanguageattr/attrstr_darwin.m: -------------------------------------------------------------------------------- 1 | struct fontParams { 2 | uiDrawFontDescriptor desc; 3 | uint16_t featureTypes[maxFeatures]; 4 | uint16_t featureSelectors[maxFeatures]; 5 | size_t nFeatures; 6 | const char *language; 7 | }; 8 | 9 | 10 | // locale identifiers are specified as BCP 47: https://developer.apple.com/reference/corefoundation/cflocale?language=objc 11 | case uiAttributeLanguage: 12 | // LONGTERM FUTURE when we move to 10.9, switch to using kCTLanguageAttributeName 13 | ensureFontInRange(p, start, end); 14 | adjustFontInRange(p, start, end, ^(struct fontParams *fp) { 15 | fp->language = (const char *) (spec->Value); 16 | }); 17 | break; 18 | 19 | desc = fontdescAppendFeatures(desc, fp->featureTypes, fp->featureSelectors, fp->nFeatures, fp->language); 20 | -------------------------------------------------------------------------------- /unix/opentype.c: -------------------------------------------------------------------------------- 1 | // 11 may 2017 2 | #include "uipriv_unix.h" 3 | #include "attrstr.h" 4 | 5 | // see https://developer.mozilla.org/en/docs/Web/CSS/font-feature-settings 6 | static uiForEach toCSS(const uiOpenTypeFeatures *otf, char a, char b, char c, char d, uint32_t value, void *data) 7 | { 8 | GString *s = (GString *) data; 9 | 10 | // the last trailing comma is removed after foreach is done 11 | g_string_append_printf(s, "\"%c%c%c%c\" %" PRIu32 ", ", 12 | a, b, c, d, value); 13 | return uiForEachContinue; 14 | } 15 | 16 | GString *uiprivOpenTypeFeaturesToPangoCSSFeaturesString(const uiOpenTypeFeatures *otf) 17 | { 18 | GString *s; 19 | 20 | s = g_string_new(""); 21 | uiOpenTypeFeaturesForEach(otf, toCSS, s); 22 | if (s->len != 0) 23 | // and remove the last comma 24 | g_string_truncate(s, s->len - 2); 25 | return s; 26 | } 27 | -------------------------------------------------------------------------------- /azure-pipelines/collapse.awk: -------------------------------------------------------------------------------- 1 | # 7 april 2019 2 | 3 | BEGIN { 4 | RS = "" 5 | FS = "\n +- " 6 | } 7 | 8 | /^- job:/ { 9 | for (i = 1; i <= NF; i++) { 10 | if (!(i in nextindex)) { 11 | # fast path for first occurrence 12 | lines[i, 0] = $i 13 | nextindex[i] = 1 14 | if (maxIndex < i) 15 | maxIndex = i 16 | continue 17 | } 18 | found = 0 19 | for (j = 0; j < nextindex[i]; j++) 20 | if (lines[i, j] == $i) { 21 | found = 1 22 | break 23 | } 24 | if (!found) { 25 | lines[i, nextindex[i]] = $i 26 | nextindex[i]++ 27 | } 28 | } 29 | } 30 | 31 | END { 32 | for (i = 1; i <= maxIndex; i++) { 33 | if (nextindex[i] == 1) { 34 | # only one entry here, just print it 35 | print "- " lines[i, 0] 36 | continue 37 | } 38 | print "{" 39 | for (j = 0; j < nextindex[i]; j++) 40 | print "- " lines[i, j] 41 | print "}" 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /unix/table.h: -------------------------------------------------------------------------------- 1 | // 4 june 2018 2 | #include "../common/table.h" 3 | 4 | // tablemodel.c 5 | #define uiTableModelType (uiTableModel_get_type()) 6 | #define uiTableModel(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), uiTableModelType, uiTableModel)) 7 | #define isuiTableModel(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), uiTableModelType)) 8 | #define uiTableModelClass(class) (G_TYPE_CHECK_CLASS_CAST((class), uiTableModelType, uiTableModelClass)) 9 | #define isuiTableModelClass(class) (G_TYPE_CHECK_CLASS_TYPE((class), uiTableModel)) 10 | #define getuiTableModelClass(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), uiTableModelType, uiTableModelClass)) 11 | typedef struct uiTableModelClass uiTableModelClass; 12 | struct uiTableModel { 13 | GObject parent_instance; 14 | uiTableModelHandler *mh; 15 | }; 16 | struct uiTableModelClass { 17 | GObjectClass parent_class; 18 | }; 19 | extern GType uiTableModel_get_type(void); 20 | -------------------------------------------------------------------------------- /_future/verticaltext/drawtext_example.c: -------------------------------------------------------------------------------- 1 | next = "vertical glyph forms"; 2 | start = uiAttributedStringLen(attrstr); 3 | end = start + strlen(next); 4 | uiAttributedStringAppendUnattributed(attrstr, next); 5 | spec.Type = uiAttributeVerticalForms; 6 | spec.Value = 1; 7 | uiAttributedStringSetAttribute(attrstr, &spec, start, end); 8 | uiAttributedStringAppendUnattributed(attrstr, " (which you can draw rotated for proper vertical text; for instance, "); 9 | next = "\xE3\x81\x82\xE3\x81\x84\xE3\x81\x86\xE3\x81\x88\xE3\x81\x8A"; 10 | start = uiAttributedStringLen(attrstr); 11 | end = start + strlen(next); 12 | uiAttributedStringAppendUnattributed(attrstr, next); 13 | spec.Type = uiAttributeVerticalForms; 14 | spec.Value = 1; 15 | uiAttributedStringSetAttribute(attrstr, &spec, start, end); 16 | uiAttributedStringAppendUnattributed(attrstr, ")"); 17 | 18 | uiAttributedStringAppendUnattributed(attrstr, ", "); 19 | -------------------------------------------------------------------------------- /common/table.h: -------------------------------------------------------------------------------- 1 | // 23 june 2018 2 | 3 | #ifdef __cplusplus 4 | extern "C" { 5 | #endif 6 | 7 | // tablemodel.c 8 | extern uiTableModelHandler *uiprivTableModelHandler(uiTableModel *m); 9 | extern int uiprivTableModelNumColumns(uiTableModel *m); 10 | extern uiTableValueType uiprivTableModelColumnType(uiTableModel *m, int column); 11 | extern int uiprivTableModelNumRows(uiTableModel *m); 12 | extern uiTableValue *uiprivTableModelCellValue(uiTableModel *m, int row, int column); 13 | extern void uiprivTableModelSetCellValue(uiTableModel *m, int row, int column, const uiTableValue *value); 14 | extern const uiTableTextColumnOptionalParams uiprivDefaultTextColumnOptionalParams; 15 | extern int uiprivTableModelCellEditable(uiTableModel *m, int row, int column); 16 | extern int uiprivTableModelColorIfProvided(uiTableModel *m, int row, int column, double *r, double *g, double *b, double *a); 17 | 18 | #ifdef __cplusplus 19 | } 20 | #endif 21 | -------------------------------------------------------------------------------- /test/test.manifest: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | Your application description here. 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /examples/example.manifest: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | Your application description here. 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /_notes/darwinAutoLayout: -------------------------------------------------------------------------------- 1 | https://developer.apple.com/library/mac/documentation/AppKit/Reference/NSLayoutConstraint_Class/ 2 | https://developer.apple.com/documentation/uikit/nslayoutconstraint?language=objc 3 | https://developer.apple.com/library/mac/documentation/UserExperience/Conceptual/AutolayoutPG/ProgrammaticallyCreatingConstraints.html#//apple_ref/doc/uid/TP40010853-CH16-SW1 4 | https://developer.apple.com/library/content/documentation/UserExperience/Conceptual/AutolayoutPG/ProgrammaticallyCreatingConstraints.html#//apple_ref/doc/uid/TP40010853-CH16-SW1 (Listing 13-3) 5 | https://developer.apple.com/library/mac/documentation/UserExperience/Conceptual/AutolayoutPG/WorkingwithScrollViews.html#//apple_ref/doc/uid/TP40010853-CH24-SW1 6 | https://developer.apple.com/library/content/documentation/UserExperience/Conceptual/AutolayoutPG/WorkingwithScrollViews.html#//apple_ref/doc/uid/TP40010853-CH24-SW1 ("IMPORTANT Your layout must fully define..." large box) 7 | -------------------------------------------------------------------------------- /windows/areautil.cpp: -------------------------------------------------------------------------------- 1 | // 18 december 2015 2 | #include "uipriv_windows.hpp" 3 | #include "area.hpp" 4 | 5 | void loadAreaSize(uiArea *a, ID2D1RenderTarget *rt, double *width, double *height) 6 | { 7 | D2D1_SIZE_F size; 8 | 9 | *width = 0; 10 | *height = 0; 11 | if (!a->scrolling) { 12 | if (rt == NULL) 13 | rt = a->rt; 14 | size = realGetSize(rt); 15 | *width = size.width; 16 | *height = size.height; 17 | } 18 | } 19 | 20 | void pixelsToDIP(uiArea *a, double *x, double *y) 21 | { 22 | FLOAT dpix, dpiy; 23 | 24 | a->rt->GetDpi(&dpix, &dpiy); 25 | // see https://msdn.microsoft.com/en-us/library/windows/desktop/dd756649%28v=vs.85%29.aspx (and others; search "direct2d mouse") 26 | *x = (*x * 96) / dpix; 27 | *y = (*y * 96) / dpiy; 28 | } 29 | 30 | void dipToPixels(uiArea *a, double *x, double *y) 31 | { 32 | FLOAT dpix, dpiy; 33 | 34 | a->rt->GetDpi(&dpix, &dpiy); 35 | *x = (*x * dpix) / 96; 36 | *y = (*y * dpiy) / 96; 37 | } 38 | -------------------------------------------------------------------------------- /_wip/sv/sourcelist.nots: -------------------------------------------------------------------------------- 1 | backgroundColor (null) 2 | drawsBackground 0 3 | borderType 2 4 | documentCursor (null) 5 | hasHorizontalScroller 1 6 | hasVerticalScroller 1 7 | autohidesScrollers 1 8 | hasHorizontalRuler 0 9 | hasVerticalRuler 0 10 | rulersVisible 0 11 | 10.10 autoAdjContentInsets 1 12 | scrollerKnobStyle 0 13 | scrollerStyle 1 14 | horizontalLineScroll 19 15 | verticalLineScroll 19 16 | horizontalPageScroll 10 17 | verticalPageScroll 10 18 | scrollsDynamically 1 19 | findBarPosition 1 20 | usesPredomAxisScroll 0 21 | horizontalElasticity 0 22 | verticalElasticity 0 23 | 10.8 allowsMagnification 0 24 | 10.8 maxMagnification 4 25 | 10.8 minMagnification 0.25 26 | -------------------------------------------------------------------------------- /windows/resources.hpp: -------------------------------------------------------------------------------- 1 | // 30 may 2015 2 | 3 | #define rcTabPageDialog 29000 4 | #define rcFontDialog 29001 5 | #define rcColorDialog 29002 6 | 7 | // TODO normalize these 8 | 9 | #define rcFontFamilyCombobox 1000 10 | #define rcFontStyleCombobox 1001 11 | #define rcFontSizeCombobox 1002 12 | #define rcFontSamplePlacement 1003 13 | 14 | #define rcColorSVChooser 1100 15 | #define rcColorHSlider 1101 16 | #define rcPreview 1102 17 | #define rcOpacitySlider 1103 18 | #define rcH 1104 19 | #define rcS 1105 20 | #define rcV 1106 21 | #define rcRDouble 1107 22 | #define rcRInt 1108 23 | #define rcGDouble 1109 24 | #define rcGInt 1110 25 | #define rcBDouble 1111 26 | #define rcBInt 1112 27 | #define rcADouble 1113 28 | #define rcAInt 1114 29 | #define rcHex 1115 30 | #define rcHLabel 1116 31 | #define rcSLabel 1117 32 | #define rcVLabel 1118 33 | #define rcRLabel 1119 34 | #define rcGLabel 1120 35 | #define rcBLabel 1121 36 | #define rcALabel 1122 37 | #define rcHexLabel 1123 38 | -------------------------------------------------------------------------------- /windows/_rc2bin/resources.hpp: -------------------------------------------------------------------------------- 1 | // 30 may 2015 2 | 3 | #define rcTabPageDialog 29000 4 | #define rcFontDialog 29001 5 | #define rcColorDialog 29002 6 | 7 | // TODO normalize these 8 | 9 | #define rcFontFamilyCombobox 1000 10 | #define rcFontStyleCombobox 1001 11 | #define rcFontSizeCombobox 1002 12 | #define rcFontSamplePlacement 1003 13 | 14 | #define rcColorSVChooser 1100 15 | #define rcColorHSlider 1101 16 | #define rcPreview 1102 17 | #define rcOpacitySlider 1103 18 | #define rcH 1104 19 | #define rcS 1105 20 | #define rcV 1106 21 | #define rcRDouble 1107 22 | #define rcRInt 1108 23 | #define rcGDouble 1109 24 | #define rcGInt 1110 25 | #define rcBDouble 1111 26 | #define rcBInt 1112 27 | #define rcADouble 1113 28 | #define rcAInt 1114 29 | #define rcHex 1115 30 | #define rcHLabel 1116 31 | #define rcSLabel 1117 32 | #define rcVLabel 1118 33 | #define rcRLabel 1119 34 | #define rcGLabel 1120 35 | #define rcBLabel 1121 36 | #define rcALabel 1122 37 | #define rcHexLabel 1123 38 | -------------------------------------------------------------------------------- /_wip/sv/normal.nots: -------------------------------------------------------------------------------- 1 | backgroundColor NSNamedColorSpace System controlColor 2 | drawsBackground 1 3 | borderType 2 4 | documentCursor (null) 5 | hasHorizontalScroller 1 6 | hasVerticalScroller 1 7 | autohidesScrollers 0 8 | hasHorizontalRuler 0 9 | hasVerticalRuler 0 10 | rulersVisible 0 11 | 10.10 autoAdjContentInsets 1 12 | scrollerKnobStyle 0 13 | scrollerStyle 1 14 | horizontalLineScroll 10 15 | verticalLineScroll 10 16 | horizontalPageScroll 10 17 | verticalPageScroll 10 18 | scrollsDynamically 1 19 | findBarPosition 1 20 | usesPredomAxisScroll 0 21 | horizontalElasticity 0 22 | verticalElasticity 0 23 | 10.8 allowsMagnification 0 24 | 10.8 maxMagnification 4 25 | 10.8 minMagnification 0.25 26 | -------------------------------------------------------------------------------- /azure-pipelines/linux-386-install-gtk-dev.yml: -------------------------------------------------------------------------------- 1 | # 7 april 2019 2 | 3 | # TODO figure out how to get meson to recognize the compiler is producing 32-bit output 4 | 5 | steps: 6 | - script: | 7 | # Azure Pipelines ships with a patched version of this and that patch is only available on 64-bit systems, so trying to install the 32-bit versions will remove the 64-bit versions outright 8 | # This is a dependency of Mesa, so we'll have to downgrade to the stock distro ones :/ 9 | llvmPackages= 10 | for i in libllvm6.0 clang-6.0 libclang-common-6.0-dev liblldb-6.0 liblldb-6.0-dev lld-6.0 lldb-6.0 llvm-6.0-dev python-lldb-6.0 libclang1-6.0 llvm-6.0 llvm-6.0-runtime; do llvmPackages="$llvmPackages $i=1:6.0-1ubuntu2~16.04.1"; done 11 | sudo dpkg --add-architecture i386 12 | sudo apt-get update 13 | sudo apt-get install --allow-downgrades \ 14 | gcc-multilib g++-multilib \ 15 | $llvmPackages \ 16 | libgtk-3-dev:i386 17 | displayName: 'Install GTK+ Dev Files' 18 | -------------------------------------------------------------------------------- /darwin/label.m: -------------------------------------------------------------------------------- 1 | // 14 august 2015 2 | #import "uipriv_darwin.h" 3 | 4 | struct uiLabel { 5 | uiDarwinControl c; 6 | NSTextField *textfield; 7 | }; 8 | 9 | uiDarwinControlAllDefaults(uiLabel, textfield) 10 | 11 | char *uiLabelText(uiLabel *l) 12 | { 13 | return uiDarwinNSStringToText([l->textfield stringValue]); 14 | } 15 | 16 | void uiLabelSetText(uiLabel *l, const char *text) 17 | { 18 | [l->textfield setStringValue:uiprivToNSString(text)]; 19 | } 20 | 21 | NSTextField *uiprivNewLabel(NSString *str) 22 | { 23 | NSTextField *tf; 24 | 25 | tf = [[NSTextField alloc] initWithFrame:NSZeroRect]; 26 | [tf setStringValue:str]; 27 | [tf setEditable:NO]; 28 | [tf setSelectable:NO]; 29 | [tf setDrawsBackground:NO]; 30 | uiprivFinishNewTextField(tf, NO); 31 | return tf; 32 | } 33 | 34 | uiLabel *uiNewLabel(const char *text) 35 | { 36 | uiLabel *l; 37 | 38 | uiDarwinNewControl(uiLabel, l); 39 | 40 | l->textfield = uiprivNewLabel(uiprivToNSString(text)); 41 | 42 | return l; 43 | } 44 | -------------------------------------------------------------------------------- /_wip/sv/outlineview.nots: -------------------------------------------------------------------------------- 1 | backgroundColor NSNamedColorSpace System controlBackgroundColor 2 | drawsBackground 1 3 | borderType 2 4 | documentCursor (null) 5 | hasHorizontalScroller 1 6 | hasVerticalScroller 1 7 | autohidesScrollers 1 8 | hasHorizontalRuler 0 9 | hasVerticalRuler 0 10 | rulersVisible 0 11 | 10.10 autoAdjContentInsets 1 12 | scrollerKnobStyle 0 13 | scrollerStyle 1 14 | horizontalLineScroll 19 15 | verticalLineScroll 19 16 | horizontalPageScroll 10 17 | verticalPageScroll 10 18 | scrollsDynamically 1 19 | findBarPosition 1 20 | usesPredomAxisScroll 0 21 | horizontalElasticity 0 22 | verticalElasticity 0 23 | 10.8 allowsMagnification 0 24 | 10.8 maxMagnification 4 25 | 10.8 minMagnification 0.25 26 | -------------------------------------------------------------------------------- /_wip/sv/tableview.nots: -------------------------------------------------------------------------------- 1 | backgroundColor NSNamedColorSpace System controlBackgroundColor 2 | drawsBackground 1 3 | borderType 2 4 | documentCursor (null) 5 | hasHorizontalScroller 1 6 | hasVerticalScroller 1 7 | autohidesScrollers 1 8 | hasHorizontalRuler 0 9 | hasVerticalRuler 0 10 | rulersVisible 0 11 | 10.10 autoAdjContentInsets 1 12 | scrollerKnobStyle 0 13 | scrollerStyle 1 14 | horizontalLineScroll 19 15 | verticalLineScroll 19 16 | horizontalPageScroll 10 17 | verticalPageScroll 10 18 | scrollsDynamically 1 19 | findBarPosition 1 20 | usesPredomAxisScroll 0 21 | horizontalElasticity 0 22 | verticalElasticity 0 23 | 10.8 allowsMagnification 0 24 | 10.8 maxMagnification 4 25 | 10.8 minMagnification 0.25 26 | -------------------------------------------------------------------------------- /_wip/sv/textview.nots: -------------------------------------------------------------------------------- 1 | backgroundColor NSCalibratedWhiteColorSpace 1 1 2 | drawsBackground 1 3 | borderType 2 4 | documentCursor 5 | hasHorizontalScroller 0 6 | hasVerticalScroller 1 7 | autohidesScrollers 0 8 | hasHorizontalRuler 0 9 | hasVerticalRuler 0 10 | rulersVisible 0 11 | 10.10 autoAdjContentInsets 1 12 | scrollerKnobStyle 0 13 | scrollerStyle 1 14 | horizontalLineScroll 10 15 | verticalLineScroll 10 16 | horizontalPageScroll 10 17 | verticalPageScroll 10 18 | scrollsDynamically 1 19 | findBarPosition 1 20 | usesPredomAxisScroll 0 21 | horizontalElasticity 0 22 | verticalElasticity 0 23 | 10.8 allowsMagnification 0 24 | 10.8 maxMagnification 4 25 | 10.8 minMagnification 0.25 26 | -------------------------------------------------------------------------------- /azure-pipelines/artifacts.yml: -------------------------------------------------------------------------------- 1 | # 6 april 2019 2 | 3 | parameters: 4 | os: '' 5 | arch: '' 6 | libtype: '' 7 | libfiles: '' 8 | osHeader: '' 9 | 10 | steps: 11 | - script: | 12 | set -x 13 | pushd build/meson-out 14 | cp ../../ui.h ../../${{ parameters.osHeader }} . 15 | tar czf $(Build.ArtifactStagingDirectory)/libui-$(Build.SourceBranchName)-${{ parameters.os }}-${{ parameters.arch }}-${{ parameters.libtype }}.tgz ${{ parameters.libfiles }} ui.h ${{ parameters.osHeader}} 16 | tar czf $(Build.ArtifactStagingDirectory)/examples-$(Build.SourceBranchName)-${{ parameters.os }}-${{ parameters.arch }}-${{ parameters.libtype }}.tgz $(releaseExamples) 17 | rm ui.h ${{ parameters.osHeader }} 18 | popd 19 | displayName: 'Create Artifacts' 20 | - task: GitHubRelease@0 21 | condition: startsWith(variables['Build.SourceBranch'], 'refs/tags/') 22 | inputs: 23 | gitHubConnection: andlabs 24 | repositoryName: andlabs/libui 25 | action: 'edit' 26 | addChangelog: false 27 | assets: '$(Build.ArtifactStagingDirectory)/*' 28 | assetUploadMode: 'replace' 29 | -------------------------------------------------------------------------------- /common/controlsigs.h: -------------------------------------------------------------------------------- 1 | // 24 april 2016 2 | 3 | // LONGTERM if I don't decide to remove these outright, should they be renamed uiprivTypeNameSignature? these aren't real symbols, so... 4 | 5 | #define uiAreaSignature 0x41726561 6 | #define uiBoxSignature 0x426F784C 7 | #define uiButtonSignature 0x42746F6E 8 | #define uiCheckboxSignature 0x43686B62 9 | #define uiColorButtonSignature 0x436F6C42 10 | #define uiComboboxSignature 0x436F6D62 11 | #define uiDateTimePickerSignature 0x44545069 12 | #define uiEditableComboboxSignature 0x45644362 13 | #define uiEntrySignature 0x456E7472 14 | #define uiFontButtonSignature 0x466F6E42 15 | #define uiFormSignature 0x466F726D 16 | #define uiGridSignature 0x47726964 17 | #define uiGroupSignature 0x47727062 18 | #define uiLabelSignature 0x4C61626C 19 | #define uiMultilineEntrySignature 0x4D6C6E45 20 | #define uiProgressBarSignature 0x50426172 21 | #define uiRadioButtonsSignature 0x5264696F 22 | #define uiSeparatorSignature 0x53657061 23 | #define uiSliderSignature 0x536C6964 24 | #define uiSpinboxSignature 0x5370696E 25 | #define uiTabSignature 0x54616273 26 | #define uiTableSignature 0x5461626C 27 | #define uiWindowSignature 0x57696E64 28 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014 Pietro Gagliardi 2 | 3 | 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: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | 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. 8 | 9 | (this is called the MIT License or Expat License; see http://www.opensource.org/licenses/MIT) 10 | -------------------------------------------------------------------------------- /unix/attrstr.h: -------------------------------------------------------------------------------- 1 | // 11 march 2018 2 | #include "../common/attrstr.h" 3 | 4 | // See https://developer.gnome.org/pango/1.30/pango-Cairo-Rendering.html#pango-Cairo-Rendering.description 5 | // For the conversion, see https://developer.gnome.org/pango/1.30/pango-Glyph-Storage.html#pango-units-to-double and https://developer.gnome.org/pango/1.30/pango-Glyph-Storage.html#pango-units-from-double 6 | #define pangoToCairo(pango) (pango_units_to_double(pango)) 7 | #define cairoToPango(cairo) (pango_units_from_double(cairo)) 8 | 9 | // opentype.c 10 | extern GString *uiprivOpenTypeFeaturesToPangoCSSFeaturesString(const uiOpenTypeFeatures *otf); 11 | 12 | // fontmatch.c 13 | extern PangoWeight uiprivWeightToPangoWeight(uiTextWeight w); 14 | extern PangoStyle uiprivItalicToPangoStyle(uiTextItalic i); 15 | extern PangoStretch uiprivStretchToPangoStretch(uiTextStretch s); 16 | extern PangoFontDescription *uiprivFontDescriptorToPangoFontDescription(const uiFontDescriptor *uidesc); 17 | extern void uiprivFontDescriptorFromPangoFontDescription(PangoFontDescription *pdesc, uiFontDescriptor *uidesc); 18 | 19 | // attrstr.c 20 | extern PangoAttrList *uiprivAttributedStringToPangoAttrList(uiDrawTextLayoutParams *p); 21 | -------------------------------------------------------------------------------- /_notes/i18n: -------------------------------------------------------------------------------- 1 | https://msdn.microsoft.com/en-us/library/windows/desktop/dd319079(v=vs.85).aspx 2 | https://msdn.microsoft.com/en-us/library/windows/desktop/dd318103(v=vs.85).aspx 3 | https://stackoverflow.com/questions/4663855/is-there-a-repository-for-localized-common-text-in-winforms 4 | https://stackoverflow.com/questions/2502375/find-localized-windows-strings 5 | https://docs.microsoft.com/en-us/windows-hardware/customize/mobile/mcsf/create-a-resource-only-dll-for-localized-strings 6 | https://msdn.microsoft.com/en-us/library/windows/desktop/ee845043(v=vs.85).aspx 7 | https://msdn.microsoft.com/en-us/library/cc194807.aspx 8 | https://www.codeproject.com/Articles/10542/Easily-Load-and-Format-Strings-from-the-String-Tab 9 | https://www.codeproject.com/Tips/431045/The-inner-working-of-FindResource-and-LoadString-W 10 | https://mihai-nita.net/2007/05/03/how-to-localize-an-rc-file/ 11 | https://www.microsoft.com/en-us/language 12 | https://www.microsoft.com/en-us/language/Terminology 13 | https://www.microsoft.com/en-us/language/LicenseAgreement 14 | https://www.microsoft.com/en-us/language/Translations 15 | http://www.ttt.org/oscarstandards/tbx/ 16 | https://blogs.msdn.microsoft.com/oldnewthing/20181122-00/?p=100295 17 | -------------------------------------------------------------------------------- /darwin/separator.m: -------------------------------------------------------------------------------- 1 | // 14 august 2015 2 | #import "uipriv_darwin.h" 3 | 4 | // TODO make this intrinsic 5 | #define separatorWidth 96 6 | #define separatorHeight 96 7 | 8 | struct uiSeparator { 9 | uiDarwinControl c; 10 | NSBox *box; 11 | }; 12 | 13 | uiDarwinControlAllDefaults(uiSeparator, box) 14 | 15 | uiSeparator *uiNewHorizontalSeparator(void) 16 | { 17 | uiSeparator *s; 18 | 19 | uiDarwinNewControl(uiSeparator, s); 20 | 21 | // make the initial width >= initial height to force horizontal 22 | s->box = [[NSBox alloc] initWithFrame:NSMakeRect(0, 0, 100, 1)]; 23 | [s->box setBoxType:NSBoxSeparator]; 24 | [s->box setBorderType:NSGrooveBorder]; 25 | [s->box setTransparent:NO]; 26 | [s->box setTitlePosition:NSNoTitle]; 27 | 28 | return s; 29 | } 30 | 31 | uiSeparator *uiNewVerticalSeparator(void) 32 | { 33 | uiSeparator *s; 34 | 35 | uiDarwinNewControl(uiSeparator, s); 36 | 37 | // make the initial height >= initial width to force vertical 38 | s->box = [[NSBox alloc] initWithFrame:NSMakeRect(0, 0, 1, 100)]; 39 | [s->box setBoxType:NSBoxSeparator]; 40 | [s->box setBorderType:NSGrooveBorder]; 41 | [s->box setTransparent:NO]; 42 | [s->box setTitlePosition:NSNoTitle]; 43 | 44 | return s; 45 | } 46 | -------------------------------------------------------------------------------- /test/page8.c: -------------------------------------------------------------------------------- 1 | // 22 december 2015 2 | #include "test.h" 3 | 4 | static void onListFonts(uiButton *b, void *data) 5 | { 6 | uiDrawFontFamilies *ff; 7 | char *this; 8 | int i, n; 9 | 10 | uiMultilineEntrySetText(uiMultilineEntry(data), ""); 11 | ff = uiDrawListFontFamilies(); 12 | n = uiDrawFontFamiliesNumFamilies(ff); 13 | for (i = 0; i < n; i++) { 14 | this = uiDrawFontFamiliesFamily(ff, i); 15 | uiMultilineEntryAppend(uiMultilineEntry(data), this); 16 | uiMultilineEntryAppend(uiMultilineEntry(data), "\n"); 17 | uiFreeText(this); 18 | } 19 | uiDrawFreeFontFamilies(ff); 20 | } 21 | 22 | uiBox *makePage8(void) 23 | { 24 | uiBox *page8; 25 | uiGroup *group; 26 | uiBox *vbox; 27 | uiMultilineEntry *me; 28 | uiButton *button; 29 | 30 | page8 = newHorizontalBox(); 31 | 32 | group = newGroup("Font Families"); 33 | uiBoxAppend(page8, uiControl(group), 1); 34 | 35 | vbox = newVerticalBox(); 36 | uiGroupSetChild(group, uiControl(vbox)); 37 | 38 | me = uiNewMultilineEntry(); 39 | uiBoxAppend(vbox, uiControl(me), 1); 40 | 41 | button = uiNewButton("List Font Families"); 42 | uiButtonOnClicked(button, onListFonts, me); 43 | uiBoxAppend(vbox, uiControl(button), 0); 44 | 45 | return page8; 46 | } 47 | -------------------------------------------------------------------------------- /windows/libui.manifest: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | Your application description here. 10 | 11 | 12 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /test/meson.build: -------------------------------------------------------------------------------- 1 | # 23 march 2019 2 | 3 | libui_test_sources = [ 4 | 'drawtests.c', 5 | 'images.c', 6 | 'main.c', 7 | 'menus.c', 8 | 'page1.c', 9 | 'page2.c', 10 | 'page3.c', 11 | 'page4.c', 12 | 'page5.c', 13 | 'page6.c', 14 | 'page7.c', 15 | 'page7a.c', 16 | 'page7b.c', 17 | 'page7c.c', 18 | # 'page8.c', 19 | # 'page9.c', 20 | # 'page10.c', 21 | 'page11.c', 22 | 'page12.c', 23 | 'page13.c', 24 | 'page14.c', 25 | 'page15.c', 26 | 'page16.c', 27 | 'spaced.c', 28 | ] 29 | 30 | if libui_OS == 'windows' 31 | libui_test_manifest = 'test.manifest' 32 | if libui_mode == 'static' 33 | libui_test_manifest = 'test.static.manifest' 34 | endif 35 | libui_test_sources += [ 36 | windows.compile_resources('resources.rc', 37 | args: libui_manifest_args, 38 | depend_files: [libui_test_manifest]), 39 | ] 40 | endif 41 | 42 | # TODO meson doesn't let us name this target test, but also doesn't seem to provide a way to override the executable name???? we'll probably need to file a feature request for this 43 | # TODO once we upgrade to 0.49.0, add pie: true 44 | executable('tester', libui_test_sources, 45 | dependencies: libui_binary_deps, 46 | link_with: libui_libui, 47 | gui_app: false, 48 | install: false) 49 | -------------------------------------------------------------------------------- /windows/_rc2bin/libui.manifest: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | Your application description here. 10 | 11 | 12 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /windows/opentype.cpp: -------------------------------------------------------------------------------- 1 | // 11 may 2017 2 | #include "uipriv_windows.hpp" 3 | #include "attrstr.hpp" 4 | 5 | // TODO pull out my decision for empty uiOpenTypeFeatures, assuming that it isn't in another file or that I even made one 6 | 7 | static uiForEach addToTypography(const uiOpenTypeFeatures *otf, char a, char b, char c, char d, uint32_t value, void *data) 8 | { 9 | IDWriteTypography *dt = (IDWriteTypography *) data; 10 | DWRITE_FONT_FEATURE dff; 11 | HRESULT hr; 12 | 13 | ZeroMemory(&dff, sizeof (DWRITE_FONT_FEATURE)); 14 | // yes, the cast here is necessary (the compiler will complain otherwise)... 15 | dff.nameTag = (DWRITE_FONT_FEATURE_TAG) DWRITE_MAKE_OPENTYPE_TAG(a, b, c, d); 16 | dff.parameter = (UINT32) value; 17 | hr = dt->AddFontFeature(dff); 18 | if (hr != S_OK) 19 | logHRESULT(L"error adding OpenType feature to IDWriteTypography", hr); 20 | return uiForEachContinue; 21 | } 22 | 23 | IDWriteTypography *uiprivOpenTypeFeaturesToIDWriteTypography(const uiOpenTypeFeatures *otf) 24 | { 25 | IDWriteTypography *dt; 26 | HRESULT hr; 27 | 28 | hr = dwfactory->CreateTypography(&dt); 29 | if (hr != S_OK) 30 | logHRESULT(L"error creating IDWriteTypography", hr); 31 | uiOpenTypeFeaturesForEach(otf, addToTypography, dt); 32 | return dt; 33 | } 34 | -------------------------------------------------------------------------------- /darwin/undocumented.m: -------------------------------------------------------------------------------- 1 | // 3 november 2017 2 | #import "uipriv_darwin.h" 3 | 4 | // functions and constants FROM THE DEPTHS BELOW! 5 | // note: for constants, dlsym() returns the address of the constant itself, as if we had done &constantName 6 | // we also provide default values just in case 7 | 8 | // these values come from 10.12.6 9 | CFStringRef uiprivUNDOC_kCTFontPreferredSubFamilyNameKey = CFSTR("CTFontPreferredSubFamilyName"); 10 | CFStringRef uiprivUNDOC_kCTFontPreferredFamilyNameKey = CFSTR("CTFontPreferredFamilyName"); 11 | 12 | // note that we treat any error as "the symbols aren't there" (and don't care if dlclose() failed) 13 | void uiprivLoadUndocumented(void) 14 | { 15 | void *handle; 16 | CFStringRef *str; 17 | 18 | // dlsym() walks the dependency chain, so opening the current process should be sufficient 19 | handle = dlopen(NULL, RTLD_LAZY); 20 | if (handle == NULL) 21 | return; 22 | #define GET(var, fn) *((void **) (&var)) = dlsym(handle, #fn) 23 | GET(str, kCTFontPreferredSubFamilyNameKey); 24 | NSLog(@"get %p", str); 25 | if (str != NULL) 26 | uiprivUNDOC_kCTFontPreferredSubFamilyNameKey = *str; 27 | GET(str, kCTFontPreferredFamilyNameKey); 28 | if (str != NULL) 29 | uiprivUNDOC_kCTFontPreferredFamilyNameKey = *str; 30 | dlclose(handle); 31 | } 32 | -------------------------------------------------------------------------------- /test/test.static.manifest: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | Your application description here. 10 | 11 | 12 | 13 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /examples/example.static.manifest: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | Your application description here. 10 | 11 | 12 | 13 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /azure-pipelines/windows-artifacts.yml: -------------------------------------------------------------------------------- 1 | # 6 april 2019 2 | 3 | parameters: 4 | os: '' 5 | arch: '' 6 | toolchain: '' 7 | libtype: '' 8 | libfiles: '' 9 | osHeader: '' 10 | 11 | steps: 12 | - powershell: | 13 | pushd build\meson-out 14 | Copy-Item @("..\..\ui.h","..\..\${{ parameters.osHeader }}") -Destination . 15 | Compress-Archive -Destination $(Build.ArtifactStagingDirectory)\libui-$(Build.SourceBranchName)-${{ parameters.os }}-${{ parameters.arch }}-${{ parameters.toolchain }}-${{ parameters.libtype }}.zip -Path @("${{ parameters.libfiles }}".Split(" ") + @("ui.h","${{ parameters.osHeader}}")) 16 | Compress-Archive -Destination $(Build.ArtifactStagingDirectory)\examples-$(Build.SourceBranchName)-${{ parameters.os }}-${{ parameters.arch }}-${{ parameters.libtype }}.zip -Path @("$(releaseExamples)".Split(" ") | % {$_ + ".exe"}) 17 | Remove-Item @("ui.h","${{ parameters.osHeader }}") 18 | popd 19 | displayName: 'Create Artifacts' 20 | - task: GitHubRelease@0 21 | condition: startsWith(variables['Build.SourceBranch'], 'refs/tags/') 22 | inputs: 23 | gitHubConnection: andlabs 24 | repositoryName: andlabs/libui 25 | action: 'edit' 26 | addChangelog: false 27 | assets: '$(Build.ArtifactStagingDirectory)/*' 28 | assetUploadMode: 'replace' 29 | -------------------------------------------------------------------------------- /unix/button.c: -------------------------------------------------------------------------------- 1 | // 10 june 2015 2 | #include "uipriv_unix.h" 3 | 4 | struct uiButton { 5 | uiUnixControl c; 6 | GtkWidget *widget; 7 | GtkButton *button; 8 | void (*onClicked)(uiButton *, void *); 9 | void *onClickedData; 10 | }; 11 | 12 | uiUnixControlAllDefaults(uiButton) 13 | 14 | static void onClicked(GtkButton *button, gpointer data) 15 | { 16 | uiButton *b = uiButton(data); 17 | 18 | (*(b->onClicked))(b, b->onClickedData); 19 | } 20 | 21 | static void defaultOnClicked(uiButton *b, void *data) 22 | { 23 | // do nothing 24 | } 25 | 26 | char *uiButtonText(uiButton *b) 27 | { 28 | return uiUnixStrdupText(gtk_button_get_label(b->button)); 29 | } 30 | 31 | void uiButtonSetText(uiButton *b, const char *text) 32 | { 33 | gtk_button_set_label(b->button, text); 34 | } 35 | 36 | void uiButtonOnClicked(uiButton *b, void (*f)(uiButton *, void *), void *data) 37 | { 38 | b->onClicked = f; 39 | b->onClickedData = data; 40 | } 41 | 42 | uiButton *uiNewButton(const char *text) 43 | { 44 | uiButton *b; 45 | 46 | uiUnixNewControl(uiButton, b); 47 | 48 | b->widget = gtk_button_new_with_label(text); 49 | b->button = GTK_BUTTON(b->widget); 50 | 51 | g_signal_connect(b->widget, "clicked", G_CALLBACK(onClicked), b); 52 | uiButtonOnClicked(b, defaultOnClicked, NULL); 53 | 54 | return b; 55 | } 56 | -------------------------------------------------------------------------------- /examples/timer/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "../../ui.h" 5 | 6 | uiMultilineEntry *e; 7 | 8 | int sayTime(void *data) 9 | { 10 | time_t t; 11 | char *s; 12 | 13 | t = time(NULL); 14 | s = ctime(&t); 15 | 16 | uiMultilineEntryAppend(e, s); 17 | return 1; 18 | } 19 | 20 | int onClosing(uiWindow *w, void *data) 21 | { 22 | uiQuit(); 23 | return 1; 24 | } 25 | 26 | void saySomething(uiButton *b, void *data) 27 | { 28 | uiMultilineEntryAppend(e, "Saying something\n"); 29 | } 30 | 31 | int main(void) 32 | { 33 | uiInitOptions o; 34 | uiWindow *w; 35 | uiBox *b; 36 | uiButton *btn; 37 | 38 | memset(&o, 0, sizeof (uiInitOptions)); 39 | if (uiInit(&o) != NULL) 40 | abort(); 41 | 42 | w = uiNewWindow("Hello", 320, 240, 0); 43 | uiWindowSetMargined(w, 1); 44 | 45 | b = uiNewVerticalBox(); 46 | uiBoxSetPadded(b, 1); 47 | uiWindowSetChild(w, uiControl(b)); 48 | 49 | e = uiNewMultilineEntry(); 50 | uiMultilineEntrySetReadOnly(e, 1); 51 | 52 | btn = uiNewButton("Say Something"); 53 | uiButtonOnClicked(btn, saySomething, NULL); 54 | uiBoxAppend(b, uiControl(btn), 0); 55 | 56 | uiBoxAppend(b, uiControl(e), 1); 57 | 58 | uiTimer(1000, sayTime, NULL); 59 | 60 | uiWindowOnClosing(w, onClosing, NULL); 61 | uiControlShow(uiControl(w)); 62 | uiMain(); 63 | return 0; 64 | } 65 | -------------------------------------------------------------------------------- /_future/textlanguageattr/drawtext_example.c: -------------------------------------------------------------------------------- 1 | before "or any combination of the above" 2 | 3 | // thanks to https://twitter.com/codeman38/status/831924064012886017 4 | next = "\xD0\xB1\xD0\xB3\xD0\xB4\xD0\xBF\xD1\x82"; 5 | uiAttributedStringAppendUnattributed(attrstr, "multiple languages (compare "); 6 | start = uiAttributedStringLen(attrstr); 7 | end = start + strlen(next); 8 | uiAttributedStringAppendUnattributed(attrstr, next); 9 | spec.Type = uiAttributeItalic; 10 | spec.Value = uiDrawTextItalicItalic; 11 | uiAttributedStringSetAttribute(attrstr, &spec, start, end); 12 | spec.Type = uiAttributeLanguage; 13 | spec.Value = (uintptr_t) "ru"; 14 | uiAttributedStringSetAttribute(attrstr, &spec, start, end); 15 | uiAttributedStringAppendUnattributed(attrstr, " to "); 16 | start = uiAttributedStringLen(attrstr); 17 | end = start + strlen(next); 18 | uiAttributedStringAppendUnattributed(attrstr, next); 19 | spec.Type = uiAttributeItalic; 20 | spec.Value = uiDrawTextItalicItalic; 21 | uiAttributedStringSetAttribute(attrstr, &spec, start, end); 22 | spec.Type = uiAttributeLanguage; 23 | spec.Value = (uintptr_t) "sr"; 24 | uiAttributedStringSetAttribute(attrstr, &spec, start, end); 25 | uiAttributedStringAppendUnattributed(attrstr, " \xE2\x80\x94 may require changing the font)"); 26 | 27 | uiAttributedStringAppendUnattributed(attrstr, ", "); 28 | -------------------------------------------------------------------------------- /windows/area.hpp: -------------------------------------------------------------------------------- 1 | // 18 december 2015 2 | 3 | // TODOs 4 | // - things look very wrong on initial draw 5 | // - initial scrolling is not set properly 6 | // - should background be inherited from parent control? 7 | 8 | struct uiArea { 9 | uiWindowsControl c; 10 | HWND hwnd; 11 | uiAreaHandler *ah; 12 | 13 | BOOL scrolling; 14 | int scrollWidth; 15 | int scrollHeight; 16 | int hscrollpos; 17 | int vscrollpos; 18 | int hwheelCarry; 19 | int vwheelCarry; 20 | 21 | uiprivClickCounter cc; 22 | BOOL capturing; 23 | 24 | BOOL inside; 25 | BOOL tracking; 26 | 27 | ID2D1HwndRenderTarget *rt; 28 | }; 29 | 30 | // areadraw.cpp 31 | extern BOOL areaDoDraw(uiArea *a, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *lResult); 32 | extern void areaDrawOnResize(uiArea *, RECT *); 33 | 34 | // areascroll.cpp 35 | extern BOOL areaDoScroll(uiArea *a, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *lResult); 36 | extern void areaScrollOnResize(uiArea *, RECT *); 37 | extern void areaUpdateScroll(uiArea *a); 38 | 39 | // areaevents.cpp 40 | extern BOOL areaDoEvents(uiArea *a, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *lResult); 41 | 42 | // areautil.cpp 43 | extern void loadAreaSize(uiArea *a, ID2D1RenderTarget *rt, double *width, double *height); 44 | extern void pixelsToDIP(uiArea *a, double *x, double *y); 45 | extern void dipToPixels(uiArea *a, double *x, double *y); 46 | -------------------------------------------------------------------------------- /test/page11.c: -------------------------------------------------------------------------------- 1 | // 14 may 2016 2 | #include "test.h" 3 | 4 | // TODO add a test for childless windows 5 | // TODO add tests for contianers with all controls hidden 6 | 7 | static uiGroup *newg(const char *n, int s) 8 | { 9 | uiGroup *g; 10 | 11 | g = uiNewGroup(n); 12 | if (s) 13 | uiGroupSetChild(g, NULL); 14 | return g; 15 | } 16 | 17 | static uiTab *newt(int tt) 18 | { 19 | uiTab *t; 20 | 21 | t = uiNewTab(); 22 | if (tt) 23 | uiTabAppend(t, "Test", NULL); 24 | return t; 25 | } 26 | 27 | uiBox *makePage11(void) 28 | { 29 | uiBox *page11; 30 | uiBox *ns; 31 | uiBox *s; 32 | 33 | page11 = newHorizontalBox(); 34 | 35 | ns = newVerticalBox(); 36 | uiBoxAppend(ns, uiControl(newg("", 0)), 0); 37 | uiBoxAppend(ns, uiControl(newg("", 1)), 0); 38 | uiBoxAppend(ns, uiControl(newg("Group", 0)), 0); 39 | uiBoxAppend(ns, uiControl(newg("Group", 1)), 0); 40 | uiBoxAppend(ns, uiControl(newt(0)), 0); 41 | uiBoxAppend(ns, uiControl(newt(1)), 0); 42 | uiBoxAppend(page11, uiControl(ns), 1); 43 | 44 | s = newVerticalBox(); 45 | uiBoxAppend(s, uiControl(newg("", 0)), 1); 46 | uiBoxAppend(s, uiControl(newg("", 1)), 1); 47 | uiBoxAppend(s, uiControl(newg("Group", 0)), 1); 48 | uiBoxAppend(s, uiControl(newg("Group", 1)), 1); 49 | uiBoxAppend(s, uiControl(newt(0)), 1); 50 | uiBoxAppend(s, uiControl(newt(1)), 1); 51 | uiBoxAppend(page11, uiControl(s), 1); 52 | 53 | return page11; 54 | } 55 | -------------------------------------------------------------------------------- /_doc/export/ttfixedtest.go: -------------------------------------------------------------------------------- 1 | // 2 november 2017 2 | package main 3 | 4 | import ( 5 | "fmt" 6 | ) 7 | 8 | type fixed1616 uint32 9 | type fixed214 uint16 10 | 11 | func fixed1616To214(f fixed1616) fixed214 { 12 | f += 0x00000002 13 | g := int32(f) >> 2 14 | return fixed214(uint32(g) & 0xFFFF) 15 | } 16 | 17 | func (f fixed1616) In214Range() bool { 18 | base := int16((f >> 16) & 0xFFFF) 19 | return base >= -2 && base < 2 20 | } 21 | 22 | func (f fixed1616) String() string { 23 | base := int16((f >> 16) & 0xFFFF) 24 | frac := float64(f & 0xFFFF) / 65536 25 | res := float64(base) + frac 26 | return fmt.Sprintf("%f 0x%08X", res, uint32(f)) 27 | } 28 | 29 | func (f fixed214) String() string { 30 | base := []int16{ 31 | 0, 32 | 1, 33 | -2, 34 | -1, 35 | }[(f & 0xC000) >> 14] 36 | frac := float64(f & 0x3FFF) / 16384 37 | res := float64(base) + frac 38 | return fmt.Sprintf("%f 0x%04X", res, uint16(f)) 39 | } 40 | 41 | func main() { 42 | fmt.Println(fixed214(0x7fff)) 43 | fmt.Println(fixed214(0x8000)) 44 | fmt.Println(fixed214(0x4000)) 45 | fmt.Println(fixed214(0xc000)) 46 | fmt.Println(fixed214(0x7000)) 47 | fmt.Println(fixed214(0x0000)) 48 | fmt.Println(fixed214(0x0001)) 49 | fmt.Println(fixed214(0xffff)) 50 | 51 | fmt.Println() 52 | 53 | for i := uint64(0x00000000); i <= 0xFFFFFFFF; i++ { 54 | j := fixed1616(i) 55 | if !j.In214Range() { continue } 56 | fmt.Println(j, "->", fixed1616To214(j)) 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /darwin/OLD_table.m: -------------------------------------------------------------------------------- 1 | // 21 june 2016 2 | #import "uipriv_darwin.h" 3 | 4 | // TODOs 5 | // - header cell seems off 6 | // - background color shows up for a line or two below selection 7 | // - editable NSTextFields have no intrinsic width 8 | // - is the Y position of checkbox cells correct? 9 | 10 | @implementation tablePart 11 | 12 | - (NSView *)mkView:(uiTableModel *)m row:(int)row 13 | { 14 | // if stretchy, don't hug, otherwise hug forcibly 15 | if (self.expand) 16 | [view setContentHuggingPriority:NSLayoutPriorityDefaultLow forOrientation:NSLayoutConstraintOrientationHorizontal]; 17 | else 18 | [view setContentHuggingPriority:NSLayoutPriorityRequired forOrientation:NSLayoutConstraintOrientationHorizontal]; 19 | } 20 | 21 | @end 22 | 23 | uiTableColumn *uiTableAppendColumn(uiTable *t, const char *name) 24 | { 25 | uiTableColumn *c; 26 | 27 | c = uiprivNew(uiTableColumn); 28 | c->c = [[tableColumn alloc] initWithIdentifier:@""]; 29 | c->c.libui_col = c; 30 | // via Interface Builder 31 | [c->c setResizingMask:(NSTableColumnAutoresizingMask | NSTableColumnUserResizingMask)]; 32 | // 10.10 adds -[NSTableColumn setTitle:]; before then we have to do this 33 | [[c->c headerCell] setStringValue:uiprivToNSString(name)]; 34 | // TODO is this sufficient? 35 | [[c->c headerCell] setFont:[NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSSmallControlSize]]]; 36 | c->parts = [NSMutableArray new]; 37 | [t->tv addTableColumn:c->c]; 38 | return c; 39 | } 40 | -------------------------------------------------------------------------------- /_future/verticaltext/README: -------------------------------------------------------------------------------- 1 | Proper vertical text support in uiDrawTextLayout was removed because DirectWrite doesn't add this until Windows 8.1 (unless I drop IDWriteTextLayout and do the script analysis myself; TODO consider this possibility). 2 | 3 | On OS X, setting the vertical forms attribute stacks non-vertical scripts in vertical text (rotates each individual glyph) with Core Text, whereas everything else — including Cocoa's text system — rotates entire non-vertical strings. Not sure what to do about this except manually detect which characters to apply the attribute to: 4 | http://www.unicode.org/notes/tn22/RobustVerticalLayout.pdf 5 | http://www.unicode.org/Public/vertical/revision-17/VerticalOrientation-17.txt 6 | 7 | In addition, with Core Text, the vertical forms attribute vertically centers the vertical glyphs on the bhorizontal baseline, rather than flush with the text. Using the baseline class attribute doesn't seem to work. 8 | TODO investigate kCJKVerticalRomanPlacementType 9 | 10 | If readded, this will need to be a layout-wide setting, not a per-character setting. Pango works right this way; the current Pango code doesn't seem to work. 11 | 12 | More links: 13 | https://www.w3.org/TR/2012/NOTE-jlreq-20120403/#line-composition 14 | https://www.w3.org/TR/REC-CSS2/notes.html 15 | 16 | TODO indicate where in the attributes.c file that block of code should go (or drop it entirely for the reasons listed above) 17 | TODO same for ui.h 18 | 19 | TODO vertical carets 20 | -------------------------------------------------------------------------------- /test/page12.c: -------------------------------------------------------------------------------- 1 | // 22 may 2016 2 | #include "test.h" 3 | 4 | // TODO OS X: if the hboxes are empty, the text views don't show up 5 | 6 | static void meChanged(uiMultilineEntry *e, void *data) 7 | { 8 | printf("%s changed\n", (char *) data); 9 | } 10 | 11 | static void setClicked(uiButton *b, void *data) 12 | { 13 | uiMultilineEntrySetText(uiMultilineEntry(data), "set"); 14 | } 15 | 16 | static void appendClicked(uiButton *b, void *data) 17 | { 18 | uiMultilineEntryAppend(uiMultilineEntry(data), "append\n"); 19 | } 20 | 21 | static uiBox *half(uiMultilineEntry *(*mk)(void), const char *which) 22 | { 23 | uiBox *vbox, *hbox; 24 | uiMultilineEntry *me; 25 | uiButton *button; 26 | 27 | vbox = newVerticalBox(); 28 | 29 | me = (*mk)(); 30 | uiMultilineEntryOnChanged(me, meChanged, (void *) which); 31 | uiBoxAppend(vbox, uiControl(me), 1); 32 | 33 | hbox = newHorizontalBox(); 34 | uiBoxAppend(vbox, uiControl(hbox), 0); 35 | 36 | button = uiNewButton("Set"); 37 | uiButtonOnClicked(button, setClicked, me); 38 | uiBoxAppend(hbox, uiControl(button), 0); 39 | 40 | button = uiNewButton("Append"); 41 | uiButtonOnClicked(button, appendClicked, me); 42 | uiBoxAppend(hbox, uiControl(button), 0); 43 | 44 | return vbox; 45 | } 46 | 47 | uiBox *makePage12(void) 48 | { 49 | uiBox *page12; 50 | uiBox *b; 51 | 52 | page12 = newHorizontalBox(); 53 | 54 | b = half(uiNewMultilineEntry, "wrap"); 55 | uiBoxAppend(page12, uiControl(b), 1); 56 | b = half(uiNewNonWrappingMultilineEntry, "no wrap"); 57 | uiBoxAppend(page12, uiControl(b), 1); 58 | 59 | return page12; 60 | } 61 | -------------------------------------------------------------------------------- /common/matrix.c: -------------------------------------------------------------------------------- 1 | // 11 october 2015 2 | #include 3 | #include "../ui.h" 4 | #include "uipriv.h" 5 | 6 | void uiDrawMatrixSetIdentity(uiDrawMatrix *m) 7 | { 8 | m->M11 = 1; 9 | m->M12 = 0; 10 | m->M21 = 0; 11 | m->M22 = 1; 12 | m->M31 = 0; 13 | m->M32 = 0; 14 | } 15 | 16 | // The rest of this file provides basic utilities in case the platform doesn't provide any of its own for these tasks. 17 | // Keep these as minimal as possible. They should generally not call other fallbacks. 18 | 19 | // see https://msdn.microsoft.com/en-us/library/windows/desktop/ff684171%28v=vs.85%29.aspx#skew_transform 20 | // TODO see if there's a way we can avoid the multiplication 21 | void uiprivFallbackSkew(uiDrawMatrix *m, double x, double y, double xamount, double yamount) 22 | { 23 | uiDrawMatrix n; 24 | 25 | uiDrawMatrixSetIdentity(&n); 26 | // TODO explain this 27 | n.M12 = tan(yamount); 28 | n.M21 = tan(xamount); 29 | n.M31 = -y * tan(xamount); 30 | n.M32 = -x * tan(yamount); 31 | uiDrawMatrixMultiply(m, &n); 32 | } 33 | 34 | void uiprivScaleCenter(double xCenter, double yCenter, double *x, double *y) 35 | { 36 | *x = xCenter - (*x * xCenter); 37 | *y = yCenter - (*y * yCenter); 38 | } 39 | 40 | // the basic algorithm is from cairo 41 | // but it's the same algorithm as the transform point, just without M31 and M32 taken into account, so let's just do that instead 42 | void uiprivFallbackTransformSize(uiDrawMatrix *m, double *x, double *y) 43 | { 44 | uiDrawMatrix m2; 45 | 46 | m2 = *m; 47 | m2.M31 = 0; 48 | m2.M32 = 0; 49 | uiDrawMatrixTransformPoint(&m2, x, y); 50 | } 51 | -------------------------------------------------------------------------------- /windows/label.cpp: -------------------------------------------------------------------------------- 1 | // 11 april 2015 2 | #include "uipriv_windows.hpp" 3 | 4 | struct uiLabel { 5 | uiWindowsControl c; 6 | HWND hwnd; 7 | }; 8 | 9 | uiWindowsControlAllDefaults(uiLabel) 10 | 11 | // via http://msdn.microsoft.com/en-us/library/windows/desktop/dn742486.aspx#sizingandspacing 12 | #define labelHeight 8 13 | 14 | static void uiLabelMinimumSize(uiWindowsControl *c, int *width, int *height) 15 | { 16 | uiLabel *l = uiLabel(c); 17 | uiWindowsSizing sizing; 18 | int y; 19 | 20 | *width = uiWindowsWindowTextWidth(l->hwnd); 21 | y = labelHeight; 22 | uiWindowsGetSizing(l->hwnd, &sizing); 23 | uiWindowsSizingDlgUnitsToPixels(&sizing, NULL, &y); 24 | *height = y; 25 | } 26 | 27 | char *uiLabelText(uiLabel *l) 28 | { 29 | return uiWindowsWindowText(l->hwnd); 30 | } 31 | 32 | void uiLabelSetText(uiLabel *l, const char *text) 33 | { 34 | uiWindowsSetWindowText(l->hwnd, text); 35 | // changing the text might necessitate a change in the label's size 36 | uiWindowsControlMinimumSizeChanged(uiWindowsControl(l)); 37 | } 38 | 39 | uiLabel *uiNewLabel(const char *text) 40 | { 41 | uiLabel *l; 42 | WCHAR *wtext; 43 | 44 | uiWindowsNewControl(uiLabel, l); 45 | 46 | wtext = toUTF16(text); 47 | l->hwnd = uiWindowsEnsureCreateControlHWND(0, 48 | L"static", wtext, 49 | // SS_LEFTNOWORDWRAP clips text past the end; SS_NOPREFIX avoids accelerator translation 50 | // controls are vertically aligned to the top by default (thanks Xeek in irc.freenode.net/#winapi) 51 | SS_LEFTNOWORDWRAP | SS_NOPREFIX, 52 | hInstance, NULL, 53 | TRUE); 54 | uiprivFree(wtext); 55 | 56 | return l; 57 | } 58 | -------------------------------------------------------------------------------- /unix/meson.build: -------------------------------------------------------------------------------- 1 | # 23 march 2019 2 | 3 | libui_sources += [ 4 | 'unix/alloc.c', 5 | 'unix/area.c', 6 | 'unix/attrstr.c', 7 | 'unix/box.c', 8 | 'unix/button.c', 9 | 'unix/cellrendererbutton.c', 10 | 'unix/checkbox.c', 11 | 'unix/child.c', 12 | 'unix/colorbutton.c', 13 | 'unix/combobox.c', 14 | 'unix/control.c', 15 | 'unix/datetimepicker.c', 16 | 'unix/debug.c', 17 | 'unix/draw.c', 18 | 'unix/drawmatrix.c', 19 | 'unix/drawpath.c', 20 | 'unix/drawtext.c', 21 | 'unix/editablecombo.c', 22 | 'unix/entry.c', 23 | 'unix/fontbutton.c', 24 | 'unix/fontmatch.c', 25 | 'unix/form.c', 26 | 'unix/future.c', 27 | 'unix/graphemes.c', 28 | 'unix/grid.c', 29 | 'unix/group.c', 30 | 'unix/image.c', 31 | 'unix/label.c', 32 | 'unix/main.c', 33 | 'unix/menu.c', 34 | 'unix/multilineentry.c', 35 | 'unix/opentype.c', 36 | 'unix/progressbar.c', 37 | 'unix/radiobuttons.c', 38 | 'unix/separator.c', 39 | 'unix/slider.c', 40 | 'unix/spinbox.c', 41 | 'unix/stddialogs.c', 42 | 'unix/tab.c', 43 | 'unix/table.c', 44 | 'unix/tablemodel.c', 45 | 'unix/text.c', 46 | 'unix/util.c', 47 | 'unix/window.c', 48 | ] 49 | 50 | libui_deps += [ 51 | dependency('gtk+-3.0', 52 | version: '>=3.10.0', 53 | method: 'pkg-config', 54 | required: true), 55 | # We specify these as not required because some Unix systems include them with libc instead of providing them as separate files (thanks textshell and jpakkane in freenode #mesonbuild) 56 | meson.get_compiler('c').find_library('m', 57 | required: false), 58 | meson.get_compiler('c').find_library('dl', 59 | required: false), 60 | ] 61 | libui_soversion = '0' 62 | libui_rpath = '$ORIGIN' 63 | -------------------------------------------------------------------------------- /darwin/map.m: -------------------------------------------------------------------------------- 1 | // 17 august 2015 2 | #import "uipriv_darwin.h" 3 | 4 | // unfortunately NSMutableDictionary copies its keys, meaning we can't use it for pointers 5 | // hence, this file 6 | // we could expose a NSMapTable directly, but let's treat all pointers as opaque and hide the implementation, just to be safe and prevent even more rewrites later 7 | struct uiprivMap { 8 | NSMapTable *m; 9 | }; 10 | 11 | uiprivMap *uiprivNewMap(void) 12 | { 13 | uiprivMap *m; 14 | 15 | m = uiprivNew(uiprivMap); 16 | m->m = [[NSMapTable alloc] initWithKeyOptions:(NSPointerFunctionsOpaqueMemory | NSPointerFunctionsOpaquePersonality) 17 | valueOptions:(NSPointerFunctionsOpaqueMemory | NSPointerFunctionsOpaquePersonality) 18 | capacity:0]; 19 | return m; 20 | } 21 | 22 | void uiprivMapDestroy(uiprivMap *m) 23 | { 24 | if ([m->m count] != 0) 25 | uiprivImplBug("attempt to destroy map with items inside"); 26 | [m->m release]; 27 | uiprivFree(m); 28 | } 29 | 30 | void *uiprivMapGet(uiprivMap *m, void *key) 31 | { 32 | return NSMapGet(m->m, key); 33 | } 34 | 35 | void uiprivMapSet(uiprivMap *m, void *key, void *value) 36 | { 37 | NSMapInsert(m->m, key, value); 38 | } 39 | 40 | void uiprivMapDelete(uiprivMap *m, void *key) 41 | { 42 | NSMapRemove(m->m, key); 43 | } 44 | 45 | void uiprivMapWalk(uiprivMap *m, void (*f)(void *key, void *value)) 46 | { 47 | NSMapEnumerator e; 48 | void *k, *v; 49 | 50 | e = NSEnumerateMapTable(m->m); 51 | k = NULL; 52 | v = NULL; 53 | while (NSNextMapEnumeratorPair(&e, &k, &v)) 54 | f(k, v); 55 | NSEndMapTableEnumeration(&e); 56 | } 57 | 58 | void uiprivMapReset(uiprivMap *m) 59 | { 60 | NSResetMapTable(m->m); 61 | } 62 | -------------------------------------------------------------------------------- /darwin/meson.build: -------------------------------------------------------------------------------- 1 | # 23 march 2019 2 | 3 | libui_sources += [ 4 | 'darwin/aat.m', 5 | 'darwin/alloc.m', 6 | 'darwin/area.m', 7 | 'darwin/areaevents.m', 8 | 'darwin/attrstr.m', 9 | 'darwin/autolayout.m', 10 | 'darwin/box.m', 11 | 'darwin/button.m', 12 | 'darwin/checkbox.m', 13 | 'darwin/colorbutton.m', 14 | 'darwin/combobox.m', 15 | 'darwin/control.m', 16 | 'darwin/datetimepicker.m', 17 | 'darwin/debug.m', 18 | 'darwin/draw.m', 19 | 'darwin/drawtext.m', 20 | 'darwin/editablecombo.m', 21 | 'darwin/entry.m', 22 | 'darwin/fontbutton.m', 23 | 'darwin/fontmatch.m', 24 | 'darwin/fonttraits.m', 25 | 'darwin/fontvariation.m', 26 | 'darwin/form.m', 27 | 'darwin/future.m', 28 | 'darwin/graphemes.m', 29 | 'darwin/grid.m', 30 | 'darwin/group.m', 31 | 'darwin/image.m', 32 | 'darwin/label.m', 33 | 'darwin/main.m', 34 | 'darwin/map.m', 35 | 'darwin/menu.m', 36 | 'darwin/multilineentry.m', 37 | 'darwin/opentype.m', 38 | 'darwin/progressbar.m', 39 | 'darwin/radiobuttons.m', 40 | 'darwin/scrollview.m', 41 | 'darwin/separator.m', 42 | 'darwin/slider.m', 43 | 'darwin/spinbox.m', 44 | 'darwin/stddialogs.m', 45 | 'darwin/tab.m', 46 | 'darwin/table.m', 47 | 'darwin/tablecolumn.m', 48 | 'darwin/text.m', 49 | 'darwin/undocumented.m', 50 | 'darwin/util.m', 51 | 'darwin/window.m', 52 | 'darwin/winmoveresize.m', 53 | ] 54 | 55 | libui_deps += [ 56 | meson.get_compiler('objc').find_library('objc', 57 | required: true), 58 | dependency('appleframeworks', 59 | modules: ['Foundation', 'AppKit'], 60 | required: true), 61 | ] 62 | libui_soversion = 'A' 63 | # the / is required by some older versions of OS X 64 | libui_rpath = '@executable_path/' 65 | -------------------------------------------------------------------------------- /_future/unittest/checklist_attrstr: -------------------------------------------------------------------------------- 1 | = attributed strings 2 | attribute lengths are rounded to complete unicode codepoints 3 | zero-length attributes are elided 4 | consecutive attributes of the same type and value are merged 5 | overlapping attributes of different types do not split each other 6 | overlapping attributes of the same type but different values do split 7 | empty string is allowed 8 | empty string cannot have attributes 9 | font family names are case-insensitive both in attributes and in descriptors 10 | attributes are unique throughout a Unicode codepoint, not just to UTF-8 bytes 11 | define what "it is an error" means in the case of uiFreeAttribute() and all uiAttributeValue() functions and constructors 12 | does uiAttributeFamily() return a normalized string 13 | should uiNewAttributeBackground() be renamed to uiNewAttributeBackgroundColor() and likewise for the type constant 14 | should underline colors just ignore non-custom component arguments 15 | should any color getter function accept a NULL pointer 16 | what should uiAttributeUnderlineColor() do if the color type isn't Custom but the other pointers are non-NULL 17 | should uiOpenTypeFeaturesGet() accept a NULL value pointer 18 | what happens if uiOpenTypeFeaturesForEach() is given a NULl function pointer 19 | should FeaturesAttribute be changed to OpenTypeFeaturesAttribute and likewise for the type enum 20 | should uiNewFeaturesAttribute() accept NULL 21 | should uiNewFamilyAttribute() accept NULL 22 | it is an error in ForEach too 23 | invalid values for uiDrawTextAlign 24 | empty text layouts have one line 25 | TODO figure out what to do if any field (particularly the font family name) in uiFontDescriptor is unset 26 | -------------------------------------------------------------------------------- /windows/alloc.cpp: -------------------------------------------------------------------------------- 1 | // 4 december 2014 2 | #include "uipriv_windows.hpp" 3 | 4 | typedef std::vector byteArray; 5 | 6 | static std::map heap; 7 | static std::map types; 8 | 9 | void initAlloc(void) 10 | { 11 | // do nothing 12 | } 13 | 14 | void uninitAlloc(void) 15 | { 16 | std::ostringstream oss; 17 | std::string ossstr; // keep alive, just to be safe 18 | 19 | if (heap.size() == 0) 20 | return; 21 | for (const auto &alloc : heap) 22 | // note the void * cast; otherwise it'll be treated as a string 23 | oss << (void *) (alloc.first) << " " << types[alloc.second] << "\n"; 24 | ossstr = oss.str(); 25 | uiprivUserBug("Some data was leaked; either you left a uiControl lying around or there's a bug in libui itself. Leaked data:\n%s", ossstr.c_str()); 26 | } 27 | 28 | #define rawBytes(pa) (&((*pa)[0])) 29 | 30 | void *uiprivAlloc(size_t size, const char *type) 31 | { 32 | byteArray *out; 33 | 34 | out = new byteArray(size, 0); 35 | heap[rawBytes(out)] = out; 36 | types[out] = type; 37 | return rawBytes(out); 38 | } 39 | 40 | void *uiprivRealloc(void *_p, size_t size, const char *type) 41 | { 42 | uint8_t *p = (uint8_t *) _p; 43 | byteArray *arr; 44 | 45 | if (p == NULL) 46 | return uiprivAlloc(size, type); 47 | arr = heap[p]; 48 | // TODO does this fill in? 49 | arr->resize(size, 0); 50 | heap.erase(p); 51 | heap[rawBytes(arr)] = arr; 52 | return rawBytes(arr); 53 | } 54 | 55 | void uiprivFree(void *_p) 56 | { 57 | uint8_t *p = (uint8_t *) _p; 58 | 59 | if (p == NULL) 60 | uiprivImplBug("attempt to uiprivFree(NULL)"); 61 | types.erase(heap[p]); 62 | delete heap[p]; 63 | heap.erase(p); 64 | } 65 | -------------------------------------------------------------------------------- /_future/verticaltext/attrstr_darwin.m: -------------------------------------------------------------------------------- 1 | case uiAttributeVerticalForms: 2 | if (spec->Value != 0) { 3 | CFAttributedStringSetAttribute(p->mas, range, kCTVerticalFormsAttributeName, kCFBooleanTrue); 4 | // CFAttributedStringSetAttribute(p->mas, range, kCTBaselineClassAttributeName, kCTBaselineClassRoman); 5 | // CFAttributedStringSetAttribute(p->mas, range, kCTBaselineClassAttributeName, kCTBaselineClassIdeographicCentered); 6 | // CFAttributedStringSetAttribute(p->mas, range, kCTBaselineClassAttributeName, kCTBaselineClassIdeographicLow); 7 | // CFAttributedStringSetAttribute(p->mas, range, kCTBaselineClassAttributeName, kCTBaselineClassIdeographicHigh); 8 | // CFAttributedStringSetAttribute(p->mas, range, kCTBaselineClassAttributeName, kCTBaselineClassHanging); 9 | // CFAttributedStringSetAttribute(p->mas, range, kCTBaselineClassAttributeName, kCTBaselineClassMath); 10 | } else { 11 | CFAttributedStringSetAttribute(p->mas, range, kCTVerticalFormsAttributeName, kCFBooleanFalse); 12 | // CFAttributedStringSetAttribute(p->mas, range, kCTBaselineClassAttributeName, kCTBaselineClassRoman); 13 | // CFAttributedStringSetAttribute(p->mas, range, kCTBaselineClassAttributeName, kCTBaselineClassIdeographicCentered); 14 | // CFAttributedStringSetAttribute(p->mas, range, kCTBaselineClassAttributeName, kCTBaselineClassIdeographicLow); 15 | // CFAttributedStringSetAttribute(p->mas, range, kCTBaselineClassAttributeName, kCTBaselineClassIdeographicHigh); 16 | // CFAttributedStringSetAttribute(p->mas, range, kCTBaselineClassAttributeName, kCTBaselineClassHanging); 17 | // CFAttributedStringSetAttribute(p->mas, range, kCTBaselineClassAttributeName, kCTBaselineClassMath); 18 | } 19 | break; 20 | -------------------------------------------------------------------------------- /_wip/attrstr_metrics/numlinesbyterange: -------------------------------------------------------------------------------- 1 | darwin 2 | int uiDrawTextLayoutNumLines(uiDrawTextLayout *tl) 3 | { 4 | return CFArrayGetCount([tl->forLines lines]); 5 | } 6 | 7 | void uiDrawTextLayoutLineByteRange(uiDrawTextLayout *tl, int line, size_t *start, size_t *end) 8 | { 9 | CTLineRef lr; 10 | CFRange range; 11 | 12 | lr = (CTLineRef) CFArrayGetValueAtIndex([tl->forLines lines], line); 13 | range = CTLineGetStringRange(lr); 14 | *start = tl->u16tou8[range.location]; 15 | if (tl->empty) 16 | *end = *start; 17 | else 18 | *end = tl->u16tou8[range.location + range.length]; 19 | } 20 | 21 | 22 | unix 23 | int uiDrawTextLayoutNumLines(uiDrawTextLayout *tl) 24 | { 25 | return pango_layout_get_line_count(tl->layout); 26 | } 27 | 28 | void uiDrawTextLayoutLineByteRange(uiDrawTextLayout *tl, int line, size_t *start, size_t *end) 29 | { 30 | PangoLayoutLine *pll; 31 | 32 | pll = pango_layout_get_line_readonly(tl->layout, line); 33 | *start = pll->start_index; 34 | *end = pll->start_index + pll->length; 35 | // TODO unref pll? 36 | } 37 | 38 | 39 | windows 40 | int uiDrawTextLayoutNumLines(uiDrawTextLayout *tl) 41 | { 42 | return 0; 43 | #if 0 44 | TODO 45 | return tl->nLines; 46 | #endif 47 | } 48 | 49 | // DirectWrite doesn't provide a direct way to do this, so we have to do this manually 50 | // TODO does that comment still apply here or to the code at the top of this file? 51 | void uiDrawTextLayoutLineByteRange(uiDrawTextLayout *tl, int line, size_t *start, size_t *end) 52 | { 53 | #if 0 54 | TODO 55 | *start = tl->lineInfo[line].startPos; 56 | *start = tl->u16tou8[*start]; 57 | *end = tl->lineInfo[line].endPos - tl->lineInfo[line].newlineCount; 58 | *end = tl->u16tou8[*end]; 59 | #endif 60 | } 61 | -------------------------------------------------------------------------------- /_abort/windowevents/page15.c: -------------------------------------------------------------------------------- 1 | static uiSpinbox *x, *y; 2 | 3 | static void moveX(uiSpinbox *s, void *data) 4 | { 5 | uiWindow *w = uiWindow(data); 6 | int xp, yp; 7 | 8 | uiWindowPosition(w, &xp, &yp); 9 | xp = uiSpinboxValue(x); 10 | uiWindowSetPosition(w, xp, yp); 11 | } 12 | 13 | static void moveY(uiSpinbox *s, void *data) 14 | { 15 | uiWindow *w = uiWindow(data); 16 | int xp, yp; 17 | 18 | uiWindowPosition(w, &xp, &yp); 19 | yp = uiSpinboxValue(y); 20 | uiWindowSetPosition(w, xp, yp); 21 | } 22 | 23 | static void updatepos(uiWindow *w) 24 | { 25 | int xp, yp; 26 | 27 | uiWindowPosition(w, &xp, &yp); 28 | uiSpinboxSetValue(x, xp); 29 | uiSpinboxSetValue(y, yp); 30 | } 31 | 32 | static void center(uiButton *b, void *data) 33 | { 34 | uiWindow *w = uiWindow(data); 35 | 36 | uiWindowCenter(w); 37 | updatepos(w); 38 | } 39 | 40 | void onMove(uiWindow *w, void *data) 41 | { 42 | printf("move\n"); 43 | updatepos(w); 44 | } 45 | 46 | uiBox *makePage15(uiWindow *w) 47 | { 48 | hbox = newHorizontalBox(); 49 | // TODO if I make this 1 and not add anything else AND not call uiWindowOnPositionChanged(), on OS X the box won't be able to grow vertically 50 | uiBoxAppend(page15, uiControl(hbox), 0); 51 | 52 | uiBoxAppend(hbox, uiControl(uiNewLabel("Position")), 0); 53 | x = uiNewSpinbox(INT_MIN, INT_MAX); 54 | uiBoxAppend(hbox, uiControl(x), 1); 55 | y = uiNewSpinbox(INT_MIN, INT_MAX); 56 | uiBoxAppend(hbox, uiControl(y), 1); 57 | button = uiNewButton("Center"); 58 | uiBoxAppend(hbox, uiControl(button), 0); 59 | 60 | uiSpinboxOnChanged(x, moveX, w); 61 | uiSpinboxOnChanged(y, moveY, w); 62 | uiButtonOnClicked(button, center, w); 63 | uiWindowOnPositionChanged(w, onMove, NULL); 64 | updatepos(w); 65 | } 66 | -------------------------------------------------------------------------------- /_doc/names.md: -------------------------------------------------------------------------------- 1 | TODO clean this up 2 | 3 | TODO note that you -fvisibility=hidden means nothing in static libraries, hence this (confirmed on OS X) 4 | 5 | In general, all names that begin with "ui" and are followed by a capital letter and all names htat begin with "uipriv" and are followed by a capita lletter are reserved by libui. This applies even in C++, where name mangling may affect the actual names in the object file. 6 | 7 | # Reserved names; for users 8 | 9 | All reserved names in libui are defined by a prefix followed by any uppercase letter in ASCII. The bullet lists before list those prefixes. 10 | 11 | Global-scope identifiers of any form (variables, constant names, functions, structure names, union names, C++ class names, enum type names, enum value names, C++ namespace names, GObject class and interface struct names, and Objective-C class and protocol name identifiers) and macro names: 12 | 13 | - `ui` 14 | - `uipriv` 15 | 16 | GObject and Objective-C class, interface, and protocol name strings, in the form they take in their respective runtime memory (e.g. when passed to `g_type_from_name()` and `NSClassFromString()`, respectively): 17 | 18 | - `uipriv` 19 | 20 | Objective-C method names: 21 | 22 | - `initWithUipriv` 23 | - `initWithFrame:uipriv` (TODO probably worth removing) 24 | - `uipriv` 25 | - `isUipriv` (for compatibility with KVO and `@property` statements) 26 | - `setUipriv` (for compatibility with KVO and `@property` statements) 27 | 28 | Objective-C ivar names: 29 | 30 | - `uipriv` 31 | - `_uipriv` (for compatibility with KVO and `@property` statements) 32 | 33 | Objective-C property names: 34 | 35 | - `uipriv` 36 | 37 | TODO GObject macros (in libui's source code), properties, and signals 38 | 39 | # Developer notes 40 | 41 | TODO 42 | -------------------------------------------------------------------------------- /windows/_rc2bin/main.cpp: -------------------------------------------------------------------------------- 1 | // 2 may 2018 2 | #include "winapi.hpp" 3 | #include 4 | #include 5 | #include "resources.hpp" 6 | 7 | // TODO make sure there are no CRs in the output 8 | 9 | void die(const char *f, const char *constname) 10 | { 11 | DWORD le; 12 | 13 | le = GetLastError(); 14 | fprintf(stderr, "error calling %s for %s: %I32d\n", f, constname, le); 15 | exit(1); 16 | } 17 | 18 | void dumpResource(const char *constname, const WCHAR *name, const WCHAR *type) 19 | { 20 | HRSRC hrsrc; 21 | HGLOBAL res; 22 | uint8_t *b, *bp; 23 | DWORD i, n; 24 | DWORD j; 25 | 26 | hrsrc = FindResourceW(NULL, name, type); 27 | if (hrsrc == NULL) 28 | die("FindResourceW()", constname); 29 | n = SizeofResource(NULL, hrsrc); 30 | if (n == 0) 31 | die("SizeofResource()", constname); 32 | res = LoadResource(NULL, hrsrc); 33 | if (res == NULL) 34 | die("LoadResource()", constname); 35 | b = (uint8_t *) LockResource(res); 36 | if (b == NULL) 37 | die("LockResource()", constname); 38 | 39 | printf("static const uint8_t %s[] = {\n", constname); 40 | bp = b; 41 | j = 0; 42 | for (i = 0; i < n; i++) { 43 | if (j == 0) 44 | printf("\t"); 45 | printf("0x%02I32X,", (uint32_t) (*bp)); 46 | bp++; 47 | if (j == 7) { 48 | printf("\n"); 49 | j = 0; 50 | } else { 51 | printf(" "); 52 | j++; 53 | } 54 | } 55 | if (j != 0) 56 | printf("\n"); 57 | printf("};\n"); 58 | printf("static_assert(ARRAYSIZE(%s) == %I32d, \"wrong size for resource %s\");\n", constname, n, constname); 59 | printf("\n"); 60 | } 61 | 62 | int main(void) 63 | { 64 | #define d(c, t) dumpResource(#c, MAKEINTRESOURCEW(c), t) 65 | d(rcTabPageDialog, RT_DIALOG); 66 | d(rcFontDialog, RT_DIALOG); 67 | d(rcColorDialog, RT_DIALOG); 68 | return 0; 69 | } 70 | -------------------------------------------------------------------------------- /_doc/export/writewidths.s: -------------------------------------------------------------------------------- 1 | # 22 october 2017 2 | # clang -o writewidths writewidths.c writewidths.s -g -Wall -Wextra -pedantic -g 3 | # thanks to: 4 | # - http://www.idryman.org/blog/2014/12/02/writing-64-bit-assembly-on-mac-os-x/ 5 | # - https://developer.apple.com/library/content/documentation/DeveloperTools/Reference/Assembler/060-i386_Addressing_Modes_and_Assembler_Instructions/i386_intructions.html#//apple_ref/doc/uid/TP30000825-TPXREF101 6 | # - https://stackoverflow.com/questions/46309041/trivial-macos-assembly-64-bit-program-has-incorrect-stack-alignment 7 | # - https://www.google.com/search?q=macos+implement+main+in+assembly+-nasm&oq=macos+implement+main+in+assembly+-nasm&gs_l=psy-ab.3...12877.13839.0.13988.6.6.0.0.0.0.117.407.4j1.5.0....0...1.1.64.psy-ab..1.0.0....0.et6MkokjvwA 8 | # - https://stackoverflow.com/questions/2529185/what-are-cfi-directives-in-gnu-assembler-gas-used-for 9 | 10 | .section __DATA,__data 11 | 12 | double10: 13 | .quad 0x4024000000000000 14 | doubleNeg05: 15 | .quad 0xbfe0000000000000 16 | 17 | fmt: 18 | .asciz "unregistered OS2 %ld:\tfloat64as(%g, 0x%016lx)\n" 19 | 20 | .section __TEXT,__text 21 | .globl _realMain 22 | _realMain: 23 | pushq %rbp 24 | movq %rsp, %rbp 25 | addq $8, %rsp 26 | 27 | xorq %rcx, %rcx 28 | loop: 29 | pushq %rcx 30 | # the code from core text 31 | movzwl %cx, %ecx 32 | xorps %xmm0, %xmm0 33 | cvtsi2sdl %ecx, %xmm0 34 | divsd double10(%rip), %xmm0 35 | addsd doubleNeg05(%rip), %xmm0 36 | # end core text code 37 | popq %rcx 38 | pushq %rcx 39 | movd %xmm0, %rdx 40 | movzwq %cx, %rsi 41 | leaq fmt(%rip), %rdi 42 | callq _printf 43 | popq %rcx 44 | incw %cx 45 | cmpw $10, %cx 46 | jbe loop 47 | 48 | xorq %rax, %rax 49 | subq $8, %rsp 50 | popq %rbp 51 | ret 52 | -------------------------------------------------------------------------------- /_wip/table/ui.h: -------------------------------------------------------------------------------- 1 | typedef struct uiTable uiTable; 2 | typedef struct uiTableModel uiTableModel; 3 | typedef struct uiTableModelSpec uiTableModelSpec; 4 | typedef struct uiTableColumnParams uiTableColumnParams; 5 | typedef enum uiTableColumnType uiTableColumnType; 6 | typedef enum uiTableNotification uiTableNotification; 7 | 8 | _UI_EXTERN uintmax_t uiTableType(void); 9 | #define uiTable(this) ((uiTable *) uiIsA((this), uiTableType(), 1)) 10 | _UI_EXTERN void uiTableSetModel(uiTable *t, uiTableModel *m); 11 | _UI_EXTERN void uiTableAppendColumn(uiTable *t, uiTableColumnParams *p); 12 | _UI_EXTERN uiTable *uiNewTable(void); 13 | 14 | enum uiTableColumnType { 15 | uiTableColumnText, 16 | //TODO uiTableColumnImage, 17 | uiTableColumnCheckbox, 18 | }; 19 | 20 | struct uiTableModelSpec { 21 | intmax_t (*NumRows)(uiTableModel *m, void *mData); 22 | void *(*CellValue)(uiTableModel *m, void *mData, intmax_t row, intmax_t column); 23 | void (*SetCellValue)(uiTableModel *m, void *mData, intmax_t row, intmax_t column, void *value); 24 | }; 25 | 26 | enum uiTableNotification { 27 | uiTableRowInserted, 28 | uiTableRowDeleted, 29 | uiTableCellChanged, 30 | }; 31 | 32 | _UI_EXTERN uiTableModel *uiNewTableModel(uintmax_t nCols, uiTableColumnType *types, uiTableModelSpec *spec, void *mData); 33 | _UI_EXTERN void uiFreeTableModel(uiTableModel *m); 34 | _UI_EXTERN void uiTableModelNotify(uiTableModel *m, uiTableNotification notification, intmax_t row, intmax_t column); 35 | 36 | #define uiTableModelFromBool(b) ((void *) ((intptr_t) (b))) 37 | _UI_EXTERN void *uiTableModelFromString(const char *str); 38 | 39 | struct uiTableColumnParams { 40 | const char *Name; 41 | // TODO make this unnecessary 42 | uiTableColumnType Type; 43 | int Mutable; // TODO move to the model? 44 | intmax_t ValueColumn; 45 | // TODO background color 46 | }; 47 | -------------------------------------------------------------------------------- /unix/combobox.c: -------------------------------------------------------------------------------- 1 | // 11 june 2015 2 | #include "uipriv_unix.h" 3 | 4 | struct uiCombobox { 5 | uiUnixControl c; 6 | GtkWidget *widget; 7 | GtkComboBox *combobox; 8 | GtkComboBoxText *comboboxText; 9 | void (*onSelected)(uiCombobox *, void *); 10 | void *onSelectedData; 11 | gulong onSelectedSignal; 12 | }; 13 | 14 | uiUnixControlAllDefaults(uiCombobox) 15 | 16 | static void onChanged(GtkComboBox *cbox, gpointer data) 17 | { 18 | uiCombobox *c = uiCombobox(data); 19 | 20 | (*(c->onSelected))(c, c->onSelectedData); 21 | } 22 | 23 | static void defaultOnSelected(uiCombobox *c, void *data) 24 | { 25 | // do nothing 26 | } 27 | 28 | void uiComboboxAppend(uiCombobox *c, const char *text) 29 | { 30 | gtk_combo_box_text_append(c->comboboxText, NULL, text); 31 | } 32 | 33 | int uiComboboxSelected(uiCombobox *c) 34 | { 35 | return gtk_combo_box_get_active(c->combobox); 36 | } 37 | 38 | void uiComboboxSetSelected(uiCombobox *c, int n) 39 | { 40 | // we need to inhibit sending of ::changed because this WILL send a ::changed otherwise 41 | g_signal_handler_block(c->combobox, c->onSelectedSignal); 42 | gtk_combo_box_set_active(c->combobox, n); 43 | g_signal_handler_unblock(c->combobox, c->onSelectedSignal); 44 | } 45 | 46 | void uiComboboxOnSelected(uiCombobox *c, void (*f)(uiCombobox *c, void *data), void *data) 47 | { 48 | c->onSelected = f; 49 | c->onSelectedData = data; 50 | } 51 | 52 | uiCombobox *uiNewCombobox(void) 53 | { 54 | uiCombobox *c; 55 | 56 | uiUnixNewControl(uiCombobox, c); 57 | 58 | c->widget = gtk_combo_box_text_new(); 59 | c->combobox = GTK_COMBO_BOX(c->widget); 60 | c->comboboxText = GTK_COMBO_BOX_TEXT(c->widget); 61 | 62 | c->onSelectedSignal = g_signal_connect(c->widget, "changed", G_CALLBACK(onChanged), c); 63 | uiComboboxOnSelected(c, defaultOnSelected, NULL); 64 | 65 | return c; 66 | } 67 | -------------------------------------------------------------------------------- /unix/slider.c: -------------------------------------------------------------------------------- 1 | // 11 june 2015 2 | #include "uipriv_unix.h" 3 | 4 | struct uiSlider { 5 | uiUnixControl c; 6 | GtkWidget *widget; 7 | GtkRange *range; 8 | GtkScale *scale; 9 | void (*onChanged)(uiSlider *, void *); 10 | void *onChangedData; 11 | gulong onChangedSignal; 12 | }; 13 | 14 | uiUnixControlAllDefaults(uiSlider) 15 | 16 | static void onChanged(GtkRange *range, gpointer data) 17 | { 18 | uiSlider *s = uiSlider(data); 19 | 20 | (*(s->onChanged))(s, s->onChangedData); 21 | } 22 | 23 | static void defaultOnChanged(uiSlider *s, void *data) 24 | { 25 | // do nothing 26 | } 27 | 28 | int uiSliderValue(uiSlider *s) 29 | { 30 | return gtk_range_get_value(s->range); 31 | } 32 | 33 | void uiSliderSetValue(uiSlider *s, int value) 34 | { 35 | // we need to inhibit sending of ::value-changed because this WILL send a ::value-changed otherwise 36 | g_signal_handler_block(s->range, s->onChangedSignal); 37 | gtk_range_set_value(s->range, value); 38 | g_signal_handler_unblock(s->range, s->onChangedSignal); 39 | } 40 | 41 | void uiSliderOnChanged(uiSlider *s, void (*f)(uiSlider *, void *), void *data) 42 | { 43 | s->onChanged = f; 44 | s->onChangedData = data; 45 | } 46 | 47 | uiSlider *uiNewSlider(int min, int max) 48 | { 49 | uiSlider *s; 50 | int temp; 51 | 52 | if (min >= max) { 53 | temp = min; 54 | min = max; 55 | max = temp; 56 | } 57 | 58 | uiUnixNewControl(uiSlider, s); 59 | 60 | s->widget = gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL, min, max, 1); 61 | s->range = GTK_RANGE(s->widget); 62 | s->scale = GTK_SCALE(s->widget); 63 | 64 | // ensure integers, just to be safe 65 | gtk_scale_set_digits(s->scale, 0); 66 | 67 | s->onChangedSignal = g_signal_connect(s->scale, "value-changed", G_CALLBACK(onChanged), s); 68 | uiSliderOnChanged(s, defaultOnChanged, NULL); 69 | 70 | return s; 71 | } 72 | -------------------------------------------------------------------------------- /stats.osxdrawtext: -------------------------------------------------------------------------------- 1 | diff --git a/darwin/drawtext.m b/darwin/drawtext.m 2 | index a84b68b..c95bbde 100644 3 | --- a/darwin/drawtext.m 4 | +++ b/darwin/drawtext.m 5 | @@ -108,7 +108,7 @@ static CFAttributedStringRef attrstrToCoreFoundation(uiAttributedString *s, uiDr 6 | boundsNoLeading = CTLineGetBoundsWithOptions(line, kCTLineBoundsExcludeTypographicLeading); 7 | 8 | // this is equivalent to boundsNoLeading.size.height + boundsNoLeading.origin.y (manually verified) 9 | - ascent = bounds.size.height + bounds.origin.y; 10 | +if(i!=5) ascent = bounds.size.height + bounds.origin.y; 11 | descent = -boundsNoLeading.origin.y; 12 | // TODO does this preserve leading sign? 13 | leading = -bounds.origin.y - descent; 14 | @@ -119,11 +119,20 @@ static CFAttributedStringRef attrstrToCoreFoundation(uiAttributedString *s, uiDr 15 | if (leading > 0) 16 | leading = floor(leading + 0.5); 17 | 18 | +NSLog(@"line %d", (int)i); 19 | +NSLog(@"ypos %g", ypos); 20 | +if (i>0) { 21 | +NSLog(@"expected Y: %g", metrics[i - 1].Y - metrics[i - 1].Height); 22 | +} 23 | + 24 | metrics[i].X = origins[i].x; 25 | metrics[i].Y = origins[i].y - descent - leading; 26 | metrics[i].Width = bounds.size.width; 27 | metrics[i].Height = ascent + descent + leading; 28 | 29 | +NSLog(@"o %g a %g d %g l %g", origins[i].y, ascent, descent, leading); 30 | +NSLog(@"actual Y: %g height: %g", metrics[i].Y, metrics[i].Height); 31 | + 32 | metrics[i].BaselineY = origins[i].y; 33 | metrics[i].Ascent = ascent; 34 | metrics[i].Descent = descent; 35 | @@ -148,7 +157,7 @@ static CFAttributedStringRef attrstrToCoreFoundation(uiAttributedString *s, uiDr 36 | metrics[i].BaselineY = size.height - metrics[i].BaselineY; 37 | // TODO also adjust by metrics[i].Height? 38 | } 39 | - 40 | +NSLog(@"==="); 41 | uiFree(origins); 42 | return metrics; 43 | } 44 | -------------------------------------------------------------------------------- /windows/winpublic.cpp: -------------------------------------------------------------------------------- 1 | // 6 april 2015 2 | #include "uipriv_windows.hpp" 3 | 4 | void uiWindowsEnsureDestroyWindow(HWND hwnd) 5 | { 6 | if (DestroyWindow(hwnd) == 0) 7 | logLastError(L"error destroying window"); 8 | } 9 | 10 | void uiWindowsEnsureSetParentHWND(HWND hwnd, HWND parent) 11 | { 12 | if (parent == NULL) 13 | parent = utilWindow; 14 | if (SetParent(hwnd, parent) == 0) 15 | logLastError(L"error setting window parent"); 16 | } 17 | 18 | void uiWindowsEnsureAssignControlIDZOrder(HWND hwnd, LONG_PTR *controlID, HWND *insertAfter) 19 | { 20 | SetWindowLongPtrW(hwnd, GWLP_ID, *controlID); 21 | (*controlID)++; 22 | setWindowInsertAfter(hwnd, *insertAfter); 23 | *insertAfter = hwnd; 24 | } 25 | 26 | void uiWindowsEnsureMoveWindowDuringResize(HWND hwnd, int x, int y, int width, int height) 27 | { 28 | RECT r; 29 | 30 | r.left = x; 31 | r.top = y; 32 | r.right = x + width; 33 | r.bottom = y + height; 34 | if (SetWindowPos(hwnd, NULL, r.left, r.top, r.right - r.left, r.bottom - r.top, SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER) == 0) 35 | logLastError(L"error moving window"); 36 | } 37 | 38 | // do these function even error out in any case other than invalid parameters?! I thought all windows had rects 39 | void uiWindowsEnsureGetClientRect(HWND hwnd, RECT *r) 40 | { 41 | if (GetClientRect(hwnd, r) == 0) { 42 | logLastError(L"error getting window client rect"); 43 | // zero out the rect on error just to be safe 44 | r->left = 0; 45 | r->top = 0; 46 | r->right = 0; 47 | r->bottom = 0; 48 | } 49 | } 50 | 51 | void uiWindowsEnsureGetWindowRect(HWND hwnd, RECT *r) 52 | { 53 | if (GetWindowRect(hwnd, r) == 0) { 54 | logLastError(L"error getting window rect"); 55 | // zero out the rect on error just to be safe 56 | r->left = 0; 57 | r->top = 0; 58 | r->right = 0; 59 | r->bottom = 0; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /unix/graphemes.c: -------------------------------------------------------------------------------- 1 | // 25 may 2016 2 | #include "uipriv_unix.h" 3 | #include "attrstr.h" 4 | 5 | int uiprivGraphemesTakesUTF16(void) 6 | { 7 | return 0; 8 | } 9 | 10 | uiprivGraphemes *uiprivNewGraphemes(void *s, size_t len) 11 | { 12 | uiprivGraphemes *g; 13 | char *text = (char *) s; 14 | size_t lenchars; 15 | PangoLogAttr *logattrs; 16 | size_t i; 17 | size_t *op; 18 | 19 | g = uiprivNew(uiprivGraphemes); 20 | 21 | // TODO see if we can use the utf routines 22 | lenchars = g_utf8_strlen(text, -1); 23 | logattrs = (PangoLogAttr *) uiprivAlloc((lenchars + 1) * sizeof (PangoLogAttr), "PangoLogAttr[] (graphemes)"); 24 | pango_get_log_attrs(text, len, 25 | -1, NULL, 26 | logattrs, lenchars + 1); 27 | 28 | // first figure out how many graphemes there are 29 | g->len = 0; 30 | for (i = 0; i < lenchars; i++) 31 | if (logattrs[i].is_cursor_position != 0) 32 | g->len++; 33 | 34 | g->pointsToGraphemes = (size_t *) uiprivAlloc((len + 1) * sizeof (size_t), "size_t[] (graphemes)"); 35 | g->graphemesToPoints = (size_t *) uiprivAlloc((g->len + 1) * sizeof (size_t), "size_t[] (graphemes)"); 36 | 37 | // compute the graphemesToPoints array 38 | // TODO merge with the next for loop somehow? 39 | op = g->graphemesToPoints; 40 | for (i = 0; i < lenchars; i++) 41 | if (logattrs[i].is_cursor_position != 0) 42 | // TODO optimize this 43 | *op++ = g_utf8_offset_to_pointer(text, i) - text; 44 | // and do the last one 45 | *op++ = len; 46 | 47 | // and finally build the pointsToGraphemes array 48 | op = g->pointsToGraphemes; 49 | for (i = 0; i < g->len; i++) { 50 | size_t j; 51 | size_t first, last; 52 | 53 | first = g->graphemesToPoints[i]; 54 | last = g->graphemesToPoints[i + 1]; 55 | for (j = first; j < last; j++) 56 | *op++ = i; 57 | } 58 | // and do the last one 59 | *op++ = i; 60 | 61 | uiprivFree(logattrs); 62 | return g; 63 | } 64 | -------------------------------------------------------------------------------- /windows/separator.cpp: -------------------------------------------------------------------------------- 1 | // 20 may 2015 2 | #include "uipriv_windows.hpp" 3 | 4 | // TODO 5 | // - font scaling issues? https://www.viksoe.dk/code/bevelline.htm 6 | // - isn't something in vista app guidelines suggesting this too? or some other microsoft doc? and what about VS itself? 7 | 8 | // references: 9 | // - http://stackoverflow.com/questions/2892703/how-do-i-draw-separators 10 | // - https://msdn.microsoft.com/en-us/library/windows/desktop/dn742405%28v=vs.85%29.aspx 11 | 12 | struct uiSeparator { 13 | uiWindowsControl c; 14 | HWND hwnd; 15 | BOOL vertical; 16 | }; 17 | 18 | uiWindowsControlAllDefaults(uiSeparator) 19 | 20 | // via https://msdn.microsoft.com/en-us/library/windows/desktop/bb226818%28v=vs.85%29.aspx 21 | #define separatorHeight 1 22 | 23 | // TODO 24 | #define separatorWidth 1 25 | 26 | static void uiSeparatorMinimumSize(uiWindowsControl *c, int *width, int *height) 27 | { 28 | uiSeparator *s = uiSeparator(c); 29 | uiWindowsSizing sizing; 30 | int x, y; 31 | 32 | *width = 1; // TODO 33 | *height = 1; 34 | x = separatorWidth; 35 | y = separatorHeight; 36 | uiWindowsGetSizing(s->hwnd, &sizing); 37 | uiWindowsSizingDlgUnitsToPixels(&sizing, &x, &y); 38 | if (s->vertical) 39 | *width = x; 40 | else 41 | *height = y; 42 | } 43 | 44 | uiSeparator *uiNewHorizontalSeparator(void) 45 | { 46 | uiSeparator *s; 47 | 48 | uiWindowsNewControl(uiSeparator, s); 49 | 50 | s->hwnd = uiWindowsEnsureCreateControlHWND(0, 51 | L"static", L"", 52 | SS_ETCHEDHORZ, 53 | hInstance, NULL, 54 | TRUE); 55 | 56 | return s; 57 | } 58 | 59 | uiSeparator *uiNewVerticalSeparator(void) 60 | { 61 | uiSeparator *s; 62 | 63 | uiWindowsNewControl(uiSeparator, s); 64 | 65 | s->hwnd = uiWindowsEnsureCreateControlHWND(0, 66 | L"static", L"", 67 | SS_ETCHEDHORZ, 68 | hInstance, NULL, 69 | TRUE); 70 | s->vertical = TRUE; 71 | 72 | return s; 73 | } 74 | -------------------------------------------------------------------------------- /_notes/macosAlternateHiDPI: -------------------------------------------------------------------------------- 1 | https://developer.apple.com/documentation/corefoundation/1542764-cfurlcopyresourcepropertyforkey?language=objc 2 | https://developer.apple.com/documentation/foundation/nsargumentdomain?language=objc 3 | https://developer.apple.com/documentation/appkit/1428499-nsapplicationmain 4 | https://webkit.googlesource.com/WebKit/+/9ae3deefb7df48bd85f01edcf8382ee300eafbd4%5E!/ 5 | https://stackoverflow.com/questions/11181324/how-to-change-retina-display-system-preferences-in-osx 6 | https://web.archive.org/web/20150828053709/http://garethjenkins.com/2012/07/01/investigating-a-high-resolution-retina-utility-for-macbook-pro-1x-and-2x-modes/ 7 | https://github.com/avibrazil/RDM 8 | https://www.google.com/search?client=firefox-b-1-d&q=IOFramebuffer+subclass 9 | https://developer.apple.com/documentation/kernel/ioframebuffer?language=objc 10 | https://stackoverflow.com/questions/51846999/how-to-write-macos-display-driver 11 | https://twitter.com/kenkeiter/status/3631378994298882 12 | http://en.ennowelbers.info/node/33 13 | https://www.insanelymac.com/forum/topic/114528-how-to-compile-a-driver-from-source/ 14 | https://github.com/mkernel/EWProxyFramebuffer 15 | https://stackoverflow.com/questions/46904493/ioframebuffer-cant-access-vram-framebuffer-in-macos-10-13 16 | https://www.google.com/search?client=firefox-b-1-d&q=IOFramebuffer+10.13 17 | https://github.com/codykrieger/gfxCardStatus/issues/296 18 | https://plugable.com/2018/03/30/macos-10-13-4-disables-displaylink-duet-display-devices/ 19 | https://www.tekrevue.com/tip/hidpi-mode-os-x/ 20 | https://medium.com/@ivan.ha/how-to-mimic-a-2k-monitor-as-retina-display-in-macos-sierra-using-hidpi-f53d87630c48 21 | https://www.google.com/search?client=firefox-b-1-d&q=IOFramebuffer+10.13 22 | https://www.quora.com/What-is-the-underlying-reason-if-DisplayLink-is-no-longer-working-properly-on-Mac-OS 23 | https://github.com/Siguza/iokit-utils 24 | -------------------------------------------------------------------------------- /_wip/table/test_page9.c: -------------------------------------------------------------------------------- 1 | // 18 october 2015 2 | #include "test.h" 3 | 4 | // TODO manage the memory of the uiTableModel 5 | 6 | static intmax_t nColumns = 4; 7 | static uiTableColumnType coltypes[] = { 8 | uiTableColumnText, 9 | uiTableColumnText, 10 | uiTableColumnCheckbox, 11 | uiTableColumnCheckbox, 12 | }; 13 | 14 | static intmax_t nRows = 6; 15 | 16 | static intmax_t modelNumRows(uiTableModel *m, void *mData) 17 | { 18 | return nRows; 19 | } 20 | 21 | void *modelCellValue(uiTableModel *m, void *mData, intmax_t row, intmax_t column) 22 | { 23 | char line[20]; 24 | 25 | line[0] = 'R'; 26 | line[1] = 'o'; 27 | line[2] = 'w'; 28 | line[3] = ' '; 29 | line[4] = row + '0'; 30 | line[5] = '\0'; 31 | switch (column) { 32 | case 0: 33 | case 1: 34 | return uiTableModelFromString(line); 35 | case 2: 36 | return uiTableModelFromBool(row % 2 == 0); 37 | case 3: 38 | return uiTableModelFromBool(row % 3 == 0); 39 | } 40 | // TODO 41 | return NULL; 42 | } 43 | 44 | // TODO make this not need to be static 45 | uiTableModelSpec spec; 46 | 47 | void modelSetCellValue(uiTableModel *m, void *mData, intmax_t row, intmax_t column, void *value) 48 | { 49 | // TODO 50 | } 51 | 52 | uiBox *makePage9(void) 53 | { 54 | uiBox *page9; 55 | uiTable *table; 56 | uiTableModel *model; 57 | uiTableColumnParams p; 58 | intmax_t i; 59 | 60 | page9 = newVerticalBox(); 61 | 62 | table = uiNewTable(); 63 | uiBoxAppend(page9, uiControl(table), 1); 64 | 65 | spec.NumRows = modelNumRows; 66 | spec.CellValue = modelCellValue; 67 | spec.SetCellValue = modelSetCellValue; 68 | model = uiNewTableModel(nColumns, coltypes, &spec, NULL); 69 | uiTableSetModel(table, model); 70 | 71 | for (i = 0; i < nColumns; i++) { 72 | p.Name = "Column"; 73 | p.Type = coltypes[i]; 74 | p.Mutable = i % 2 == 1; 75 | p.ValueColumn = i; 76 | uiTableAppendColumn(table, &p); 77 | } 78 | 79 | return page9; 80 | } 81 | -------------------------------------------------------------------------------- /unix/spinbox.c: -------------------------------------------------------------------------------- 1 | // 11 june 2015 2 | #include "uipriv_unix.h" 3 | 4 | struct uiSpinbox { 5 | uiUnixControl c; 6 | GtkWidget *widget; 7 | GtkEntry *entry; 8 | GtkSpinButton *spinButton; 9 | void (*onChanged)(uiSpinbox *, void *); 10 | void *onChangedData; 11 | gulong onChangedSignal; 12 | }; 13 | 14 | uiUnixControlAllDefaults(uiSpinbox) 15 | 16 | static void onChanged(GtkSpinButton *sb, gpointer data) 17 | { 18 | uiSpinbox *s = uiSpinbox(data); 19 | 20 | (*(s->onChanged))(s, s->onChangedData); 21 | } 22 | 23 | static void defaultOnChanged(uiSpinbox *s, void *data) 24 | { 25 | // do nothing 26 | } 27 | 28 | int uiSpinboxValue(uiSpinbox *s) 29 | { 30 | return gtk_spin_button_get_value(s->spinButton); 31 | } 32 | 33 | void uiSpinboxSetValue(uiSpinbox *s, int value) 34 | { 35 | // we need to inhibit sending of ::value-changed because this WILL send a ::value-changed otherwise 36 | g_signal_handler_block(s->spinButton, s->onChangedSignal); 37 | // this clamps for us 38 | gtk_spin_button_set_value(s->spinButton, (gdouble) value); 39 | g_signal_handler_unblock(s->spinButton, s->onChangedSignal); 40 | } 41 | 42 | void uiSpinboxOnChanged(uiSpinbox *s, void (*f)(uiSpinbox *, void *), void *data) 43 | { 44 | s->onChanged = f; 45 | s->onChangedData = data; 46 | } 47 | 48 | uiSpinbox *uiNewSpinbox(int min, int max) 49 | { 50 | uiSpinbox *s; 51 | int temp; 52 | 53 | if (min >= max) { 54 | temp = min; 55 | min = max; 56 | max = temp; 57 | } 58 | 59 | uiUnixNewControl(uiSpinbox, s); 60 | 61 | s->widget = gtk_spin_button_new_with_range(min, max, 1); 62 | s->entry = GTK_ENTRY(s->widget); 63 | s->spinButton = GTK_SPIN_BUTTON(s->widget); 64 | 65 | // ensure integers, just to be safe 66 | gtk_spin_button_set_digits(s->spinButton, 0); 67 | 68 | s->onChangedSignal = g_signal_connect(s->spinButton, "value-changed", G_CALLBACK(onChanged), s); 69 | uiSpinboxOnChanged(s, defaultOnChanged, NULL); 70 | 71 | return s; 72 | } 73 | -------------------------------------------------------------------------------- /windows/_rc2bin/winapi.hpp: -------------------------------------------------------------------------------- 1 | // 31 may 2015 2 | #define UNICODE 3 | #define _UNICODE 4 | #define STRICT 5 | #define STRICT_TYPED_ITEMIDS 6 | 7 | // see https://github.com/golang/go/issues/9916#issuecomment-74812211 8 | // TODO get rid of this 9 | #define INITGUID 10 | 11 | // for the manifest 12 | #ifndef _UI_STATIC 13 | #define ISOLATION_AWARE_ENABLED 1 14 | #endif 15 | 16 | // get Windows version right; right now Windows Vista 17 | // unless otherwise stated, all values from Microsoft's sdkddkver.h 18 | // TODO is all of this necessary? how is NTDDI_VERSION used? 19 | // TODO platform update sp2 20 | #define WINVER 0x0600 /* from Microsoft's winnls.h */ 21 | #define _WIN32_WINNT 0x0600 22 | #define _WIN32_WINDOWS 0x0600 /* from Microsoft's pdh.h */ 23 | #define _WIN32_IE 0x0700 24 | #define NTDDI_VERSION 0x06000000 25 | 26 | // The MinGW-w64 header has an unverified IDWriteTypography definition. 27 | // TODO I can confirm this myself, but I don't know how long it will take for them to note my adjustments... Either way, I have to confirm this myself. 28 | // TODO change the check from _MSC_VER to a MinGW-w64-specific check 29 | // TODO keep track of what else is guarded by this 30 | #ifndef _MSC_VER 31 | #define __MINGW_USE_BROKEN_INTERFACE 32 | #endif 33 | 34 | #include 35 | 36 | // Microsoft's resource compiler will segfault if we feed it headers it was not designed to handle 37 | #ifndef RC_INVOKED 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include 45 | 46 | #include 47 | #include 48 | #include 49 | #include 50 | #include 51 | #include 52 | #include 53 | #include 54 | 55 | #include 56 | #include 57 | #include 58 | #include 59 | #include 60 | #endif 61 | -------------------------------------------------------------------------------- /examples/meson.build: -------------------------------------------------------------------------------- 1 | # 24 march 2019 2 | 3 | libui_example_sources = [] 4 | libui_example_link_args = [] 5 | libui_example_cpp_extra_args = [] 6 | if libui_OS == 'windows' 7 | libui_example_manifest = 'example.manifest' 8 | if libui_mode == 'static' 9 | libui_example_manifest = 'example.static.manifest' 10 | endif 11 | libui_example_sources += [ 12 | windows.compile_resources('resources.rc', 13 | args: libui_manifest_args, 14 | depend_files: [libui_example_manifest]), 15 | ] 16 | # because Microsoft's toolchain is dumb 17 | if libui_MSVC 18 | libui_example_link_args += ['/ENTRY:mainCRTStartup'] 19 | endif 20 | elif libui_OS == 'darwin' 21 | # since we use a deployment target of 10.8, the non-C++11-compliant libstdc++ is chosen by default; we need C++11 22 | # see issue #302 for more details 23 | libui_example_cpp_extra_args += ['--stdlib=libc++'] 24 | endif 25 | 26 | libui_examples = { 27 | 'controlgallery': { 28 | 'sources': ['controlgallery/main.c'], 29 | }, 30 | 'histogram': { 31 | 'sources': ['histogram/main.c'], 32 | }, 33 | 'cpp-multithread': { 34 | 'sources': ['cpp-multithread/main.cpp'], 35 | 'deps': [ 36 | dependency('threads', 37 | required: true), 38 | ], 39 | 'cpp_args': libui_example_cpp_extra_args, 40 | 'link_args': libui_example_cpp_extra_args, 41 | }, 42 | 'drawtext': { 43 | 'sources': ['drawtext/main.c'], 44 | }, 45 | 'timer': { 46 | 'sources': ['timer/main.c'], 47 | }, 48 | 'datetime': { 49 | 'sources': ['datetime/main.c'], 50 | }, 51 | } 52 | foreach name, args : libui_examples 53 | # TODO once we upgrade to 0.49.0, add pie: true 54 | executable(name, args['sources'] + libui_example_sources, 55 | dependencies: args.get('deps', []) + libui_binary_deps, 56 | link_with: libui_libui, 57 | cpp_args: args.get('cpp_args', []), 58 | link_args: args.get('link_args', []) + libui_example_link_args, 59 | gui_app: false, 60 | install: false) 61 | endforeach 62 | -------------------------------------------------------------------------------- /unix/progressbar.c: -------------------------------------------------------------------------------- 1 | // 11 june 2015 2 | #include "uipriv_unix.h" 3 | 4 | // LONGTERM: 5 | // - in GTK+ 3.22 at least, running both a GtkProgressBar and a GtkCellRendererProgress in pulse mode with our code will cause the former to slow down and eventually stop, and I can't tell why at all 6 | 7 | struct uiProgressBar { 8 | uiUnixControl c; 9 | GtkWidget *widget; 10 | GtkProgressBar *pbar; 11 | gboolean indeterminate; 12 | guint pulser; 13 | }; 14 | 15 | uiUnixControlAllDefaultsExceptDestroy(uiProgressBar) 16 | 17 | static void uiProgressBarDestroy(uiControl *c) 18 | { 19 | uiProgressBar *p = uiProgressBar(c); 20 | 21 | // be sure to stop the timeout now 22 | if (p->indeterminate) 23 | g_source_remove(p->pulser); 24 | g_object_unref(p->widget); 25 | uiFreeControl(uiControl(p)); 26 | } 27 | 28 | int uiProgressBarValue(uiProgressBar *p) 29 | { 30 | if (p->indeterminate) 31 | return -1; 32 | return (int) (gtk_progress_bar_get_fraction(p->pbar) * 100); 33 | } 34 | 35 | static gboolean pulse(void* data) 36 | { 37 | uiProgressBar *p = uiProgressBar(data); 38 | 39 | gtk_progress_bar_pulse(p->pbar); 40 | return TRUE; 41 | } 42 | 43 | void uiProgressBarSetValue(uiProgressBar *p, int value) 44 | { 45 | if (value == -1) { 46 | if (!p->indeterminate) { 47 | p->indeterminate = TRUE; 48 | // TODO verify the timeout 49 | p->pulser = g_timeout_add(100, pulse, p); 50 | } 51 | return; 52 | } 53 | if (p->indeterminate) { 54 | p->indeterminate = FALSE; 55 | g_source_remove(p->pulser); 56 | } 57 | 58 | if (value < 0 || value > 100) 59 | uiprivUserBug("Value %d is out of range for a uiProgressBar.", value); 60 | 61 | gtk_progress_bar_set_fraction(p->pbar, ((gdouble) value) / 100); 62 | } 63 | 64 | uiProgressBar *uiNewProgressBar(void) 65 | { 66 | uiProgressBar *p; 67 | 68 | uiUnixNewControl(uiProgressBar, p); 69 | 70 | p->widget = gtk_progress_bar_new(); 71 | p->pbar = GTK_PROGRESS_BAR(p->widget); 72 | 73 | return p; 74 | } 75 | -------------------------------------------------------------------------------- /_wip/sv/sourcelist: -------------------------------------------------------------------------------- 1 | 2016-05-26 22:43:58.600 svtest[82237:548359] backgroundColor (null) 2 | 2016-05-26 22:43:58.600 svtest[82237:548359] drawsBackground 0 3 | 2016-05-26 22:43:58.600 svtest[82237:548359] borderType 2 4 | 2016-05-26 22:43:58.600 svtest[82237:548359] documentCursor (null) 5 | 2016-05-26 22:43:58.600 svtest[82237:548359] hasHorizontalScroller 1 6 | 2016-05-26 22:43:58.600 svtest[82237:548359] hasVerticalScroller 1 7 | 2016-05-26 22:43:58.600 svtest[82237:548359] autohidesScrollers 1 8 | 2016-05-26 22:43:58.600 svtest[82237:548359] hasHorizontalRuler 0 9 | 2016-05-26 22:43:58.600 svtest[82237:548359] hasVerticalRuler 0 10 | 2016-05-26 22:43:58.600 svtest[82237:548359] rulersVisible 0 11 | 2016-05-26 22:43:58.601 svtest[82237:548359] 10.10 autoAdjContentInsets 1 12 | 2016-05-26 22:43:58.601 svtest[82237:548359] scrollerKnobStyle 0 13 | 2016-05-26 22:43:58.601 svtest[82237:548359] scrollerStyle 1 14 | 2016-05-26 22:43:58.601 svtest[82237:548359] horizontalLineScroll 19 15 | 2016-05-26 22:43:58.601 svtest[82237:548359] verticalLineScroll 19 16 | 2016-05-26 22:43:58.645 svtest[82237:548359] horizontalPageScroll 10 17 | 2016-05-26 22:43:58.645 svtest[82237:548359] verticalPageScroll 10 18 | 2016-05-26 22:43:58.645 svtest[82237:548359] scrollsDynamically 1 19 | 2016-05-26 22:43:58.645 svtest[82237:548359] findBarPosition 1 20 | 2016-05-26 22:43:58.645 svtest[82237:548359] usesPredomAxisScroll 0 21 | 2016-05-26 22:43:58.645 svtest[82237:548359] horizontalElasticity 0 22 | 2016-05-26 22:43:58.646 svtest[82237:548359] verticalElasticity 0 23 | 2016-05-26 22:43:58.646 svtest[82237:548359] 10.8 allowsMagnification 0 24 | 2016-05-26 22:43:58.646 svtest[82237:548359] 10.8 maxMagnification 4 25 | 2016-05-26 22:43:58.646 svtest[82237:548359] 10.8 minMagnification 0.25 26 | -------------------------------------------------------------------------------- /test/page7b.c: -------------------------------------------------------------------------------- 1 | // 13 october 2015 2 | #include "test.h" 3 | 4 | static uiArea *area; 5 | static uiCheckbox *label; 6 | 7 | struct handler { 8 | uiAreaHandler ah; 9 | }; 10 | 11 | static struct handler handler; 12 | 13 | static void handlerDraw(uiAreaHandler *a, uiArea *area, uiAreaDrawParams *p) 14 | { 15 | // do nothing 16 | } 17 | 18 | static void handlerMouseEvent(uiAreaHandler *a, uiArea *area, uiAreaMouseEvent *e) 19 | { 20 | char pos[128]; 21 | 22 | // wonderful, vanilla snprintf() isn't in visual studio 2013 - http://blogs.msdn.com/b/vcblog/archive/2013/07/19/c99-library-support-in-visual-studio-2013.aspx 23 | // we can't use _snprintf() in the test suite because that's msvc-only, so oops. sprintf() it is. 24 | sprintf(pos, "X %g Y %g", e->X, e->Y); 25 | uiCheckboxSetText(label, pos); 26 | } 27 | 28 | static void handlerMouseCrossed(uiAreaHandler *ah, uiArea *a, int left) 29 | { 30 | printf("%d %d\n", left, !left); 31 | uiCheckboxSetChecked(label, !left); 32 | } 33 | 34 | static void handlerDragBroken(uiAreaHandler *ah, uiArea *a) 35 | { 36 | // do nothing 37 | } 38 | 39 | static int handlerKeyEvent(uiAreaHandler *ah, uiArea *a, uiAreaKeyEvent *e) 40 | { 41 | if (e->Key == 'h' && !e->Up) { 42 | // TODO hide the widget momentarily on the h key 43 | return 1; 44 | } 45 | return 0; 46 | } 47 | 48 | uiGroup *makePage7b(void) 49 | { 50 | uiGroup *group; 51 | uiBox *box; 52 | 53 | handler.ah.Draw = handlerDraw; 54 | handler.ah.MouseEvent = handlerMouseEvent; 55 | handler.ah.MouseCrossed = handlerMouseCrossed; 56 | handler.ah.DragBroken = handlerDragBroken; 57 | handler.ah.KeyEvent = handlerKeyEvent; 58 | 59 | group = newGroup("Scrolling Mouse Test"); 60 | 61 | box = newVerticalBox(); 62 | uiGroupSetChild(group, uiControl(box)); 63 | 64 | area = uiNewScrollingArea((uiAreaHandler *) (&handler), 5000, 5000); 65 | uiBoxAppend(box, uiControl(area), 1); 66 | 67 | label = uiNewCheckbox(""); 68 | uiBoxAppend(box, uiControl(label), 0); 69 | 70 | return group; 71 | } 72 | -------------------------------------------------------------------------------- /_wip/sv/normal: -------------------------------------------------------------------------------- 1 | 2016-05-26 22:38:12.877 svtest[81790:544681] backgroundColor NSNamedColorSpace System controlColor 2 | 2016-05-26 22:38:12.877 svtest[81790:544681] drawsBackground 1 3 | 2016-05-26 22:38:12.877 svtest[81790:544681] borderType 2 4 | 2016-05-26 22:38:12.877 svtest[81790:544681] documentCursor (null) 5 | 2016-05-26 22:38:12.877 svtest[81790:544681] hasHorizontalScroller 1 6 | 2016-05-26 22:38:12.877 svtest[81790:544681] hasVerticalScroller 1 7 | 2016-05-26 22:38:12.877 svtest[81790:544681] autohidesScrollers 0 8 | 2016-05-26 22:38:12.877 svtest[81790:544681] hasHorizontalRuler 0 9 | 2016-05-26 22:38:12.878 svtest[81790:544681] hasVerticalRuler 0 10 | 2016-05-26 22:38:12.878 svtest[81790:544681] rulersVisible 0 11 | 2016-05-26 22:38:12.878 svtest[81790:544681] 10.10 autoAdjContentInsets 1 12 | 2016-05-26 22:38:12.878 svtest[81790:544681] scrollerKnobStyle 0 13 | 2016-05-26 22:38:12.878 svtest[81790:544681] scrollerStyle 1 14 | 2016-05-26 22:38:12.878 svtest[81790:544681] horizontalLineScroll 10 15 | 2016-05-26 22:38:12.878 svtest[81790:544681] verticalLineScroll 10 16 | 2016-05-26 22:38:12.886 svtest[81790:544681] horizontalPageScroll 10 17 | 2016-05-26 22:38:12.886 svtest[81790:544681] verticalPageScroll 10 18 | 2016-05-26 22:38:12.886 svtest[81790:544681] scrollsDynamically 1 19 | 2016-05-26 22:38:12.886 svtest[81790:544681] findBarPosition 1 20 | 2016-05-26 22:38:12.886 svtest[81790:544681] usesPredomAxisScroll 0 21 | 2016-05-26 22:38:12.886 svtest[81790:544681] horizontalElasticity 0 22 | 2016-05-26 22:38:12.886 svtest[81790:544681] verticalElasticity 0 23 | 2016-05-26 22:38:12.887 svtest[81790:544681] 10.8 allowsMagnification 0 24 | 2016-05-26 22:38:12.887 svtest[81790:544681] 10.8 maxMagnification 4 25 | 2016-05-26 22:38:12.887 svtest[81790:544681] 10.8 minMagnification 0.25 26 | -------------------------------------------------------------------------------- /test/page3.c: -------------------------------------------------------------------------------- 1 | // 7 may 2015 2 | #include "test.h" 3 | 4 | static uiBox *makeSet(int omit, int hidden, int stretch) 5 | { 6 | uiBox *hbox; 7 | uiButton *buttons[4]; 8 | 9 | // don't use newHorizontalBox() 10 | // the point of this test is to test hidden controls and padded 11 | hbox = (*newhbox)(); 12 | uiBoxSetPadded(hbox, 1); 13 | if (omit != 0) { 14 | buttons[0] = uiNewButton("First"); 15 | uiBoxAppend(hbox, uiControl(buttons[0]), stretch); 16 | } 17 | if (omit != 1) { 18 | buttons[1] = uiNewButton("Second"); 19 | uiBoxAppend(hbox, uiControl(buttons[1]), stretch); 20 | } 21 | if (omit != 2) { 22 | buttons[2] = uiNewButton("Third"); 23 | uiBoxAppend(hbox, uiControl(buttons[2]), stretch); 24 | } 25 | if (omit != 3) { 26 | buttons[3] = uiNewButton("Fourth"); 27 | uiBoxAppend(hbox, uiControl(buttons[3]), stretch); 28 | } 29 | if (hidden != -1) 30 | uiControlHide(uiControl(buttons[hidden])); 31 | return hbox; 32 | } 33 | 34 | uiBox *makePage3(void) 35 | { 36 | uiBox *page3; 37 | uiBox *hbox; 38 | uiBox *hbox2; 39 | uiBox *vbox; 40 | int hidden; 41 | 42 | page3 = newVerticalBox(); 43 | 44 | // first the non-stretchy type 45 | for (hidden = 0; hidden < 4; hidden++) { 46 | // these two must stay unpadded as well, otherwise the test isn't meaningful 47 | hbox2 = (*newhbox)(); 48 | vbox = (*newvbox)(); 49 | // reference set 50 | hbox = makeSet(hidden, -1, 0); 51 | uiBoxAppend(vbox, uiControl(hbox), 0); 52 | // real thing 53 | hbox = makeSet(-1, hidden, 0); 54 | uiBoxAppend(vbox, uiControl(hbox), 0); 55 | // pack vbox in 56 | uiBoxAppend(hbox2, uiControl(vbox), 0); 57 | // and have a button in there for showing right margins 58 | uiBoxAppend(hbox2, uiControl(uiNewButton("Right Margin Test")), 1); 59 | uiBoxAppend(page3, uiControl(hbox2), 0); 60 | } 61 | 62 | // then the stretchy type 63 | for (hidden = 0; hidden < 4; hidden++) { 64 | hbox = makeSet(-1, hidden, 1); 65 | uiBoxAppend(page3, uiControl(hbox), 0); 66 | } 67 | 68 | return page3; 69 | } 70 | -------------------------------------------------------------------------------- /_wip/sv/outlineview: -------------------------------------------------------------------------------- 1 | 2016-05-26 22:42:16.208 svtest[82103:547159] backgroundColor NSNamedColorSpace System controlBackgroundColor 2 | 2016-05-26 22:42:16.208 svtest[82103:547159] drawsBackground 1 3 | 2016-05-26 22:42:16.208 svtest[82103:547159] borderType 2 4 | 2016-05-26 22:42:16.208 svtest[82103:547159] documentCursor (null) 5 | 2016-05-26 22:42:16.209 svtest[82103:547159] hasHorizontalScroller 1 6 | 2016-05-26 22:42:16.209 svtest[82103:547159] hasVerticalScroller 1 7 | 2016-05-26 22:42:16.209 svtest[82103:547159] autohidesScrollers 1 8 | 2016-05-26 22:42:16.209 svtest[82103:547159] hasHorizontalRuler 0 9 | 2016-05-26 22:42:16.209 svtest[82103:547159] hasVerticalRuler 0 10 | 2016-05-26 22:42:16.209 svtest[82103:547159] rulersVisible 0 11 | 2016-05-26 22:42:16.209 svtest[82103:547159] 10.10 autoAdjContentInsets 1 12 | 2016-05-26 22:42:16.209 svtest[82103:547159] scrollerKnobStyle 0 13 | 2016-05-26 22:42:16.209 svtest[82103:547159] scrollerStyle 1 14 | 2016-05-26 22:42:16.209 svtest[82103:547159] horizontalLineScroll 19 15 | 2016-05-26 22:42:16.209 svtest[82103:547159] verticalLineScroll 19 16 | 2016-05-26 22:42:16.217 svtest[82103:547159] horizontalPageScroll 10 17 | 2016-05-26 22:42:16.218 svtest[82103:547159] verticalPageScroll 10 18 | 2016-05-26 22:42:16.218 svtest[82103:547159] scrollsDynamically 1 19 | 2016-05-26 22:42:16.218 svtest[82103:547159] findBarPosition 1 20 | 2016-05-26 22:42:16.218 svtest[82103:547159] usesPredomAxisScroll 0 21 | 2016-05-26 22:42:16.218 svtest[82103:547159] horizontalElasticity 0 22 | 2016-05-26 22:42:16.218 svtest[82103:547159] verticalElasticity 0 23 | 2016-05-26 22:42:16.218 svtest[82103:547159] 10.8 allowsMagnification 0 24 | 2016-05-26 22:42:16.218 svtest[82103:547159] 10.8 maxMagnification 4 25 | 2016-05-26 22:42:16.218 svtest[82103:547159] 10.8 minMagnification 0.25 26 | -------------------------------------------------------------------------------- /_wip/sv/tableview: -------------------------------------------------------------------------------- 1 | 2016-05-26 22:41:26.514 svtest[82032:546554] backgroundColor NSNamedColorSpace System controlBackgroundColor 2 | 2016-05-26 22:41:26.514 svtest[82032:546554] drawsBackground 1 3 | 2016-05-26 22:41:26.514 svtest[82032:546554] borderType 2 4 | 2016-05-26 22:41:26.514 svtest[82032:546554] documentCursor (null) 5 | 2016-05-26 22:41:26.515 svtest[82032:546554] hasHorizontalScroller 1 6 | 2016-05-26 22:41:26.515 svtest[82032:546554] hasVerticalScroller 1 7 | 2016-05-26 22:41:26.515 svtest[82032:546554] autohidesScrollers 1 8 | 2016-05-26 22:41:26.515 svtest[82032:546554] hasHorizontalRuler 0 9 | 2016-05-26 22:41:26.516 svtest[82032:546554] hasVerticalRuler 0 10 | 2016-05-26 22:41:26.516 svtest[82032:546554] rulersVisible 0 11 | 2016-05-26 22:41:26.516 svtest[82032:546554] 10.10 autoAdjContentInsets 1 12 | 2016-05-26 22:41:26.516 svtest[82032:546554] scrollerKnobStyle 0 13 | 2016-05-26 22:41:26.516 svtest[82032:546554] scrollerStyle 1 14 | 2016-05-26 22:41:26.516 svtest[82032:546554] horizontalLineScroll 19 15 | 2016-05-26 22:41:26.516 svtest[82032:546554] verticalLineScroll 19 16 | 2016-05-26 22:41:26.528 svtest[82032:546554] horizontalPageScroll 10 17 | 2016-05-26 22:41:26.528 svtest[82032:546554] verticalPageScroll 10 18 | 2016-05-26 22:41:26.528 svtest[82032:546554] scrollsDynamically 1 19 | 2016-05-26 22:41:26.528 svtest[82032:546554] findBarPosition 1 20 | 2016-05-26 22:41:26.528 svtest[82032:546554] usesPredomAxisScroll 0 21 | 2016-05-26 22:41:26.528 svtest[82032:546554] horizontalElasticity 0 22 | 2016-05-26 22:41:26.528 svtest[82032:546554] verticalElasticity 0 23 | 2016-05-26 22:41:26.528 svtest[82032:546554] 10.8 allowsMagnification 0 24 | 2016-05-26 22:41:26.528 svtest[82032:546554] 10.8 maxMagnification 4 25 | 2016-05-26 22:41:26.528 svtest[82032:546554] 10.8 minMagnification 0.25 26 | -------------------------------------------------------------------------------- /darwin/graphemes.m: -------------------------------------------------------------------------------- 1 | // 3 december 2016 2 | #import "uipriv_darwin.h" 3 | #import "attrstr.h" 4 | 5 | // CFStringGetRangeOfComposedCharactersAtIndex() is the function for grapheme clusters 6 | // https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/Strings/Articles/stringsClusters.html says that this does work on all multi-codepoint graphemes (despite the name), and that this is the preferred function for this particular job anyway 7 | 8 | int uiprivGraphemesTakesUTF16(void) 9 | { 10 | return 1; 11 | } 12 | 13 | uiprivGraphemes *uiprivNewGraphemes(void *s, size_t len) 14 | { 15 | uiprivGraphemes *g; 16 | UniChar *str = (UniChar *) s; 17 | CFStringRef cfstr; 18 | size_t ppos, gpos; 19 | CFRange range; 20 | size_t i; 21 | 22 | g = uiprivNew(uiprivGraphemes); 23 | 24 | cfstr = CFStringCreateWithCharactersNoCopy(NULL, str, len, kCFAllocatorNull); 25 | if (cfstr == NULL) { 26 | // TODO 27 | } 28 | 29 | // first figure out how many graphemes there are 30 | g->len = 0; 31 | ppos = 0; 32 | while (ppos < len) { 33 | range = CFStringGetRangeOfComposedCharactersAtIndex(cfstr, ppos); 34 | g->len++; 35 | ppos = range.location + range.length; 36 | } 37 | 38 | g->pointsToGraphemes = (size_t *) uiprivAlloc((len + 1) * sizeof (size_t), "size_t[] (graphemes)"); 39 | g->graphemesToPoints = (size_t *) uiprivAlloc((g->len + 1) * sizeof (size_t), "size_t[] (graphemes)"); 40 | 41 | // now calculate everything 42 | // fortunately due to the use of CFRange we can do this in one loop trivially! 43 | ppos = 0; 44 | gpos = 0; 45 | while (ppos < len) { 46 | range = CFStringGetRangeOfComposedCharactersAtIndex(cfstr, ppos); 47 | for (i = 0; i < range.length; i++) 48 | g->pointsToGraphemes[range.location + i] = gpos; 49 | g->graphemesToPoints[gpos] = range.location; 50 | gpos++; 51 | ppos = range.location + range.length; 52 | } 53 | // and set the last one 54 | g->pointsToGraphemes[ppos] = gpos; 55 | g->graphemesToPoints[gpos] = ppos; 56 | 57 | CFRelease(cfstr); 58 | return g; 59 | } 60 | -------------------------------------------------------------------------------- /_wip/sv/textview: -------------------------------------------------------------------------------- 1 | 2016-05-26 22:40:02.050 svtest[81927:545793] backgroundColor NSCalibratedWhiteColorSpace 1 1 2 | 2016-05-26 22:40:02.050 svtest[81927:545793] drawsBackground 1 3 | 2016-05-26 22:40:02.051 svtest[81927:545793] borderType 2 4 | 2016-05-26 22:40:02.052 svtest[81927:545793] documentCursor 5 | 2016-05-26 22:40:02.052 svtest[81927:545793] hasHorizontalScroller 0 6 | 2016-05-26 22:40:02.052 svtest[81927:545793] hasVerticalScroller 1 7 | 2016-05-26 22:40:02.052 svtest[81927:545793] autohidesScrollers 0 8 | 2016-05-26 22:40:02.052 svtest[81927:545793] hasHorizontalRuler 0 9 | 2016-05-26 22:40:02.052 svtest[81927:545793] hasVerticalRuler 0 10 | 2016-05-26 22:40:02.052 svtest[81927:545793] rulersVisible 0 11 | 2016-05-26 22:40:02.052 svtest[81927:545793] 10.10 autoAdjContentInsets 1 12 | 2016-05-26 22:40:02.052 svtest[81927:545793] scrollerKnobStyle 0 13 | 2016-05-26 22:40:02.052 svtest[81927:545793] scrollerStyle 1 14 | 2016-05-26 22:40:02.054 svtest[81927:545793] horizontalLineScroll 10 15 | 2016-05-26 22:40:02.055 svtest[81927:545793] verticalLineScroll 10 16 | 2016-05-26 22:40:02.062 svtest[81927:545793] horizontalPageScroll 10 17 | 2016-05-26 22:40:02.062 svtest[81927:545793] verticalPageScroll 10 18 | 2016-05-26 22:40:02.062 svtest[81927:545793] scrollsDynamically 1 19 | 2016-05-26 22:40:02.062 svtest[81927:545793] findBarPosition 1 20 | 2016-05-26 22:40:02.062 svtest[81927:545793] usesPredomAxisScroll 0 21 | 2016-05-26 22:40:02.062 svtest[81927:545793] horizontalElasticity 0 22 | 2016-05-26 22:40:02.062 svtest[81927:545793] verticalElasticity 0 23 | 2016-05-26 22:40:02.062 svtest[81927:545793] 10.8 allowsMagnification 0 24 | 2016-05-26 22:40:02.062 svtest[81927:545793] 10.8 maxMagnification 4 25 | 2016-05-26 22:40:02.063 svtest[81927:545793] 10.8 minMagnification 0.25 26 | -------------------------------------------------------------------------------- /windows/winapi.hpp: -------------------------------------------------------------------------------- 1 | // 31 may 2015 2 | #define UNICODE 3 | #define _UNICODE 4 | #define STRICT 5 | #define STRICT_TYPED_ITEMIDS 6 | 7 | // see https://github.com/golang/go/issues/9916#issuecomment-74812211 8 | // TODO get rid of this 9 | #define INITGUID 10 | 11 | // for the manifest 12 | #ifndef _UI_STATIC 13 | #define ISOLATION_AWARE_ENABLED 1 14 | #endif 15 | 16 | // get Windows version right; right now Windows Vista 17 | // unless otherwise stated, all values from Microsoft's sdkddkver.h 18 | // TODO is all of this necessary? how is NTDDI_VERSION used? 19 | // TODO platform update sp2 20 | #define WINVER 0x0600 /* from Microsoft's winnls.h */ 21 | #define _WIN32_WINNT 0x0600 22 | #define _WIN32_WINDOWS 0x0600 /* from Microsoft's pdh.h */ 23 | #define _WIN32_IE 0x0700 24 | #define NTDDI_VERSION 0x06000000 25 | 26 | // The MinGW-w64 header has an unverified IDWriteTypography definition. 27 | // TODO I can confirm this myself, but I don't know how long it will take for them to note my adjustments... Either way, I have to confirm this myself. 28 | // TODO change the check from _MSC_VER to a MinGW-w64-specific check 29 | // TODO keep track of what else is guarded by this 30 | #ifndef _MSC_VER 31 | #define __MINGW_USE_BROKEN_INTERFACE 32 | #endif 33 | 34 | #include 35 | 36 | // Microsoft's resource compiler will segfault if we feed it headers it was not designed to handle 37 | #ifndef RC_INVOKED 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include 45 | #include 46 | #include 47 | #include 48 | 49 | #include 50 | #include 51 | #include 52 | #include 53 | #include 54 | #include 55 | #include 56 | #include 57 | 58 | #include 59 | #include 60 | #include 61 | #include 62 | #include 63 | #include 64 | #endif 65 | -------------------------------------------------------------------------------- /_notes/windowsHighDPI: -------------------------------------------------------------------------------- 1 | https://msdn.microsoft.com/en-us/library/windows/desktop/dn469266(v=vs.85).aspx 2 | https://msdn.microsoft.com/en-us/library/windows/desktop/mt744321(v=vs.85).aspx 3 | !!!! http://stackoverflow.com/questions/41917279/do-child-windows-have-the-same-dpi-as-their-parents-in-a-per-monitor-aware-appli 4 | https://msdn.microsoft.com/en-us/library/windows/desktop/mt843498(v=vs.85).aspx 5 | https://msdn.microsoft.com/library/windows/desktop/mt791579(v=vs.85).aspx 6 | https://blogs.windows.com/buildingapps/2017/04/04/high-dpi-scaling-improvements-desktop-applications-windows-10-creators-update/ 7 | https://channel9.msdn.com/Events/Windows/Windows-Developer-Day-Creators-Update/High-DPI-Improvements-for-Desktop-Developers 8 | https://social.msdn.microsoft.com/Forums/vstudio/en-US/31d2a89f-3518-403e-b1e4-bbe37ac1b0f0/per-monitor-high-dpi-awareness-wmdpichanged?forum=vcgeneral 9 | https://stackoverflow.com/questions/36864894/scaling-the-non-client-area-title-bar-menu-bar-for-per-monitor-high-dpi-suppo/37624363 10 | https://stackoverflow.com/questions/41448320/dlgtemplateex-and-ds-shellfont-what-about-point-size 11 | http://stackoverflow.com/questions/41917279/do-child-windows-have-the-same-dpi-as-their-parents-in-a-per-monitor-aware-appli 12 | 13 | https://msdn.microsoft.com/en-us/library/windows/desktop/dn469266(v=vs.85).aspx 14 | https://msdn.microsoft.com/library/windows/desktop/mt843498(v=vs.85).aspx(d=robot) 15 | https://msdn.microsoft.com/en-us/library/windows/desktop/dn469266(v=vs.85).aspx#appendix_c_common_high_dpi_issues 16 | https://msdn.microsoft.com/library/windows/desktop/mt843498(v=vs.85).aspx(d=robot)#appendix_c_common_high_dpi_issues 17 | https://msdn.microsoft.com/en-us/library/windows/desktop/dn469266(v=vs.85).aspx#addressing_high_dpi_issues 18 | https://msdn.microsoft.com/library/windows/desktop/mt843498(v=vs.85).aspx(d=robot)#addressing_high_dpi_issues 19 | 20 | https://msdn.microsoft.com/en-us/library/windows/desktop/dn302215(v=vs.85).aspx 21 | https://msdn.microsoft.com/en-us/library/windows/desktop/hh802769(v=vs.85).aspx 22 | -------------------------------------------------------------------------------- /darwin/progressbar.m: -------------------------------------------------------------------------------- 1 | // 14 august 2015 2 | #import "uipriv_darwin.h" 3 | 4 | // NSProgressIndicator has no intrinsic width by default; use the default width in Interface Builder 5 | #define progressIndicatorWidth 100 6 | 7 | @interface intrinsicWidthNSProgressIndicator : NSProgressIndicator 8 | @end 9 | 10 | @implementation intrinsicWidthNSProgressIndicator 11 | 12 | - (NSSize)intrinsicContentSize 13 | { 14 | NSSize s; 15 | 16 | s = [super intrinsicContentSize]; 17 | s.width = progressIndicatorWidth; 18 | return s; 19 | } 20 | 21 | @end 22 | 23 | struct uiProgressBar { 24 | uiDarwinControl c; 25 | NSProgressIndicator *pi; 26 | }; 27 | 28 | uiDarwinControlAllDefaults(uiProgressBar, pi) 29 | 30 | int uiProgressBarValue(uiProgressBar *p) 31 | { 32 | if ([p->pi isIndeterminate]) 33 | return -1; 34 | return [p->pi doubleValue]; 35 | } 36 | 37 | void uiProgressBarSetValue(uiProgressBar *p, int value) 38 | { 39 | if (value == -1) { 40 | [p->pi setIndeterminate:YES]; 41 | [p->pi startAnimation:p->pi]; 42 | return; 43 | } 44 | 45 | if ([p->pi isIndeterminate]) { 46 | [p->pi setIndeterminate:NO]; 47 | [p->pi stopAnimation:p->pi]; 48 | } 49 | 50 | if (value < 0 || value > 100) 51 | uiprivUserBug("Value %d out of range for a uiProgressBar.", value); 52 | 53 | // on 10.8 there's an animation when the progress bar increases, just like with Aero 54 | if (value == 100) { 55 | [p->pi setMaxValue:101]; 56 | [p->pi setDoubleValue:101]; 57 | [p->pi setDoubleValue:100]; 58 | [p->pi setMaxValue:100]; 59 | return; 60 | } 61 | [p->pi setDoubleValue:((double) (value + 1))]; 62 | [p->pi setDoubleValue:((double) value)]; 63 | } 64 | 65 | uiProgressBar *uiNewProgressBar(void) 66 | { 67 | uiProgressBar *p; 68 | 69 | uiDarwinNewControl(uiProgressBar, p); 70 | 71 | p->pi = [[intrinsicWidthNSProgressIndicator alloc] initWithFrame:NSZeroRect]; 72 | [p->pi setControlSize:NSRegularControlSize]; 73 | [p->pi setBezeled:YES]; 74 | [p->pi setStyle:NSProgressIndicatorBarStyle]; 75 | [p->pi setIndeterminate:NO]; 76 | 77 | return p; 78 | } 79 | -------------------------------------------------------------------------------- /darwin/future.m: -------------------------------------------------------------------------------- 1 | // 19 may 2017 2 | #import "uipriv_darwin.h" 3 | 4 | // functions and constants FROM THE FUTURE! 5 | // note: for constants, dlsym() returns the address of the constant itself, as if we had done &constantName 6 | 7 | // added in OS X 10.10; we need 10.8 8 | CFStringRef *uiprivFUTURE_kCTFontOpenTypeFeatureTag = NULL; 9 | CFStringRef *uiprivFUTURE_kCTFontOpenTypeFeatureValue = NULL; 10 | 11 | // added in OS X 10.12; we need 10.8 12 | CFStringRef *uiprivFUTURE_kCTBackgroundColorAttributeName = NULL; 13 | 14 | // note that we treat any error as "the symbols aren't there" (and don't care if dlclose() failed) 15 | void uiprivLoadFutures(void) 16 | { 17 | void *handle; 18 | 19 | // dlsym() walks the dependency chain, so opening the current process should be sufficient 20 | handle = dlopen(NULL, RTLD_LAZY); 21 | if (handle == NULL) 22 | return; 23 | #define GET(var, fn) *((void **) (&var)) = dlsym(handle, #fn) 24 | GET(uiprivFUTURE_kCTFontOpenTypeFeatureTag, kCTFontOpenTypeFeatureTag); 25 | GET(uiprivFUTURE_kCTFontOpenTypeFeatureValue, kCTFontOpenTypeFeatureValue); 26 | GET(uiprivFUTURE_kCTBackgroundColorAttributeName, kCTBackgroundColorAttributeName); 27 | dlclose(handle); 28 | } 29 | 30 | // wrappers for methods that exist in the future that we can check for with respondsToSelector: 31 | // keep them in one place for convenience 32 | 33 | // apparently only added in 10.9; we need 10.8 34 | void uiprivFUTURE_NSLayoutConstraint_setIdentifier(NSLayoutConstraint *constraint, NSString *identifier) 35 | { 36 | id cid = (id) constraint; 37 | 38 | if ([constraint respondsToSelector:@selector(setIdentifier:)]) 39 | [cid setIdentifier:identifier]; 40 | } 41 | 42 | // added in 10.11; we need 10.8 43 | // return whether this was done because we recreate its effects if not (see winmoveresize.m) 44 | BOOL uiprivFUTURE_NSWindow_performWindowDragWithEvent(NSWindow *w, NSEvent *initialEvent) 45 | { 46 | id cw = (id) w; 47 | 48 | if ([w respondsToSelector:@selector(performWindowDragWithEvent:)]) { 49 | [cw performWindowDragWithEvent:initialEvent]; 50 | return YES; 51 | } 52 | return NO; 53 | } 54 | -------------------------------------------------------------------------------- /common/tablemodel.c: -------------------------------------------------------------------------------- 1 | // 23 june 2018 2 | #include "../ui.h" 3 | #include "uipriv.h" 4 | #include "table.h" 5 | 6 | int uiprivTableModelNumColumns(uiTableModel *m) 7 | { 8 | uiTableModelHandler *mh; 9 | 10 | mh = uiprivTableModelHandler(m); 11 | return (*(mh->NumColumns))(mh, m); 12 | } 13 | 14 | uiTableValueType uiprivTableModelColumnType(uiTableModel *m, int column) 15 | { 16 | uiTableModelHandler *mh; 17 | 18 | mh = uiprivTableModelHandler(m); 19 | return (*(mh->ColumnType))(mh, m, column); 20 | } 21 | 22 | int uiprivTableModelNumRows(uiTableModel *m) 23 | { 24 | uiTableModelHandler *mh; 25 | 26 | mh = uiprivTableModelHandler(m); 27 | return (*(mh->NumRows))(mh, m); 28 | } 29 | 30 | uiTableValue *uiprivTableModelCellValue(uiTableModel *m, int row, int column) 31 | { 32 | uiTableModelHandler *mh; 33 | 34 | mh = uiprivTableModelHandler(m); 35 | return (*(mh->CellValue))(mh, m, row, column); 36 | } 37 | 38 | void uiprivTableModelSetCellValue(uiTableModel *m, int row, int column, const uiTableValue *value) 39 | { 40 | uiTableModelHandler *mh; 41 | 42 | mh = uiprivTableModelHandler(m); 43 | (*(mh->SetCellValue))(mh, m, row, column, value); 44 | } 45 | 46 | const uiTableTextColumnOptionalParams uiprivDefaultTextColumnOptionalParams = { 47 | .ColorModelColumn = -1, 48 | }; 49 | 50 | int uiprivTableModelCellEditable(uiTableModel *m, int row, int column) 51 | { 52 | uiTableValue *value; 53 | int editable; 54 | 55 | switch (column) { 56 | case uiTableModelColumnNeverEditable: 57 | return 0; 58 | case uiTableModelColumnAlwaysEditable: 59 | return 1; 60 | } 61 | value = uiprivTableModelCellValue(m, row, column); 62 | editable = uiTableValueInt(value); 63 | uiFreeTableValue(value); 64 | return editable; 65 | } 66 | 67 | int uiprivTableModelColorIfProvided(uiTableModel *m, int row, int column, double *r, double *g, double *b, double *a) 68 | { 69 | uiTableValue *value; 70 | 71 | if (column == -1) 72 | return 0; 73 | value = uiprivTableModelCellValue(m, row, column); 74 | if (value == NULL) 75 | return 0; 76 | uiTableValueColor(value, r, g, b, a); 77 | uiFreeTableValue(value); 78 | return 1; 79 | } 80 | -------------------------------------------------------------------------------- /windows/graphemes.cpp: -------------------------------------------------------------------------------- 1 | // 25 may 2016 2 | #include "uipriv_windows.hpp" 3 | #include "attrstr.hpp" 4 | 5 | // We could use CharNextW() to generate grapheme cluster boundaries, but it doesn't handle surrogate pairs properly (see http://archives.miloush.net/michkap/archive/2008/12/16/9223301.html). 6 | // We could also use Uniscribe (see http://archives.miloush.net/michkap/archive/2005/01/14/352802.html, http://www.catch22.net/tuts/uniscribe-mysteries, http://www.catch22.net/tuts/keyboard-navigation, and https://maxradi.us/documents/uniscribe/), but its rules for buffer sizes is convoluted. 7 | // Let's just deal with the CharNextW() bug. 8 | 9 | int uiprivGraphemesTakesUTF16(void) 10 | { 11 | return 1; 12 | } 13 | 14 | uiprivGraphemes *uiprivNewGraphemes(void *s, size_t len) 15 | { 16 | uiprivGraphemes *g; 17 | WCHAR *str; 18 | size_t *pPTG, *pGTP; 19 | 20 | g = uiprivNew(uiprivGraphemes); 21 | 22 | g->len = 0; 23 | str = (WCHAR *) s; 24 | while (*str != L'\0') { 25 | g->len++; 26 | str = CharNextW(str); 27 | // no need to worry about surrogates if we're just counting 28 | } 29 | 30 | g->pointsToGraphemes = (size_t *) uiprivAlloc((len + 1) * sizeof (size_t), "size_t[] (graphemes)"); 31 | g->graphemesToPoints = (size_t *) uiprivAlloc((g->len + 1) * sizeof (size_t), "size_t[] (graphemes)"); 32 | 33 | pPTG = g->pointsToGraphemes; 34 | pGTP = g->graphemesToPoints; 35 | str = (WCHAR *) s; 36 | while (*str != L'\0') { 37 | WCHAR *next, *p; 38 | ptrdiff_t nextoff; 39 | 40 | // as part of the bug, we need to make sure we only call CharNextW() on low halves, otherwise it'll return the same low half forever 41 | nextoff = 0; 42 | if (IS_HIGH_SURROGATE(*str)) 43 | nextoff = 1; 44 | next = CharNextW(str + nextoff); 45 | if (IS_LOW_SURROGATE(*next)) 46 | next--; 47 | 48 | *pGTP = pPTG - g->pointsToGraphemes; 49 | for (p = str; p < next; p++) 50 | *pPTG++ = pGTP - g->graphemesToPoints; 51 | pGTP++; 52 | 53 | str = next; 54 | } 55 | // and handle the last item for the end of the string 56 | *pGTP = pPTG - g->pointsToGraphemes; 57 | *pPTG = pGTP - g->graphemesToPoints; 58 | 59 | return g; 60 | } 61 | -------------------------------------------------------------------------------- /unix/checkbox.c: -------------------------------------------------------------------------------- 1 | // 10 june 2015 2 | #include "uipriv_unix.h" 3 | 4 | struct uiCheckbox { 5 | uiUnixControl c; 6 | GtkWidget *widget; 7 | GtkButton *button; 8 | GtkToggleButton *toggleButton; 9 | GtkCheckButton *checkButton; 10 | void (*onToggled)(uiCheckbox *, void *); 11 | void *onToggledData; 12 | gulong onToggledSignal; 13 | }; 14 | 15 | uiUnixControlAllDefaults(uiCheckbox) 16 | 17 | static void onToggled(GtkToggleButton *b, gpointer data) 18 | { 19 | uiCheckbox *c = uiCheckbox(data); 20 | 21 | (*(c->onToggled))(c, c->onToggledData); 22 | } 23 | 24 | static void defaultOnToggled(uiCheckbox *c, void *data) 25 | { 26 | // do nothing 27 | } 28 | 29 | char *uiCheckboxText(uiCheckbox *c) 30 | { 31 | return uiUnixStrdupText(gtk_button_get_label(c->button)); 32 | } 33 | 34 | void uiCheckboxSetText(uiCheckbox *c, const char *text) 35 | { 36 | gtk_button_set_label(GTK_BUTTON(c->button), text); 37 | } 38 | 39 | void uiCheckboxOnToggled(uiCheckbox *c, void (*f)(uiCheckbox *, void *), void *data) 40 | { 41 | c->onToggled = f; 42 | c->onToggledData = data; 43 | } 44 | 45 | int uiCheckboxChecked(uiCheckbox *c) 46 | { 47 | return gtk_toggle_button_get_active(c->toggleButton) != FALSE; 48 | } 49 | 50 | void uiCheckboxSetChecked(uiCheckbox *c, int checked) 51 | { 52 | gboolean active; 53 | 54 | active = FALSE; 55 | if (checked) 56 | active = TRUE; 57 | // we need to inhibit sending of ::toggled because this WILL send a ::toggled otherwise 58 | g_signal_handler_block(c->toggleButton, c->onToggledSignal); 59 | gtk_toggle_button_set_active(c->toggleButton, active); 60 | g_signal_handler_unblock(c->toggleButton, c->onToggledSignal); 61 | } 62 | 63 | uiCheckbox *uiNewCheckbox(const char *text) 64 | { 65 | uiCheckbox *c; 66 | 67 | uiUnixNewControl(uiCheckbox, c); 68 | 69 | c->widget = gtk_check_button_new_with_label(text); 70 | c->button = GTK_BUTTON(c->widget); 71 | c->toggleButton = GTK_TOGGLE_BUTTON(c->widget); 72 | c->checkButton = GTK_CHECK_BUTTON(c->widget); 73 | 74 | c->onToggledSignal = g_signal_connect(c->widget, "toggled", G_CALLBACK(onToggled), c); 75 | uiCheckboxOnToggled(c, defaultOnToggled, NULL); 76 | 77 | return c; 78 | } 79 | -------------------------------------------------------------------------------- /unix/colorbutton.c: -------------------------------------------------------------------------------- 1 | // 15 may 2016 2 | #include "uipriv_unix.h" 3 | 4 | struct uiColorButton { 5 | uiUnixControl c; 6 | GtkWidget *widget; 7 | GtkButton *button; 8 | GtkColorButton *cb; 9 | GtkColorChooser *cc; 10 | void (*onChanged)(uiColorButton *, void *); 11 | void *onChangedData; 12 | }; 13 | 14 | uiUnixControlAllDefaults(uiColorButton) 15 | 16 | static void onColorSet(GtkColorButton *button, gpointer data) 17 | { 18 | uiColorButton *b = uiColorButton(data); 19 | 20 | (*(b->onChanged))(b, b->onChangedData); 21 | } 22 | 23 | static void defaultOnChanged(uiColorButton *b, void *data) 24 | { 25 | // do nothing 26 | } 27 | 28 | void uiColorButtonColor(uiColorButton *b, double *r, double *g, double *bl, double *a) 29 | { 30 | GdkRGBA rgba; 31 | 32 | gtk_color_chooser_get_rgba(b->cc, &rgba); 33 | *r = rgba.red; 34 | *g = rgba.green; 35 | *bl = rgba.blue; 36 | *a = rgba.alpha; 37 | } 38 | 39 | void uiColorButtonSetColor(uiColorButton *b, double r, double g, double bl, double a) 40 | { 41 | GdkRGBA rgba; 42 | 43 | rgba.red = r; 44 | rgba.green = g; 45 | rgba.blue = bl; 46 | rgba.alpha = a; 47 | // no need to inhibit the signal; color-set is documented as only being sent when the user changes the color 48 | gtk_color_chooser_set_rgba(b->cc, &rgba); 49 | } 50 | 51 | void uiColorButtonOnChanged(uiColorButton *b, void (*f)(uiColorButton *, void *), void *data) 52 | { 53 | b->onChanged = f; 54 | b->onChangedData = data; 55 | } 56 | 57 | uiColorButton *uiNewColorButton(void) 58 | { 59 | uiColorButton *b; 60 | GdkRGBA black; 61 | 62 | uiUnixNewControl(uiColorButton, b); 63 | 64 | // I'm not sure what the initial color is; set up a real one 65 | black.red = 0.0; 66 | black.green = 0.0; 67 | black.blue = 0.0; 68 | black.alpha = 1.0; 69 | b->widget = gtk_color_button_new_with_rgba(&black); 70 | b->button = GTK_BUTTON(b->widget); 71 | b->cb = GTK_COLOR_BUTTON(b->widget); 72 | b->cc = GTK_COLOR_CHOOSER(b->widget); 73 | 74 | gtk_color_chooser_set_use_alpha(b->cc, TRUE); 75 | 76 | g_signal_connect(b->widget, "color-set", G_CALLBACK(onColorSet), b); 77 | uiColorButtonOnChanged(b, defaultOnChanged, NULL); 78 | 79 | return b; 80 | } 81 | -------------------------------------------------------------------------------- /unix/future.c: -------------------------------------------------------------------------------- 1 | // 29 june 2016 2 | #include "uipriv_unix.h" 3 | 4 | // functions FROM THE FUTURE! 5 | // in some cases, because being held back by LTS releases sucks :/ 6 | // in others, because parts of GTK+ being unstable until recently also sucks :/ 7 | 8 | // added in pango 1.38; we need 1.36 9 | static PangoAttribute *(*newFeaturesAttr)(const gchar *features) = NULL; 10 | static PangoAttribute *(*newFGAlphaAttr)(guint16 alpha) = NULL; 11 | static PangoAttribute *(*newBGAlphaAttr)(guint16 alpha) = NULL; 12 | 13 | // added in GTK+ 3.20; we need 3.10 14 | static void (*gwpIterSetObjectName)(GtkWidgetPath *path, gint pos, const char *name) = NULL; 15 | 16 | // note that we treat any error as "the symbols aren't there" (and don't care if dlclose() failed) 17 | void uiprivLoadFutures(void) 18 | { 19 | void *handle; 20 | 21 | // dlsym() walks the dependency chain, so opening the current process should be sufficient 22 | handle = dlopen(NULL, RTLD_LAZY); 23 | if (handle == NULL) 24 | return; 25 | #define GET(var, fn) *((void **) (&var)) = dlsym(handle, #fn) 26 | GET(newFeaturesAttr, pango_attr_font_features_new); 27 | GET(newFGAlphaAttr, pango_attr_foreground_alpha_new); 28 | GET(newBGAlphaAttr, pango_attr_background_alpha_new); 29 | GET(gwpIterSetObjectName, gtk_widget_path_iter_set_object_name); 30 | dlclose(handle); 31 | } 32 | 33 | PangoAttribute *uiprivFUTURE_pango_attr_font_features_new(const gchar *features) 34 | { 35 | if (newFeaturesAttr == NULL) 36 | return NULL; 37 | return (*newFeaturesAttr)(features); 38 | } 39 | 40 | PangoAttribute *uiprivFUTURE_pango_attr_foreground_alpha_new(guint16 alpha) 41 | { 42 | if (newFGAlphaAttr == NULL) 43 | return NULL; 44 | return (*newFGAlphaAttr)(alpha); 45 | } 46 | 47 | PangoAttribute *uiprivFUTURE_pango_attr_background_alpha_new(guint16 alpha) 48 | { 49 | if (newBGAlphaAttr == NULL) 50 | return NULL; 51 | return (*newBGAlphaAttr)(alpha); 52 | } 53 | 54 | gboolean uiprivFUTURE_gtk_widget_path_iter_set_object_name(GtkWidgetPath *path, gint pos, const char *name) 55 | { 56 | if (gwpIterSetObjectName == NULL) 57 | return FALSE; 58 | (*gwpIterSetObjectName)(path, pos, name); 59 | return TRUE; 60 | } 61 | -------------------------------------------------------------------------------- /examples/cpp-multithread/main.cpp: -------------------------------------------------------------------------------- 1 | // 6 december 2015 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include "../../ui.h" 10 | using namespace std; 11 | 12 | uiMultilineEntry *e; 13 | condition_variable cv; 14 | mutex m; 15 | unique_lock ourlock(m); 16 | thread *timeThread; 17 | 18 | void sayTime(void *data) 19 | { 20 | char *s = (char *) data; 21 | 22 | uiMultilineEntryAppend(e, s); 23 | delete s; 24 | } 25 | 26 | void threadproc(void) 27 | { 28 | ourlock.lock(); 29 | while (cv.wait_for(ourlock, chrono::seconds(1)) == cv_status::timeout) { 30 | time_t t; 31 | char *base; 32 | char *s; 33 | 34 | t = time(NULL); 35 | base = ctime(&t); 36 | s = new char[strlen(base) + 1]; 37 | strcpy(s, base); 38 | uiQueueMain(sayTime, s); 39 | } 40 | } 41 | 42 | int onClosing(uiWindow *w, void *data) 43 | { 44 | cv.notify_all(); 45 | // C++ throws a hissy fit if you don't do this 46 | // we might as well, to ensure no uiQueueMain() gets in after uiQuit() 47 | timeThread->join(); 48 | uiQuit(); 49 | return 1; 50 | } 51 | 52 | void saySomething(uiButton *b, void *data) 53 | { 54 | uiMultilineEntryAppend(e, "Saying something\n"); 55 | } 56 | 57 | int main(void) 58 | { 59 | uiInitOptions o; 60 | uiWindow *w; 61 | uiBox *b; 62 | uiButton *btn; 63 | 64 | memset(&o, 0, sizeof (uiInitOptions)); 65 | if (uiInit(&o) != NULL) 66 | abort(); 67 | 68 | w = uiNewWindow("Hello", 320, 240, 0); 69 | uiWindowSetMargined(w, 1); 70 | 71 | b = uiNewVerticalBox(); 72 | uiBoxSetPadded(b, 1); 73 | uiWindowSetChild(w, uiControl(b)); 74 | 75 | e = uiNewMultilineEntry(); 76 | uiMultilineEntrySetReadOnly(e, 1); 77 | 78 | btn = uiNewButton("Say Something"); 79 | uiButtonOnClicked(btn, saySomething, NULL); 80 | uiBoxAppend(b, uiControl(btn), 0); 81 | 82 | uiBoxAppend(b, uiControl(e), 1); 83 | 84 | // timeThread needs to lock ourlock itself - see http://stackoverflow.com/a/34121629/3408572 85 | ourlock.unlock(); 86 | timeThread = new thread(threadproc); 87 | 88 | uiWindowOnClosing(w, onClosing, NULL); 89 | uiControlShow(uiControl(w)); 90 | uiMain(); 91 | return 0; 92 | } 93 | -------------------------------------------------------------------------------- /unix/fontbutton.c: -------------------------------------------------------------------------------- 1 | // 14 april 2016 2 | #include "uipriv_unix.h" 3 | #include "attrstr.h" 4 | 5 | struct uiFontButton { 6 | uiUnixControl c; 7 | GtkWidget *widget; 8 | GtkButton *button; 9 | GtkFontButton *fb; 10 | GtkFontChooser *fc; 11 | void (*onChanged)(uiFontButton *, void *); 12 | void *onChangedData; 13 | }; 14 | 15 | uiUnixControlAllDefaults(uiFontButton) 16 | 17 | // TODO NOTE no need to inhibit the signal; font-set is documented as only being sent when the user changes the font 18 | static void onFontSet(GtkFontButton *button, gpointer data) 19 | { 20 | uiFontButton *b = uiFontButton(data); 21 | 22 | (*(b->onChanged))(b, b->onChangedData); 23 | } 24 | 25 | static void defaultOnChanged(uiFontButton *b, void *data) 26 | { 27 | // do nothing 28 | } 29 | 30 | void uiFontButtonFont(uiFontButton *b, uiFontDescriptor *desc) 31 | { 32 | PangoFontDescription *pdesc; 33 | 34 | pdesc = gtk_font_chooser_get_font_desc(b->fc); 35 | uiprivFontDescriptorFromPangoFontDescription(pdesc, desc); 36 | // pdesc is transfer-full and thus is a copy 37 | pango_font_description_free(pdesc); 38 | } 39 | 40 | void uiFontButtonOnChanged(uiFontButton *b, void (*f)(uiFontButton *, void *), void *data) 41 | { 42 | b->onChanged = f; 43 | b->onChangedData = data; 44 | } 45 | 46 | uiFontButton *uiNewFontButton(void) 47 | { 48 | uiFontButton *b; 49 | 50 | uiUnixNewControl(uiFontButton, b); 51 | 52 | b->widget = gtk_font_button_new(); 53 | b->button = GTK_BUTTON(b->widget); 54 | b->fb = GTK_FONT_BUTTON(b->widget); 55 | b->fc = GTK_FONT_CHOOSER(b->widget); 56 | 57 | // match behavior on other platforms 58 | gtk_font_button_set_show_style(b->fb, TRUE); 59 | gtk_font_button_set_show_size(b->fb, TRUE); 60 | gtk_font_button_set_use_font(b->fb, FALSE); 61 | gtk_font_button_set_use_size(b->fb, FALSE); 62 | // other customizations 63 | gtk_font_chooser_set_show_preview_entry(b->fc, TRUE); 64 | 65 | g_signal_connect(b->widget, "font-set", G_CALLBACK(onFontSet), b); 66 | uiFontButtonOnChanged(b, defaultOnChanged, NULL); 67 | 68 | return b; 69 | } 70 | 71 | void uiFreeFontButtonFont(uiFontDescriptor *desc) 72 | { 73 | // TODO ensure this is synchronized with fontmatch.c 74 | uiFreeText((char *) (desc->Family)); 75 | } 76 | -------------------------------------------------------------------------------- /_notes/OS2: -------------------------------------------------------------------------------- 1 | https://twitter.com/OS2World/status/983822011389620224 2 | Hi. I recommend you today to start with OS/2 Warp 4.52 or ArcaOS ( The tools are almost the same of Warp 3). EDM/2 is a good place to start: http://www.edm2.com 3 | https://twitter.com/OS2World/status/983822594465034240 4 | There is also an RPM with OS/2 Software (https://www.arcanoae.com/resources/downloadables/arca-noae-package-manager/ …), and you can get from it some parts of the OS/2 Toolkit. If you want to develop drivers you require the OS/2 Device Driver Kit. (that is more complex). You can also develop in Qt4 and compile things with gcc. 5 | http://www.edm2.com/index.php/Main_Page 6 | https://www.arcanoae.com/resources/downloadables/arca-noae-package-manager/ 7 | http://www.edm2.com/index.php/IBM_OS/2_Toolkit_Documentation 8 | https://www.os2world.com/forum/index.php?topic=953.0 9 | https://www.google.com/search?client=firefox-b-1&ei=QIPPWurPLs7OwAK65K24BA&q=%22OS%2F2+Toolkit%22+site%3Aamazon.com&oq=%22OS%2F2+Toolkit%22+site%3AAmazon.com&gs_l=psy-ab.3...160814.161293.0.161540.2.2.0.0.0.0.128.252.0j2.2.0....0...1c.1.64.psy-ab..0.0.0....0.itT9Og6hC5c 10 | http://www.edm2.com/index.php/List_of_Presentation_Manager_Articles 11 | https://www.ecsoft2.org/ 12 | http://www.edm2.com/index.php/Cairo 13 | http://www.edm2.com/index.php/Doodle 14 | http://www.edm2.com/index.php/Workplace_Shell_Toolkit 15 | http://wpstk.netlabs.org/en/site/index.xml 16 | https://en.wikipedia.org/wiki/Workplace_Shell 17 | https://www.google.com/search?q=OS2+alphablending&ie=utf-8&oe=utf-8&client=firefox-b-1 18 | http://www.edm2.com/index.php/List_of_Multimedia_Articles 19 | alphablending: 20 | http://www.osnews.com/story/369/Review-eComStation-OS2-1.0/page3/ 21 | http://halfos.ru/documentation/33-os2-api-documentation/67-opengl-os2-developer-reference-guide.html 22 | http://www.altools.com/ALTools/ALSee/ALSee-Image-Viewer.aspx 23 | http://www.os2voice.org/vnewsarc/bn2007122.html 24 | http://www.mozillazine.org/talkback.html?article=194 25 | https://books.google.com/books?id=9cpU5uYCzq4C&pg=PA202&lpg=PA202&dq=%22OS/2%22+alphablending&source=bl&ots=uatEop2jAL&sig=HAa_ofQSKsk6-8tBR6YZ6MRJG_0&hl=en&sa=X&ved=0ahUKEwiDq5HukLbaAhUk8IMKHR7aCw4Q6AEIWTAI#v=onepage&q=%22OS%2F2%22%20alphablending&f=false 26 | -------------------------------------------------------------------------------- /windows/sizing.cpp: -------------------------------------------------------------------------------- 1 | // 14 may 2015 2 | #include "uipriv_windows.hpp" 3 | 4 | // TODO rework the error handling 5 | void getSizing(HWND hwnd, uiWindowsSizing *sizing, HFONT font) 6 | { 7 | HDC dc; 8 | HFONT prevfont; 9 | TEXTMETRICW tm; 10 | SIZE size; 11 | 12 | dc = GetDC(hwnd); 13 | if (dc == NULL) 14 | logLastError(L"error getting DC"); 15 | prevfont = (HFONT) SelectObject(dc, font); 16 | if (prevfont == NULL) 17 | logLastError(L"error loading control font into device context"); 18 | 19 | ZeroMemory(&tm, sizeof (TEXTMETRICW)); 20 | if (GetTextMetricsW(dc, &tm) == 0) 21 | logLastError(L"error getting text metrics"); 22 | if (GetTextExtentPoint32W(dc, L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 52, &size) == 0) 23 | logLastError(L"error getting text extent point"); 24 | 25 | sizing->BaseX = (int) ((size.cx / 26 + 1) / 2); 26 | sizing->BaseY = (int) tm.tmHeight; 27 | sizing->InternalLeading = tm.tmInternalLeading; 28 | 29 | if (SelectObject(dc, prevfont) != font) 30 | logLastError(L"error restoring previous font into device context"); 31 | if (ReleaseDC(hwnd, dc) == 0) 32 | logLastError(L"error releasing DC"); 33 | } 34 | 35 | void uiWindowsGetSizing(HWND hwnd, uiWindowsSizing *sizing) 36 | { 37 | return getSizing(hwnd, sizing, hMessageFont); 38 | } 39 | 40 | #define dlgUnitsToX(dlg, baseX) MulDiv((dlg), (baseX), 4) 41 | #define dlgUnitsToY(dlg, baseY) MulDiv((dlg), (baseY), 8) 42 | 43 | void uiWindowsSizingDlgUnitsToPixels(uiWindowsSizing *sizing, int *x, int *y) 44 | { 45 | if (x != NULL) 46 | *x = dlgUnitsToX(*x, sizing->BaseX); 47 | if (y != NULL) 48 | *y = dlgUnitsToY(*y, sizing->BaseY); 49 | } 50 | 51 | // from https://msdn.microsoft.com/en-us/library/windows/desktop/dn742486.aspx#sizingandspacing and https://msdn.microsoft.com/en-us/library/windows/desktop/bb226818%28v=vs.85%29.aspx 52 | // this X value is really only for buttons but I don't see a better one :/ 53 | #define winXPadding 4 54 | // TODO is this too much? 55 | #define winYPadding 4 56 | 57 | void uiWindowsSizingStandardPadding(uiWindowsSizing *sizing, int *x, int *y) 58 | { 59 | if (x != NULL) 60 | *x = dlgUnitsToX(winXPadding, sizing->BaseX); 61 | if (y != NULL) 62 | *y = dlgUnitsToY(winYPadding, sizing->BaseY); 63 | } 64 | -------------------------------------------------------------------------------- /_doc/export/ctwidthscombined: -------------------------------------------------------------------------------- 1 | -0.100000 2 | style string contains "Semi Cond" 3 | style string contains "Semi Condensed"; unregistered fonts only (see below) 4 | style string contains "SemiCondensed" 5 | OS2 width 4 6 | 7 | -0.200000 8 | ('head' table byte 0x2d) & 0x20 != 0 9 | ATSD style "cond" 10 | panose 6 11 | style string contains "Cond" 12 | style string contains "Condensed" 13 | OS2 width 3 14 | 15 | -0.400000 16 | panose 8 17 | style string contains "Compact" 18 | style string contains "Narrow" 19 | 20 | -0.500000 21 | style string contains "Compressed" 22 | style string contains "Ext Cond" 23 | style string contains "Ext Condensed" 24 | style string contains "Extra Cond" 25 | style string contains "Extra Condensed" 26 | style string contains "Extra Narrow" 27 | style string contains "ExtraNarrow" 28 | OS2 width 2 29 | 30 | -0.700000 31 | style string contains "Ext Compressed" 32 | style string contains "Extra Compressed" 33 | style string contains "Semi Condensed" (this is probably a typo, since another "Semi Condensed" with a value of -0.1 follows this in the table it comes from); registered fonts only 34 | style string contains "Thin" 35 | style string contains "Ultra Compressed" 36 | style string contains "Ultra Cond" 37 | style string contains "Ultra Condensed" 38 | OS2 width 1 39 | 40 | 0.000000 41 | default 42 | ATSD style "med" 43 | panose 2, 3, 4 44 | OS2 width 5 45 | 46 | 0.100000 47 | style string contains "Semi Expanded" 48 | style string contains "Semi Extended" 49 | style string contains "SemiExpanded" 50 | OS2 width 6 51 | 52 | 0.200000 53 | ('head' table byte 0x2d) & 0x40 != 0 54 | ATSD style "ext" 55 | panose 5 56 | style string contains "Expanded" 57 | style string contains "Extended" 58 | 59 | 0.400000 60 | panose 7 61 | style string contains "Ext Expanded" 62 | style string contains "Ext Extended" 63 | style string contains "Extra Expanded" 64 | style string contains "Extra Extended" 65 | style string contains "ExtraExpanded" 66 | OS2 width 7 67 | 68 | 0.600000 69 | style string contains "Wide" 70 | OS2 width 8 71 | 72 | 0.800000 73 | style string contains "Extra Wide" 74 | style string contains "ExtraWide" 75 | style string contains "Ultra Expanded" 76 | style string contains "Ultra Extended" 77 | OS2 width 9 78 | -------------------------------------------------------------------------------- /common/attrstr.h: -------------------------------------------------------------------------------- 1 | // 19 february 2018 2 | 3 | #ifdef __cplusplus 4 | extern "C" { 5 | #endif 6 | 7 | // attribute.c 8 | extern uiAttribute *uiprivAttributeRetain(uiAttribute *a); 9 | extern void uiprivAttributeRelease(uiAttribute *a); 10 | extern int uiprivAttributeEqual(const uiAttribute *a, const uiAttribute *b); 11 | 12 | // opentype.c 13 | extern int uiprivOpenTypeFeaturesEqual(const uiOpenTypeFeatures *a, const uiOpenTypeFeatures *b); 14 | 15 | // attrlist.c 16 | typedef struct uiprivAttrList uiprivAttrList; 17 | extern uiprivAttrList *uiprivNewAttrList(void); 18 | extern void uiprivFreeAttrList(uiprivAttrList *alist); 19 | extern void uiprivAttrListInsertAttribute(uiprivAttrList *alist, uiAttribute *val, size_t start, size_t end); 20 | extern void uiprivAttrListInsertCharactersUnattributed(uiprivAttrList *alist, size_t start, size_t count); 21 | extern void uiprivAttrListInsertCharactersExtendingAttributes(uiprivAttrList *alist, size_t start, size_t count); 22 | extern void uiprivAttrListRemoveAttribute(uiprivAttrList *alist, uiAttributeType type, size_t start, size_t end); 23 | extern void uiprivAttrListRemoveAttributes(uiprivAttrList *alist, size_t start, size_t end); 24 | extern void uiprivAttrListRemoveCharacters(uiprivAttrList *alist, size_t start, size_t end); 25 | extern void uiprivAttrListForEach(const uiprivAttrList *alist, const uiAttributedString *s, uiAttributedStringForEachAttributeFunc f, void *data); 26 | 27 | // attrstr.c 28 | extern const uint16_t *uiprivAttributedStringUTF16String(const uiAttributedString *s); 29 | extern size_t uiprivAttributedStringUTF16Len(const uiAttributedString *s); 30 | extern size_t uiprivAttributedStringUTF8ToUTF16(const uiAttributedString *s, size_t n); 31 | extern size_t *uiprivAttributedStringCopyUTF8ToUTF16Table(const uiAttributedString *s, size_t *n); 32 | extern size_t *uiprivAttributedStringCopyUTF16ToUTF8Table(const uiAttributedString *s, size_t *n); 33 | 34 | // per-OS graphemes.c/graphemes.cpp/graphemes.m/etc. 35 | typedef struct uiprivGraphemes uiprivGraphemes; 36 | struct uiprivGraphemes { 37 | size_t len; 38 | size_t *pointsToGraphemes; 39 | size_t *graphemesToPoints; 40 | }; 41 | extern int uiprivGraphemesTakesUTF16(void); 42 | extern uiprivGraphemes *uiprivNewGraphemes(void *s, size_t len); 43 | 44 | #ifdef __cplusplus 45 | } 46 | #endif 47 | -------------------------------------------------------------------------------- /unix/stddialogs.c: -------------------------------------------------------------------------------- 1 | // 26 june 2015 2 | #include "uipriv_unix.h" 3 | 4 | // LONGTERM figure out why, and describe, that this is the desired behavior 5 | // LONGTERM also point out that font and color buttons also work like this 6 | 7 | #define windowWindow(w) (GTK_WINDOW(uiControlHandle(uiControl(w)))) 8 | 9 | static char *filedialog(GtkWindow *parent, GtkFileChooserAction mode, const gchar *confirm) 10 | { 11 | GtkWidget *fcd; 12 | GtkFileChooser *fc; 13 | gint response; 14 | char *filename; 15 | 16 | fcd = gtk_file_chooser_dialog_new(NULL, parent, mode, 17 | "_Cancel", GTK_RESPONSE_CANCEL, 18 | confirm, GTK_RESPONSE_ACCEPT, 19 | NULL); 20 | fc = GTK_FILE_CHOOSER(fcd); 21 | gtk_file_chooser_set_local_only(fc, FALSE); 22 | gtk_file_chooser_set_select_multiple(fc, FALSE); 23 | gtk_file_chooser_set_show_hidden(fc, TRUE); 24 | gtk_file_chooser_set_do_overwrite_confirmation(fc, TRUE); 25 | gtk_file_chooser_set_create_folders(fc, TRUE); 26 | response = gtk_dialog_run(GTK_DIALOG(fcd)); 27 | if (response != GTK_RESPONSE_ACCEPT) { 28 | gtk_widget_destroy(fcd); 29 | return NULL; 30 | } 31 | filename = uiUnixStrdupText(gtk_file_chooser_get_filename(fc)); 32 | gtk_widget_destroy(fcd); 33 | return filename; 34 | } 35 | 36 | char *uiOpenFile(uiWindow *parent) 37 | { 38 | return filedialog(windowWindow(parent), GTK_FILE_CHOOSER_ACTION_OPEN, "_Open"); 39 | } 40 | 41 | char *uiSaveFile(uiWindow *parent) 42 | { 43 | return filedialog(windowWindow(parent), GTK_FILE_CHOOSER_ACTION_SAVE, "_Save"); 44 | } 45 | 46 | static void msgbox(GtkWindow *parent, const char *title, const char *description, GtkMessageType type, GtkButtonsType buttons) 47 | { 48 | GtkWidget *md; 49 | 50 | md = gtk_message_dialog_new(parent, GTK_DIALOG_MODAL, 51 | type, buttons, 52 | "%s", title); 53 | gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(md), "%s", description); 54 | gtk_dialog_run(GTK_DIALOG(md)); 55 | gtk_widget_destroy(md); 56 | } 57 | 58 | void uiMsgBox(uiWindow *parent, const char *title, const char *description) 59 | { 60 | msgbox(windowWindow(parent), title, description, GTK_MESSAGE_OTHER, GTK_BUTTONS_OK); 61 | } 62 | 63 | void uiMsgBoxError(uiWindow *parent, const char *title, const char *description) 64 | { 65 | msgbox(windowWindow(parent), title, description, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK); 66 | } 67 | -------------------------------------------------------------------------------- /darwin/scrollview.m: -------------------------------------------------------------------------------- 1 | // 27 may 2016 2 | #include "uipriv_darwin.h" 3 | 4 | // see http://stackoverflow.com/questions/37979445/how-do-i-properly-set-up-a-scrolling-nstableview-using-auto-layout-what-ive-tr for why we don't use auto layout 5 | // TODO do the same with uiGroup and uiTab? 6 | 7 | struct uiprivScrollViewData { 8 | BOOL hscroll; 9 | BOOL vscroll; 10 | }; 11 | 12 | NSScrollView *uiprivMkScrollView(uiprivScrollViewCreateParams *p, uiprivScrollViewData **dout) 13 | { 14 | NSScrollView *sv; 15 | NSBorderType border; 16 | uiprivScrollViewData *d; 17 | 18 | sv = [[NSScrollView alloc] initWithFrame:NSZeroRect]; 19 | if (p->BackgroundColor != nil) 20 | [sv setBackgroundColor:p->BackgroundColor]; 21 | [sv setDrawsBackground:p->DrawsBackground]; 22 | border = NSNoBorder; 23 | if (p->Bordered) 24 | border = NSBezelBorder; 25 | // document view seems to set the cursor properly 26 | [sv setBorderType:border]; 27 | [sv setAutohidesScrollers:YES]; 28 | [sv setHasHorizontalRuler:NO]; 29 | [sv setHasVerticalRuler:NO]; 30 | [sv setRulersVisible:NO]; 31 | [sv setScrollerKnobStyle:NSScrollerKnobStyleDefault]; 32 | // the scroller style is documented as being set by default for us 33 | // LONGTERM verify line and page for programmatically created NSTableView 34 | [sv setScrollsDynamically:YES]; 35 | [sv setFindBarPosition:NSScrollViewFindBarPositionAboveContent]; 36 | [sv setUsesPredominantAxisScrolling:NO]; 37 | [sv setHorizontalScrollElasticity:NSScrollElasticityAutomatic]; 38 | [sv setVerticalScrollElasticity:NSScrollElasticityAutomatic]; 39 | [sv setAllowsMagnification:NO]; 40 | 41 | [sv setDocumentView:p->DocumentView]; 42 | d = uiprivNew(uiprivScrollViewData); 43 | uiprivScrollViewSetScrolling(sv, d, p->HScroll, p->VScroll); 44 | 45 | *dout = d; 46 | return sv; 47 | } 48 | 49 | // based on http://blog.bjhomer.com/2014/08/nsscrollview-and-autolayout.html because (as pointed out there) Apple's official guide is really only for iOS 50 | void uiprivScrollViewSetScrolling(NSScrollView *sv, uiprivScrollViewData *d, BOOL hscroll, BOOL vscroll) 51 | { 52 | d->hscroll = hscroll; 53 | [sv setHasHorizontalScroller:d->hscroll]; 54 | d->vscroll = vscroll; 55 | [sv setHasVerticalScroller:d->vscroll]; 56 | } 57 | 58 | void uiprivScrollViewFreeData(NSScrollView *sv, uiprivScrollViewData *d) 59 | { 60 | uiprivFree(d); 61 | } 62 | -------------------------------------------------------------------------------- /test/test.h: -------------------------------------------------------------------------------- 1 | // 22 april 2015 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include "../ui.h" 10 | 11 | // main.c 12 | extern void die(const char *, ...); 13 | extern uiBox *mainBox; 14 | extern uiTab *mainTab; 15 | extern uiBox *(*newhbox)(void); 16 | extern uiBox *(*newvbox)(void); 17 | 18 | // spaced.c 19 | extern void setSpaced(int); 20 | extern void querySpaced(char[12]); 21 | extern uiWindow *newWindow(const char *title, int width, int height, int hasMenubar); 22 | extern uiBox *newHorizontalBox(void); 23 | extern uiBox *newVerticalBox(void); 24 | extern uiTab *newTab(void); 25 | extern uiGroup *newGroup(const char *); 26 | extern uiForm *newForm(void); 27 | extern uiGrid *newGrid(void); 28 | 29 | // menus.c 30 | extern uiMenuItem *shouldQuitItem; 31 | extern void initMenus(void); 32 | 33 | // page1.c 34 | extern uiBox *page1; 35 | extern void makePage1(uiWindow *); 36 | 37 | // page2.c 38 | extern uiGroup *page2group; 39 | extern uiBox *makePage2(void); 40 | 41 | // page3.c 42 | extern uiBox *makePage3(void); 43 | 44 | // page4.c 45 | extern uiBox *makePage4(void); 46 | 47 | // page5.c 48 | extern uiBox *makePage5(uiWindow *); 49 | 50 | // page6.c 51 | extern uiBox *makePage6(void); 52 | 53 | // drawtests.c 54 | extern void runDrawTest(int, uiAreaDrawParams *); 55 | extern void populateComboboxWithTests(uiCombobox *); 56 | 57 | // page7.c 58 | extern uiBox *makePage7(void); 59 | 60 | // page7a.c 61 | extern uiGroup *makePage7a(void); 62 | 63 | // page7b.c 64 | extern uiGroup *makePage7b(void); 65 | 66 | // page7c.c 67 | extern uiGroup *makePage7c(void); 68 | 69 | // page8.c 70 | extern uiBox *makePage8(void); 71 | 72 | // page9.c 73 | extern uiBox *makePage9(void); 74 | 75 | // page10.c 76 | extern uiBox *makePage10(void); 77 | 78 | // page11.c 79 | extern uiBox *makePage11(void); 80 | 81 | // page12.c 82 | extern uiBox *makePage12(void); 83 | 84 | // page13.c 85 | extern uiBox *makePage13(void); 86 | 87 | // page14.c 88 | extern uiTab *makePage14(void); 89 | 90 | // page15.c 91 | extern uiBox *makePage15(uiWindow *); 92 | 93 | // page16.c 94 | extern uiBox *makePage16(void); 95 | extern void freePage16(void); 96 | 97 | // images.c 98 | extern void appendImageNamed(uiImage *img, const char *name); 99 | -------------------------------------------------------------------------------- /unix/alloc.c: -------------------------------------------------------------------------------- 1 | // 7 april 2015 2 | #include 3 | #include "uipriv_unix.h" 4 | 5 | static GPtrArray *allocations; 6 | 7 | #define UINT8(p) ((uint8_t *) (p)) 8 | #define PVOID(p) ((void *) (p)) 9 | #define EXTRA (sizeof (size_t) + sizeof (const char **)) 10 | #define DATA(p) PVOID(UINT8(p) + EXTRA) 11 | #define BASE(p) PVOID(UINT8(p) - EXTRA) 12 | #define SIZE(p) ((size_t *) (p)) 13 | #define CCHAR(p) ((const char **) (p)) 14 | #define TYPE(p) CCHAR(UINT8(p) + sizeof (size_t)) 15 | 16 | void uiprivInitAlloc(void) 17 | { 18 | allocations = g_ptr_array_new(); 19 | } 20 | 21 | static void uninitComplain(gpointer ptr, gpointer data) 22 | { 23 | char **str = (char **) data; 24 | char *str2; 25 | 26 | if (*str == NULL) 27 | *str = g_strdup_printf(""); 28 | str2 = g_strdup_printf("%s%p %s\n", *str, ptr, *TYPE(ptr)); 29 | g_free(*str); 30 | *str = str2; 31 | } 32 | 33 | void uiprivUninitAlloc(void) 34 | { 35 | char *str = NULL; 36 | 37 | if (allocations->len == 0) { 38 | g_ptr_array_free(allocations, TRUE); 39 | return; 40 | } 41 | g_ptr_array_foreach(allocations, uninitComplain, &str); 42 | uiprivUserBug("Some data was leaked; either you left a uiControl lying around or there's a bug in libui itself. Leaked data:\n%s", str); 43 | g_free(str); 44 | } 45 | 46 | void *uiprivAlloc(size_t size, const char *type) 47 | { 48 | void *out; 49 | 50 | out = g_malloc0(EXTRA + size); 51 | *SIZE(out) = size; 52 | *TYPE(out) = type; 53 | g_ptr_array_add(allocations, out); 54 | return DATA(out); 55 | } 56 | 57 | void *uiprivRealloc(void *p, size_t new, const char *type) 58 | { 59 | void *out; 60 | size_t *s; 61 | 62 | if (p == NULL) 63 | return uiprivAlloc(new, type); 64 | p = BASE(p); 65 | out = g_realloc(p, EXTRA + new); 66 | s = SIZE(out); 67 | if (new > *s) 68 | memset(((uint8_t *) DATA(out)) + *s, 0, new - *s); 69 | *s = new; 70 | if (g_ptr_array_remove(allocations, p) == FALSE) 71 | uiprivImplBug("%p not found in allocations array in uiprivRealloc()", p); 72 | g_ptr_array_add(allocations, out); 73 | return DATA(out); 74 | } 75 | 76 | void uiprivFree(void *p) 77 | { 78 | if (p == NULL) 79 | uiprivImplBug("attempt to uiprivFree(NULL)"); 80 | p = BASE(p); 81 | g_free(p); 82 | if (g_ptr_array_remove(allocations, p) == FALSE) 83 | uiprivImplBug("%p not found in allocations array in uiprivFree()", p); 84 | } 85 | -------------------------------------------------------------------------------- /common/tablevalue.c: -------------------------------------------------------------------------------- 1 | // 3 june 2018 2 | #include "../ui.h" 3 | #include "uipriv.h" 4 | #include "table.h" 5 | 6 | struct uiTableValue { 7 | uiTableValueType type; 8 | union { 9 | char *str; 10 | uiImage *img; 11 | int i; 12 | struct { 13 | double r; 14 | double g; 15 | double b; 16 | double a; 17 | } color; 18 | } u; 19 | }; 20 | 21 | static uiTableValue *newTableValue(uiTableValueType type) 22 | { 23 | uiTableValue *v; 24 | 25 | v = uiprivNew(uiTableValue); 26 | v->type = type; 27 | return v; 28 | } 29 | 30 | void uiFreeTableValue(uiTableValue *v) 31 | { 32 | switch (v->type) { 33 | case uiTableValueTypeString: 34 | uiprivFree(v->u.str); 35 | break; 36 | } 37 | uiprivFree(v); 38 | } 39 | 40 | uiTableValueType uiTableValueGetType(const uiTableValue *v) 41 | { 42 | return v->type; 43 | } 44 | 45 | uiTableValue *uiNewTableValueString(const char *str) 46 | { 47 | uiTableValue *v; 48 | 49 | v = newTableValue(uiTableValueTypeString); 50 | v->u.str = (char *) uiprivAlloc((strlen(str) + 1) * sizeof (char), "char[] (uiTableValue)"); 51 | strcpy(v->u.str, str); 52 | return v; 53 | } 54 | 55 | const char *uiTableValueString(const uiTableValue *v) 56 | { 57 | return v->u.str; 58 | } 59 | 60 | uiTableValue *uiNewTableValueImage(uiImage *img) 61 | { 62 | uiTableValue *v; 63 | 64 | v = newTableValue(uiTableValueTypeImage); 65 | v->u.img = img; 66 | return v; 67 | } 68 | 69 | uiImage *uiTableValueImage(const uiTableValue *v) 70 | { 71 | return v->u.img; 72 | } 73 | 74 | uiTableValue *uiNewTableValueInt(int i) 75 | { 76 | uiTableValue *v; 77 | 78 | v = newTableValue(uiTableValueTypeInt); 79 | v->u.i = i; 80 | return v; 81 | } 82 | 83 | int uiTableValueInt(const uiTableValue *v) 84 | { 85 | return v->u.i; 86 | } 87 | 88 | uiTableValue *uiNewTableValueColor(double r, double g, double b, double a) 89 | { 90 | uiTableValue *v; 91 | 92 | v = newTableValue(uiTableValueTypeColor); 93 | v->u.color.r = r; 94 | v->u.color.g = g; 95 | v->u.color.b = b; 96 | v->u.color.a = a; 97 | return v; 98 | } 99 | 100 | void uiTableValueColor(const uiTableValue *v, double *r, double *g, double *b, double *a) 101 | { 102 | *r = v->u.color.r; 103 | *g = v->u.color.g; 104 | *b = v->u.color.b; 105 | *a = v->u.color.a; 106 | } 107 | -------------------------------------------------------------------------------- /test/images/gen.go: -------------------------------------------------------------------------------- 1 | // 25 june 2016 2 | package main 3 | 4 | import ( 5 | "fmt" 6 | "os" 7 | "image" 8 | "image/draw" 9 | _ "image/png" 10 | ) 11 | 12 | type img struct { 13 | filename string 14 | data []byte 15 | width int 16 | height int 17 | stride int 18 | } 19 | 20 | func main() { 21 | if len(os.Args[1:]) == 0 { 22 | panic("no files specified") 23 | } 24 | 25 | images := make([]*img, 0, len(os.Args[1:])) 26 | for _, fn := range os.Args[1:] { 27 | f, err := os.Open(fn) 28 | if err != nil { 29 | panic(err) 30 | } 31 | ii, _, err := image.Decode(f) 32 | if err != nil { 33 | panic(err) 34 | } 35 | f.Close() 36 | 37 | i := image.NewRGBA(ii.Bounds()) 38 | draw.Draw(i, i.Rect, ii, ii.Bounds().Min, draw.Src) 39 | 40 | im := &img{ 41 | filename: fn, 42 | data: i.Pix, 43 | width: i.Rect.Dx(), 44 | height: i.Rect.Dy(), 45 | stride: i.Stride, 46 | } 47 | images = append(images, im) 48 | } 49 | 50 | fmt.Println("// auto-generated by images/gen.go") 51 | fmt.Println("#include \"test.h\"") 52 | fmt.Println() 53 | for i, im := range images { 54 | fmt.Printf("static const uint8_t dat%d[] = {", i) 55 | for j := 0; j < len(im.data); j++ { 56 | if (j % 16) == 0 { 57 | fmt.Printf("\n\t") 58 | } else { 59 | fmt.Printf(" ") 60 | } 61 | fmt.Printf("0x%02X,", im.data[j]) 62 | 63 | } 64 | fmt.Println("\n};") 65 | fmt.Println() 66 | } 67 | fmt.Println("static const struct {") 68 | fmt.Println(" const char *name;") 69 | fmt.Println(" void *data;") 70 | fmt.Println(" int width;") 71 | fmt.Println(" int height;") 72 | fmt.Println(" int stride;") 73 | fmt.Println("} files[] = {") 74 | for i, im := range images { 75 | fmt.Printf(" { %q, dat%d, %d, %d, %d },\n", 76 | im.filename, i, im.width, im.height, im.stride) 77 | } 78 | fmt.Println("};") 79 | fmt.Println() 80 | fmt.Println("void appendImageNamed(uiImage *img, const char *name)") 81 | fmt.Println("{") 82 | fmt.Println(" int i;") 83 | fmt.Println("") 84 | fmt.Println(" i = 0;") 85 | fmt.Println(" for (;;) {") 86 | fmt.Println(" if (strcmp(name, files[i].name) == 0) {") 87 | fmt.Println(" uiImageAppend(img, files[i].data, files[i].width, files[i].height, files[i].stride);") 88 | fmt.Println(" return;") 89 | fmt.Println(" }") 90 | fmt.Println(" i++;") 91 | fmt.Println(" }") 92 | fmt.Println("}") 93 | fmt.Println() 94 | } 95 | -------------------------------------------------------------------------------- /unix/editablecombo.c: -------------------------------------------------------------------------------- 1 | // 11 june 2015 2 | #include "uipriv_unix.h" 3 | 4 | struct uiEditableCombobox { 5 | uiUnixControl c; 6 | GtkWidget *widget; 7 | GtkBin *bin; 8 | GtkComboBox *combobox; 9 | GtkComboBoxText *comboboxText; 10 | void (*onChanged)(uiEditableCombobox *, void *); 11 | void *onChangedData; 12 | gulong onChangedSignal; 13 | }; 14 | 15 | uiUnixControlAllDefaults(uiEditableCombobox) 16 | 17 | static void onChanged(GtkComboBox *cbox, gpointer data) 18 | { 19 | uiEditableCombobox *c = uiEditableCombobox(data); 20 | 21 | (*(c->onChanged))(c, c->onChangedData); 22 | } 23 | 24 | static void defaultOnChanged(uiEditableCombobox *c, void *data) 25 | { 26 | // do nothing 27 | } 28 | 29 | void uiEditableComboboxAppend(uiEditableCombobox *c, const char *text) 30 | { 31 | gtk_combo_box_text_append(c->comboboxText, NULL, text); 32 | } 33 | 34 | char *uiEditableComboboxText(uiEditableCombobox *c) 35 | { 36 | char *s; 37 | char *out; 38 | 39 | s = gtk_combo_box_text_get_active_text(c->comboboxText); 40 | // s will always be non-NULL in the case of a combobox with an entry (according to the source code) 41 | out = uiUnixStrdupText(s); 42 | g_free(s); 43 | return out; 44 | } 45 | 46 | void uiEditableComboboxSetText(uiEditableCombobox *c, const char *text) 47 | { 48 | GtkEntry *e; 49 | 50 | // we need to inhibit sending of ::changed because this WILL send a ::changed otherwise 51 | g_signal_handler_block(c->combobox, c->onChangedSignal); 52 | // since there isn't a gtk_combo_box_text_set_active_text()... 53 | e = GTK_ENTRY(gtk_bin_get_child(c->bin)); 54 | gtk_entry_set_text(e, text); 55 | g_signal_handler_unblock(c->combobox, c->onChangedSignal); 56 | } 57 | 58 | void uiEditableComboboxOnChanged(uiEditableCombobox *c, void (*f)(uiEditableCombobox *c, void *data), void *data) 59 | { 60 | c->onChanged = f; 61 | c->onChangedData = data; 62 | } 63 | 64 | uiEditableCombobox *uiNewEditableCombobox(void) 65 | { 66 | uiEditableCombobox *c; 67 | 68 | uiUnixNewControl(uiEditableCombobox, c); 69 | 70 | c->widget = gtk_combo_box_text_new_with_entry(); 71 | c->bin = GTK_BIN(c->widget); 72 | c->combobox = GTK_COMBO_BOX(c->widget); 73 | c->comboboxText = GTK_COMBO_BOX_TEXT(c->widget); 74 | 75 | c->onChangedSignal = g_signal_connect(c->widget, "changed", G_CALLBACK(onChanged), c); 76 | uiEditableComboboxOnChanged(c, defaultOnChanged, NULL); 77 | 78 | return c; 79 | } 80 | -------------------------------------------------------------------------------- /_wip/table/unix_table.c: -------------------------------------------------------------------------------- 1 | // 18 october 2015 2 | #include "uipriv_unix.h" 3 | 4 | struct uiTable { 5 | uiUnixControl c; 6 | GtkWidget *widget; 7 | GtkContainer *scontainer; 8 | GtkScrolledWindow *sw; 9 | GtkWidget *treeWidget; 10 | GtkTreeView *treeview; 11 | GtkTreeSelection *selection; 12 | uiTableModel *model; 13 | }; 14 | 15 | uiUnixDefineControl( 16 | uiTable // type name 17 | ) 18 | 19 | void uiTableSetModel(uiTable *t, uiTableModel *m) 20 | { 21 | t->model = m; 22 | gtk_tree_view_set_model(t->treeview, GTK_TREE_MODEL(t->model)); 23 | } 24 | 25 | void uiTableAppendColumn(uiTable *t, uiTableColumnParams *p) 26 | { 27 | GtkTreeViewColumn *col; 28 | GtkCellRenderer *r; 29 | const char *attribute; 30 | const char *mutableAttr; 31 | gboolean mutable; 32 | 33 | switch (p->Type) { 34 | case uiTableColumnText: 35 | r = gtk_cell_renderer_text_new(); 36 | attribute = "text"; 37 | mutableAttr = "editable"; 38 | break; 39 | //TODO case uiTableColumnImage: 40 | // TODO 41 | case uiTableColumnCheckbox: 42 | r = gtk_cell_renderer_toggle_new(); 43 | attribute = "active"; 44 | mutableAttr = "activatable"; 45 | break; 46 | default: 47 | complain("unknown table column type %d in uiTableAppendColumn()", p->Type); 48 | } 49 | mutable = FALSE; 50 | if (p->Mutable) 51 | mutable = TRUE; 52 | g_object_set(r, 53 | mutableAttr, mutable, 54 | NULL); 55 | col = gtk_tree_view_column_new_with_attributes(p->Name, r, 56 | attribute, p->ValueColumn, 57 | NULL); 58 | // allow columns to be resized 59 | gtk_tree_view_column_set_resizable(col, TRUE); 60 | gtk_tree_view_append_column(t->treeview, col); 61 | } 62 | 63 | uiTable *uiNewTable(void) 64 | { 65 | uiTable *t; 66 | 67 | t = (uiTable *) uiNewControl(uiTableType()); 68 | 69 | t->widget = gtk_scrolled_window_new(NULL, NULL); 70 | t->scontainer = GTK_CONTAINER(t->widget); 71 | t->sw = GTK_SCROLLED_WINDOW(t->widget); 72 | 73 | t->treeWidget = gtk_tree_view_new(); 74 | t->treeview = GTK_TREE_VIEW(t->treeWidget); 75 | 76 | t->selection = gtk_tree_view_get_selection(t->treeview); 77 | 78 | // give a border and add the table 79 | gtk_scrolled_window_set_shadow_type(t->sw, GTK_SHADOW_IN); 80 | gtk_container_add(t->scontainer, t->treeWidget); 81 | // and make the table visible; only the scrolled window's visibility is controlled by libui 82 | gtk_widget_show(t->treeWidget); 83 | 84 | uiUnixFinishNewControl(t, uiTable); 85 | 86 | return t; 87 | } 88 | -------------------------------------------------------------------------------- /darwin/alloc.m: -------------------------------------------------------------------------------- 1 | // 4 december 2014 2 | #import 3 | #import "uipriv_darwin.h" 4 | 5 | static NSMutableArray *allocations; 6 | NSMutableArray *uiprivDelegates; 7 | 8 | void uiprivInitAlloc(void) 9 | { 10 | allocations = [NSMutableArray new]; 11 | uiprivDelegates = [NSMutableArray new]; 12 | } 13 | 14 | #define UINT8(p) ((uint8_t *) (p)) 15 | #define PVOID(p) ((void *) (p)) 16 | #define EXTRA (sizeof (size_t) + sizeof (const char **)) 17 | #define DATA(p) PVOID(UINT8(p) + EXTRA) 18 | #define BASE(p) PVOID(UINT8(p) - EXTRA) 19 | #define SIZE(p) ((size_t *) (p)) 20 | #define CCHAR(p) ((const char **) (p)) 21 | #define TYPE(p) CCHAR(UINT8(p) + sizeof (size_t)) 22 | 23 | void uiprivUninitAlloc(void) 24 | { 25 | NSMutableString *str; 26 | NSValue *v; 27 | 28 | [uiprivDelegates release]; 29 | if ([allocations count] == 0) { 30 | [allocations release]; 31 | return; 32 | } 33 | str = [NSMutableString new]; 34 | for (v in allocations) { 35 | void *ptr; 36 | 37 | ptr = [v pointerValue]; 38 | [str appendString:[NSString stringWithFormat:@"%p %s\n", ptr, *TYPE(ptr)]]; 39 | } 40 | uiprivUserBug("Some data was leaked; either you left a uiControl lying around or there's a bug in libui itself. Leaked data:\n%s", [str UTF8String]); 41 | [str release]; 42 | } 43 | 44 | void *uiprivAlloc(size_t size, const char *type) 45 | { 46 | void *out; 47 | 48 | out = malloc(EXTRA + size); 49 | if (out == NULL) { 50 | fprintf(stderr, "memory exhausted in uiAlloc()\n"); 51 | abort(); 52 | } 53 | memset(DATA(out), 0, size); 54 | *SIZE(out) = size; 55 | *TYPE(out) = type; 56 | [allocations addObject:[NSValue valueWithPointer:out]]; 57 | return DATA(out); 58 | } 59 | 60 | void *uiprivRealloc(void *p, size_t new, const char *type) 61 | { 62 | void *out; 63 | size_t *s; 64 | 65 | if (p == NULL) 66 | return uiprivAlloc(new, type); 67 | p = BASE(p); 68 | out = realloc(p, EXTRA + new); 69 | if (out == NULL) { 70 | fprintf(stderr, "memory exhausted in uiprivRealloc()\n"); 71 | abort(); 72 | } 73 | s = SIZE(out); 74 | if (new > *s) 75 | memset(((uint8_t *) DATA(out)) + *s, 0, new - *s); 76 | *s = new; 77 | [allocations removeObject:[NSValue valueWithPointer:p]]; 78 | [allocations addObject:[NSValue valueWithPointer:out]]; 79 | return DATA(out); 80 | } 81 | 82 | void uiprivFree(void *p) 83 | { 84 | if (p == NULL) 85 | uiprivImplBug("attempt to uiprivFree(NULL)"); 86 | p = BASE(p); 87 | free(p); 88 | [allocations removeObject:[NSValue valueWithPointer:p]]; 89 | } 90 | -------------------------------------------------------------------------------- /unix/uipriv_unix.h: -------------------------------------------------------------------------------- 1 | // 22 april 2015 2 | #define GLIB_VERSION_MIN_REQUIRED GLIB_VERSION_2_40 3 | #define GLIB_VERSION_MAX_ALLOWED GLIB_VERSION_2_40 4 | #define GDK_VERSION_MIN_REQUIRED GDK_VERSION_3_10 5 | #define GDK_VERSION_MAX_ALLOWED GDK_VERSION_3_10 6 | #include 7 | #include 8 | #include // see future.c 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include "../ui.h" 14 | #include "../ui_unix.h" 15 | #include "../common/uipriv.h" 16 | 17 | #define uiprivGTKXMargin 12 18 | #define uiprivGTKYMargin 12 19 | #define uiprivGTKXPadding 12 20 | #define uiprivGTKYPadding 6 21 | 22 | // menu.c 23 | extern GtkWidget *uiprivMakeMenubar(uiWindow *); 24 | extern void uiprivFreeMenubar(GtkWidget *); 25 | extern void uiprivUninitMenus(void); 26 | 27 | // alloc.c 28 | extern void uiprivInitAlloc(void); 29 | extern void uiprivUninitAlloc(void); 30 | 31 | // util.c 32 | extern void uiprivSetMargined(GtkContainer *, int); 33 | 34 | // child.c 35 | typedef struct uiprivChild uiprivChild; 36 | extern uiprivChild *uiprivNewChild(uiControl *child, uiControl *parent, GtkContainer *parentContainer); 37 | extern uiprivChild *uiprivNewChildWithBox(uiControl *child, uiControl *parent, GtkContainer *parentContainer, int margined); 38 | extern void uiprivChildRemove(uiprivChild *c); 39 | extern void uiprivChildDestroy(uiprivChild *c); 40 | extern GtkWidget *uiprivChildWidget(uiprivChild *c); 41 | extern int uiprivChildFlag(uiprivChild *c); 42 | extern void uiprivChildSetFlag(uiprivChild *c, int flag); 43 | extern GtkWidget *uiprivChildBox(uiprivChild *c); 44 | extern void uiprivChildSetMargined(uiprivChild *c, int margined); 45 | 46 | // draw.c 47 | extern uiDrawContext *uiprivNewContext(cairo_t *cr, GtkStyleContext *style); 48 | extern void uiprivFreeContext(uiDrawContext *); 49 | 50 | // image.c 51 | extern cairo_surface_t *uiprivImageAppropriateSurface(uiImage *i, GtkWidget *w); 52 | 53 | // cellrendererbutton.c 54 | extern GtkCellRenderer *uiprivNewCellRendererButton(void); 55 | 56 | // future.c 57 | extern void uiprivLoadFutures(void); 58 | extern PangoAttribute *uiprivFUTURE_pango_attr_font_features_new(const gchar *features); 59 | extern PangoAttribute *uiprivFUTURE_pango_attr_foreground_alpha_new(guint16 alpha); 60 | extern PangoAttribute *uiprivFUTURE_pango_attr_background_alpha_new(guint16 alpha); 61 | extern gboolean uiprivFUTURE_gtk_widget_path_iter_set_object_name(GtkWidgetPath *path, gint pos, const char *name); 62 | -------------------------------------------------------------------------------- /unix/tab.c: -------------------------------------------------------------------------------- 1 | // 11 june 2015 2 | #include "uipriv_unix.h" 3 | 4 | struct uiTab { 5 | uiUnixControl c; 6 | 7 | GtkWidget *widget; 8 | GtkContainer *container; 9 | GtkNotebook *notebook; 10 | 11 | GArray *pages; // []*uiprivChild 12 | }; 13 | 14 | uiUnixControlAllDefaultsExceptDestroy(uiTab) 15 | 16 | static void uiTabDestroy(uiControl *c) 17 | { 18 | uiTab *t = uiTab(c); 19 | guint i; 20 | uiprivChild *page; 21 | 22 | for (i = 0; i < t->pages->len; i++) { 23 | page = g_array_index(t->pages, uiprivChild *, i); 24 | uiprivChildDestroy(page); 25 | } 26 | g_array_free(t->pages, TRUE); 27 | // and free ourselves 28 | g_object_unref(t->widget); 29 | uiFreeControl(uiControl(t)); 30 | } 31 | 32 | void uiTabAppend(uiTab *t, const char *name, uiControl *child) 33 | { 34 | uiTabInsertAt(t, name, t->pages->len, child); 35 | } 36 | 37 | void uiTabInsertAt(uiTab *t, const char *name, int n, uiControl *child) 38 | { 39 | uiprivChild *page; 40 | 41 | // this will create a tab, because of gtk_container_add() 42 | page = uiprivNewChildWithBox(child, uiControl(t), t->container, 0); 43 | 44 | gtk_notebook_set_tab_label_text(t->notebook, uiprivChildBox(page), name); 45 | gtk_notebook_reorder_child(t->notebook, uiprivChildBox(page), n); 46 | 47 | g_array_insert_val(t->pages, n, page); 48 | } 49 | 50 | void uiTabDelete(uiTab *t, int n) 51 | { 52 | uiprivChild *page; 53 | 54 | page = g_array_index(t->pages, uiprivChild *, n); 55 | // this will remove the tab, because gtk_widget_destroy() calls gtk_container_remove() 56 | uiprivChildRemove(page); 57 | g_array_remove_index(t->pages, n); 58 | } 59 | 60 | int uiTabNumPages(uiTab *t) 61 | { 62 | return t->pages->len; 63 | } 64 | 65 | int uiTabMargined(uiTab *t, int n) 66 | { 67 | uiprivChild *page; 68 | 69 | page = g_array_index(t->pages, uiprivChild *, n); 70 | return uiprivChildFlag(page); 71 | } 72 | 73 | void uiTabSetMargined(uiTab *t, int n, int margined) 74 | { 75 | uiprivChild *page; 76 | 77 | page = g_array_index(t->pages, uiprivChild *, n); 78 | uiprivChildSetFlag(page, margined); 79 | uiprivChildSetMargined(page, uiprivChildFlag(page)); 80 | } 81 | 82 | uiTab *uiNewTab(void) 83 | { 84 | uiTab *t; 85 | 86 | uiUnixNewControl(uiTab, t); 87 | 88 | t->widget = gtk_notebook_new(); 89 | t->container = GTK_CONTAINER(t->widget); 90 | t->notebook = GTK_NOTEBOOK(t->widget); 91 | 92 | gtk_notebook_set_scrollable(t->notebook, TRUE); 93 | 94 | t->pages = g_array_new(FALSE, TRUE, sizeof (uiprivChild *)); 95 | 96 | return t; 97 | } 98 | -------------------------------------------------------------------------------- /test/page5.c: -------------------------------------------------------------------------------- 1 | // 22 may 2015 2 | #include "test.h" 3 | 4 | static uiWindow *parent; 5 | 6 | static void openFile(uiButton *b, void *data) 7 | { 8 | char *fn; 9 | 10 | fn = uiOpenFile(parent); 11 | if (fn == NULL) 12 | uiLabelSetText(uiLabel(data), "(cancelled)"); 13 | else { 14 | uiLabelSetText(uiLabel(data), fn); 15 | uiFreeText(fn); 16 | } 17 | } 18 | 19 | static void saveFile(uiButton *b, void *data) 20 | { 21 | char *fn; 22 | 23 | fn = uiSaveFile(parent); 24 | if (fn == NULL) 25 | uiLabelSetText(uiLabel(data), "(cancelled)"); 26 | else { 27 | uiLabelSetText(uiLabel(data), fn); 28 | uiFreeText(fn); 29 | } 30 | } 31 | 32 | static uiEntry *title, *description; 33 | 34 | static void msgBox(uiButton *b, void *data) 35 | { 36 | char *t, *d; 37 | 38 | t = uiEntryText(title); 39 | d = uiEntryText(description); 40 | uiMsgBox(parent, t, d); 41 | uiFreeText(d); 42 | uiFreeText(t); 43 | } 44 | 45 | static void msgBoxError(uiButton *b, void *data) 46 | { 47 | char *t, *d; 48 | 49 | t = uiEntryText(title); 50 | d = uiEntryText(description); 51 | uiMsgBoxError(parent, t, d); 52 | uiFreeText(d); 53 | uiFreeText(t); 54 | } 55 | 56 | uiBox *makePage5(uiWindow *pw) 57 | { 58 | uiBox *page5; 59 | uiBox *hbox; 60 | uiButton *button; 61 | uiLabel *label; 62 | 63 | parent = pw; 64 | 65 | page5 = newVerticalBox(); 66 | 67 | #define D(n, f) \ 68 | hbox = newHorizontalBox(); \ 69 | button = uiNewButton(n); \ 70 | label = uiNewLabel(""); \ 71 | uiButtonOnClicked(button, f, label); \ 72 | uiBoxAppend(hbox, uiControl(button), 0); \ 73 | uiBoxAppend(hbox, uiControl(label), 0); \ 74 | uiBoxAppend(page5, uiControl(hbox), 0); 75 | 76 | D("Open File", openFile); 77 | D("Save File", saveFile); 78 | 79 | title = uiNewEntry(); 80 | uiEntrySetText(title, "Title"); 81 | description = uiNewEntry(); 82 | uiEntrySetText(description, "Description"); 83 | 84 | hbox = newHorizontalBox(); 85 | button = uiNewButton("Message Box"); 86 | uiButtonOnClicked(button, msgBox, NULL); 87 | uiBoxAppend(hbox, uiControl(button), 0); 88 | uiBoxAppend(hbox, uiControl(title), 0); 89 | uiBoxAppend(page5, uiControl(hbox), 0); 90 | 91 | hbox = newHorizontalBox(); 92 | button = uiNewButton("Error Box"); 93 | uiButtonOnClicked(button, msgBoxError, NULL); 94 | uiBoxAppend(hbox, uiControl(button), 0); 95 | uiBoxAppend(hbox, uiControl(description), 0); 96 | uiBoxAppend(page5, uiControl(hbox), 0); 97 | 98 | return page5; 99 | } 100 | -------------------------------------------------------------------------------- /unix/entry.c: -------------------------------------------------------------------------------- 1 | // 11 june 2015 2 | #include "uipriv_unix.h" 3 | 4 | struct uiEntry { 5 | uiUnixControl c; 6 | GtkWidget *widget; 7 | GtkEntry *entry; 8 | GtkEditable *editable; 9 | void (*onChanged)(uiEntry *, void *); 10 | void *onChangedData; 11 | gulong onChangedSignal; 12 | }; 13 | 14 | uiUnixControlAllDefaults(uiEntry) 15 | 16 | static void onChanged(GtkEditable *editable, gpointer data) 17 | { 18 | uiEntry *e = uiEntry(data); 19 | 20 | (*(e->onChanged))(e, e->onChangedData); 21 | } 22 | 23 | static void defaultOnChanged(uiEntry *e, void *data) 24 | { 25 | // do nothing 26 | } 27 | 28 | char *uiEntryText(uiEntry *e) 29 | { 30 | return uiUnixStrdupText(gtk_entry_get_text(e->entry)); 31 | } 32 | 33 | void uiEntrySetText(uiEntry *e, const char *text) 34 | { 35 | // we need to inhibit sending of ::changed because this WILL send a ::changed otherwise 36 | g_signal_handler_block(e->editable, e->onChangedSignal); 37 | gtk_entry_set_text(e->entry, text); 38 | g_signal_handler_unblock(e->editable, e->onChangedSignal); 39 | // don't queue the control for resize; entry sizes are independent of their contents 40 | } 41 | 42 | void uiEntryOnChanged(uiEntry *e, void (*f)(uiEntry *, void *), void *data) 43 | { 44 | e->onChanged = f; 45 | e->onChangedData = data; 46 | } 47 | 48 | int uiEntryReadOnly(uiEntry *e) 49 | { 50 | return gtk_editable_get_editable(e->editable) == FALSE; 51 | } 52 | 53 | void uiEntrySetReadOnly(uiEntry *e, int readonly) 54 | { 55 | gboolean editable; 56 | 57 | editable = TRUE; 58 | if (readonly) 59 | editable = FALSE; 60 | gtk_editable_set_editable(e->editable, editable); 61 | } 62 | 63 | static uiEntry *finishNewEntry(GtkWidget *w, const gchar *signal) 64 | { 65 | uiEntry *e; 66 | 67 | uiUnixNewControl(uiEntry, e); 68 | 69 | e->widget = w; 70 | e->entry = GTK_ENTRY(e->widget); 71 | e->editable = GTK_EDITABLE(e->widget); 72 | 73 | e->onChangedSignal = g_signal_connect(e->widget, signal, G_CALLBACK(onChanged), e); 74 | uiEntryOnChanged(e, defaultOnChanged, NULL); 75 | 76 | return e; 77 | } 78 | 79 | uiEntry *uiNewEntry(void) 80 | { 81 | return finishNewEntry(gtk_entry_new(), "changed"); 82 | } 83 | 84 | uiEntry *uiNewPasswordEntry(void) 85 | { 86 | GtkWidget *e; 87 | 88 | e = gtk_entry_new(); 89 | gtk_entry_set_visibility(GTK_ENTRY(e), FALSE); 90 | return finishNewEntry(e, "changed"); 91 | } 92 | 93 | // TODO make it use a separate function to be type-safe 94 | uiEntry *uiNewSearchEntry(void) 95 | { 96 | return finishNewEntry(gtk_search_entry_new(), "search-changed"); 97 | } 98 | -------------------------------------------------------------------------------- /common/control.c: -------------------------------------------------------------------------------- 1 | // 26 may 2015 2 | #include "../ui.h" 3 | #include "uipriv.h" 4 | 5 | void uiControlDestroy(uiControl *c) 6 | { 7 | (*(c->Destroy))(c); 8 | } 9 | 10 | uintptr_t uiControlHandle(uiControl *c) 11 | { 12 | return (*(c->Handle))(c); 13 | } 14 | 15 | uiControl *uiControlParent(uiControl *c) 16 | { 17 | return (*(c->Parent))(c); 18 | } 19 | 20 | void uiControlSetParent(uiControl *c, uiControl *parent) 21 | { 22 | (*(c->SetParent))(c, parent); 23 | } 24 | 25 | int uiControlToplevel(uiControl *c) 26 | { 27 | return (*(c->Toplevel))(c); 28 | } 29 | 30 | int uiControlVisible(uiControl *c) 31 | { 32 | return (*(c->Visible))(c); 33 | } 34 | 35 | void uiControlShow(uiControl *c) 36 | { 37 | (*(c->Show))(c); 38 | } 39 | 40 | void uiControlHide(uiControl *c) 41 | { 42 | (*(c->Hide))(c); 43 | } 44 | 45 | int uiControlEnabled(uiControl *c) 46 | { 47 | return (*(c->Enabled))(c); 48 | } 49 | 50 | void uiControlEnable(uiControl *c) 51 | { 52 | (*(c->Enable))(c); 53 | } 54 | 55 | void uiControlDisable(uiControl *c) 56 | { 57 | (*(c->Disable))(c); 58 | } 59 | 60 | #define uiprivControlSignature 0x7569436F 61 | 62 | uiControl *uiAllocControl(size_t size, uint32_t OSsig, uint32_t typesig, const char *typenamestr) 63 | { 64 | uiControl *c; 65 | 66 | c = (uiControl *) uiprivAlloc(size, typenamestr); 67 | c->Signature = uiprivControlSignature; 68 | c->OSSignature = OSsig; 69 | c->TypeSignature = typesig; 70 | return c; 71 | } 72 | 73 | void uiFreeControl(uiControl *c) 74 | { 75 | if (uiControlParent(c) != NULL) 76 | uiprivUserBug("You cannot destroy a uiControl while it still has a parent. (control: %p)", c); 77 | uiprivFree(c); 78 | } 79 | 80 | void uiControlVerifySetParent(uiControl *c, uiControl *parent) 81 | { 82 | uiControl *curParent; 83 | 84 | if (uiControlToplevel(c)) 85 | uiprivUserBug("You cannot give a toplevel uiControl a parent. (control: %p)", c); 86 | curParent = uiControlParent(c); 87 | if (parent != NULL && curParent != NULL) 88 | uiprivUserBug("You cannot give a uiControl a parent while it already has one. (control: %p; current parent: %p; new parent: %p)", c, curParent, parent); 89 | if (parent == NULL && curParent == NULL) 90 | uiprivImplBug("attempt to double unparent uiControl %p", c); 91 | } 92 | 93 | int uiControlEnabledToUser(uiControl *c) 94 | { 95 | while (c != NULL) { 96 | if (!uiControlEnabled(c)) 97 | return 0; 98 | c = uiControlParent(c); 99 | } 100 | return 1; 101 | } 102 | --------------------------------------------------------------------------------