{"id":48604014,"url":"https://github.com/ericoulashin/cxwidgets","last_synced_at":"2026-04-13T19:01:04.935Z","repository":{"id":332282701,"uuid":"1133016103","full_name":"EricOulashin/cxWidgets","owner":"EricOulashin","description":"An object-oriented text user interface library (based on nCurses) for Linux, MacOS, BSD, AIX, and Windows written in C++ (the Windows version uses PDCurses)","archived":false,"fork":false,"pushed_at":"2026-04-02T03:28:53.000Z","size":92374,"stargazers_count":0,"open_issues_count":0,"forks_count":1,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-08T23:32:40.698Z","etag":null,"topics":["bsd","chui","cpp","library","linux","macosx","ncurses","ncurses-tui","tui","unix","wrapper-library"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/EricOulashin.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-01-12T19:06:47.000Z","updated_at":"2026-04-02T03:28:57.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/EricOulashin/cxWidgets","commit_stats":null,"previous_names":["ericoulashin/cxwidgets"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/EricOulashin/cxWidgets","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EricOulashin%2FcxWidgets","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EricOulashin%2FcxWidgets/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EricOulashin%2FcxWidgets/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EricOulashin%2FcxWidgets/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/EricOulashin","download_url":"https://codeload.github.com/EricOulashin/cxWidgets/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EricOulashin%2FcxWidgets/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31766482,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-13T15:25:13.801Z","status":"ssl_error","status_checked_at":"2026-04-13T15:25:09.162Z","response_time":93,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bsd","chui","cpp","library","linux","macosx","ncurses","ncurses-tui","tui","unix","wrapper-library"],"created_at":"2026-04-08T23:09:20.100Z","updated_at":"2026-04-13T19:01:04.912Z","avatar_url":"https://github.com/EricOulashin.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# cxWidgets\nThis is an object-oriented text user interface library for Linux, macOS, and Windows written in C++.  This is intended for\nthose developing a text terminal-based software application in C++.\n\nThis is a wrapper around \u003ca href='https://invisible-island.net/ncurses/' target='_blank'\u003enCurses\u003c/a\u003e; thus,\nthis library requires the package libncurses-dev to be installed, and any software that uses this (and\nthus, nCurses) requires the package ncurses-bin and related packages to be installed.\n\nThis library contains C++ classes for text-based UI elements such as a button, text input, multi-line text\ninput, combo box, dialog, form, menu, file viewer, frame, panel, etc.  All the UI element classes\nderive from a parent class, cxWindow, to provide abstraction \u0026 re-use of general functions contained\nwithin cxWindow; another advantage is polymorphism - if you need a function that would work with any\ncxWindow (regardless of whether it's a cxWindow or a subtype), you could pass a cxWindow pointer or\nreference to that function.\n\ncxWindow drives from cxObject, which has a few fairly general methods in it.\n\nThere is a namespace called cxBase that contains some general utility functions.\n\nYou can click \u003ca href='uml/cxWidgets_class_diagram.png' target='_blank'\u003ehere\u003c/a\u003e to see a (generated)\nUML diagram showing the cxWidgets class heirarchy.  Note that in the 'callbacks' section, classes\nnot depicted include templated cxFunction classes that allow for strongly-typed functions. These\nfunctions are used as event functions for on-load, on-leave, keypresses, etc. The class diagram was\ngenerated by \u003ca href='https://graphviz.org/doc/info/command.html' target='_blank'\u003edot\u003c/a\u003e, which is\npart of \u003ca href='https://graphviz.org' target='_blank'\u003eGraphviz\u003c/a\u003e (open-source graph visualization\nsoftware). In the uml directory, there are also the files cxWidgets_classes.dot and cxWidgets_classes.puml\nfor use with the dot utility. Also, the genUMLDiagram.sh script in the cxWidgets directory can be run\nto re-generate the UML class diagram.\u003cbr/\u003e\n\u003ccenter\u003e\n\u003ca href='uml/cxWidgets_class_diagram.png' target='_blank'\u003e\u003cimg src=\"uml/cxWidgets_class_diagram.png\" alt=\"cxWidgets class diagram (UML)\" width=\"800\"\u003e\u003c/a\u003e\n\u003c/center\u003e\n\nIn addition to the class library, there are also test tools:\n\u003cul\u003e\n\u003cli\u003e\u003cb\u003etestApp:\u003c/b\u003e An application for manually testing various cxWidgets components. See testApp.cpp. This will build to the executable testApp.\n\u003cli\u003e\u003cb\u003ecxUnitTest:\u003c/b\u003e Automated unit tests. See cxUnitTest.cpp. This builds to the executable cxUnitTest; however, this is incomplete.\n\u003c/ul\u003e\n\nThere are \u003ca href='https://www.doxygen.nl' target='_blank'\u003eDoxygen\u003c/a\u003e comments in the source in order to provide\ndocumentation; there is also a Doxyfile available for building Doxygen-based documentation.\n\u003ca href='https://ericoulashin.github.io/cxWidgets/html/index.html' target='_blank'\u003eHTML documentation\u003c/a\u003e\nfor the C++ code has been added in the \u003ca href='docs/html' target='_blank'\u003edocs/html directory\u003c/a\u003e.  If you want\nto generate documentation, you can simply run 'doxygen' from the cxWidgets directory, and it will\noutput documentation into the 'docs' directory.\n\nThere is also a KDevelop project file available if you wish to use KDevelop.\n\nI worked on this library from 2005 to 2007 while working at a startup company called Red Ace Solutions\n(which no longer exists).  I worked on the majority of this library, together with Mike Kinney (the owner\nof Red Ace Solutions) as well as Glen Thorne.  We developed this library on Fedora Linux.\n\nI have recently modernized the code a bit to be more up to date with C++17, including:\n\u003cul\u003e\n\u003cli\u003eUsing \u003ca href='https://en.cppreference.com/w/cpp/memory/shared_ptr.html' target='_blank'\u003estd::shared_ptr\u003c/a\u003e and \u003ca href='https://en.cppreference.com/w/cpp/memory/unique_ptr.html' target='_blank'\u003estd::unique_ptr\u003c/a\u003e to manage dynamically-allocated memory instead of doing manual allocations \u0026 de-allocations with 'new' \u0026amp; 'free'. This should help avoid memory leaks.\n\u003cli\u003eInitializing class member variables in the declaration (in the header file) as applicable. This is known as default member initialization, or in-class member initialization.\n\u003cli\u003eUse of the \u003ca href='https://en.cppreference.com/w/cpp/language/nullptr.html' target='_blank'\u003e'nullptr'\u003c/a\u003e keyword instead of 'NULL'. nullptr is a typed null pointer; also, it avoids ambiguous function calls that could happen when using NULL (which is typically defined as (void*)0).\n\u003cli\u003eUse of the \u003ca href='http://en.cppreference.com/w/cpp/language/override.html' target='_blank'\u003e'override'\u003c/a\u003e keyword to help keep track of which class functions/methods are overridden from base classes.\n\u003c/ul\u003e\n\nAt Red Ace Solutions, we tested cxWidgets on the following operating systems:\n\u003cul\u003e\n\t\u003cli\u003eIBM AIX 5.3\n\t\u003cli\u003eIBM AIX 4.3.3\n\t\u003cli\u003eIBM AIX 4.3.0\n\t\t\u003cul\u003e\n\t\t\t\u003cli\u003eget ncurses-5.3.tar.Z from \u003ca href='http://aixpdslib.seas.ucla.edu/index.html' target='_blank'\u003ehttp://aixpdslib.seas.ucla.edu/index.html\u003c/a\u003e\n\t\t\t\u003cli\u003ecompiled and tested on AIX 4.3.0 with g++/gcc 2.95.3 :-)\n\t\t\u003c/ul\u003e\n\t\u003cli\u003eRed Hat Enterprise Linux (3, 4 and 5) \n\t\u003cli\u003eFedora Core Linux (4, 5, and 6)\n\u003c/ul\u003e\nWe had tried to ensure the code base works well with the following terminals:\n\u003cul\u003e\n\t\u003cli\u003eWyse 50, 50+, 55, 60\n\t\u003cli\u003eIBM 3151 \n\u003c/ul\u003e\nWe had tried to ensure the code base works well with the following software emulators:\n\u003cul\u003e\n\t\u003cli\u003eGNOME Terminal (linux)\n\t\u003cli\u003eProcommPlus (wy50, ibm3151) (planned)\n\t\u003cli\u003ePutty (vt100, vt220, vt320) (planned)\n\t\u003cli\u003eWindows \"telnet\" (vt100-works except border lines...) (planned)\n\t\u003cli\u003eAnzio (wy50, ibm3151, vt220) (planned)\n\t\u003cli\u003eTinyTerm (vt220; wy50) (planned)\n\t\u003cli\u003ePowerTerm (planned)\n\u003c/ul\u003e\n\nRecently, I have made sure this builds on Linux Mint; otherwise, the source \u0026 makefile is as it was in 2007.\nAside from Linux Mint, it should also (hopefully) build fairly easily on similar modern distributions such as\nUbuntu, Debian, etc.\n\nWe had also been able to build the library on OS X (Darwin), though that hasn't been tested recently.\n\n## Versioning\n\ncxWidgets uses [semantic versioning](https://semver.org/) for releases. The authoritative version is the\ncontents of **`CXWIDGETS_VERSION`** at the repository root (for example `1.0.0` on a single line). This\nfile must not be named `VERSION`: with `-I..` while building from `src/`, a root file named `VERSION`\nis mistaken for the C++20 standard header `\u003cversion\u003e` on macOS (typically case-insensitive filesystems).\n\n- **`CXWIDGETS_VERSION`** — bump this when you tag or publish a release (major / minor / patch).\n- **`src/cxVersion.h`** — C/C++ macros `CXWIDGETS_VERSION_MAJOR`, `CXWIDGETS_VERSION_MINOR`,\n  `CXWIDGETS_VERSION_PATCH`, and `CXWIDGETS_VERSION_STRING`. Regenerate this file after changing\n  `CXWIDGETS_VERSION` by running `scripts/generate-cxVersion-h.sh`.\n- **`Doxyfile`** — keep `PROJECT_NUMBER` in sync with `CXWIDGETS_VERSION`.\n- **Shared libraries** — On Linux, the build produces a real file `libcxWidgets.so.M.N.P` (from `CXWIDGETS_VERSION`),\n  `SONAME` `libcxWidgets.so.M` (`M` is the major version), and `libcxWidgets.so` as a symlink. On macOS,\n  the same idea is expressed with `libcxWidgets.M.N.P.dylib` and `libcxWidgets.M.dylib` symlinks.\n\n## CI build artifacts\n\n[GitHub Actions](https://github.com/EricOulashin/cxWidgets/actions) builds each push and pull request\nagainst `main`. Completed workflows expose downloadable artifacts (retention follows GitHub’s default\npolicy), including:\n\n| Artifact | Contents |\n|----------|-----------|\n| **linux-packages** | `.deb` for Debian/Ubuntu-style systems and an `.rpm` produced via `alien` (test on Fedora/RHEL derivatives). |\n| **windows-sdk** | Zip layout: `include/cx/*.h`, `lib/` with Release `cxWidgets_static.lib`, import library, DLL, `pdcurses.lib`, and `docs-html/` when Doxygen runs or pre-generated docs are present. |\n| **macos-sdk** | `.tar.gz` with the same general layout: headers under `include/cx/`, static and versioned dynamic libraries under `lib/`, and `docs-html/` when available. |\n\n## Linux package repositories (APT and YUM) via GitHub Pages\n\nWhen a workflow run on **`main`** succeeds, CI can publish a **flat** APT repository and a **createrepo**-style\nYUM tree on the **`gh-pages`** branch under **`linux-repo/`**. Everything below assumes the\nGitHub Pages site is enabled for this repo.\n\n### One-time setup (project maintainer)\n\n1. In the GitHub repo: **Settings → Pages**.\n2. Under **Build and deployment**, set **Source** to **Deploy from a branch**.\n3. Choose branch **`gh-pages`**, folder **`/ (root)`**, then save.\n4. Push to **`main`** (or use **Actions → CI Build and Test → Run workflow**) so the **Publish APT and YUM indexes** job runs. It only runs on pushes to **`main`**, not on pull requests.\n\nUntil **`gh-pages`** exists and that job has run at least once, the APT URL will return **404** and `apt` will report **Unable to locate package**.\n\n### Check that the APT index exists\n\nReplace the host and repo name if you use a fork (Pages URL is `https://\u003cuser\u003e.github.io/\u003crepo\u003e/`).\n\n```bash\ncurl -fsSL -o /dev/null -w '%{http_code}\\n' \\\n  https://ericoulashin.github.io/cxWidgets/linux-repo/apt/Packages.gz\n```\n\nYou want **`200`**. **`404`** means Pages is not deployed yet, the path is wrong, or the publish job failed.\n\n### Architecture\n\nCI currently builds **`amd64`** packages only. Confirm before using the APT line:\n\n```bash\ndpkg --print-architecture\n```\n\nIf that prints **`arm64`** (or anything other than **`amd64`**), this APT repo will not offer **`libcxwidgets-dev`** until an **`arm64`** (or multi-arch) build is published. Use [Building](#building) from source, or install a downloaded `.deb` only if it matches your architecture.\n\n### APT (Debian, Ubuntu, Linux Mint, etc.)\n\nPackage indexes are **not** GPG-signed. Using **`trusted=yes`** is only appropriate if you trust this source.\n\n**Classic `sources.list` drop-in** — create `/etc/apt/sources.list.d/cxwidgets.list`:\n\n```\ndeb [trusted=yes arch=amd64] https://ericoulashin.github.io/cxWidgets/linux-repo/apt ./\n```\n\nThen:\n\n```bash\nsudo apt update\nsudo apt install libcxwidgets-dev\n```\n\nIf **`apt update`** prints errors for that URL (404, certificate, etc.), fix Pages or the URL before retrying **`apt install`**.\n\n**DEB822 (Ubuntu 22.04+)** — e.g. `/etc/apt/sources.list.d/cxwidgets.sources`:\n\n```\nTypes: deb\nURIs: https://ericoulashin.github.io/cxWidgets/linux-repo/apt\nSuites: ./\nComponents:\nArchitectures: amd64\nTrusted: yes\n```\n\n### Install the `.deb` directly (no APT metadata)\n\nIf Pages is broken or you prefer a one-off install after a release landed on **`gh-pages`**:\n\n```bash\nVER=1.0.0\ncurl -fLO \"https://raw.githubusercontent.com/EricOulashin/cxWidgets/gh-pages/linux-repo/apt/libcxwidgets-dev_${VER}_amd64.deb\"\nsudo apt install ./libcxwidgets-dev_${VER}_amd64.deb\n```\n\nAdjust **`VER`**, **`EricOulashin/cxWidgets`**, and **`amd64`** to match the file that actually exists on the **`gh-pages`** branch (browse the repo on GitHub, branch **`gh-pages`**, path **`linux-repo/apt/`**).\n\n**YUM/DNF (Fedora, RHEL, AlmaLinux, etc.)**\n\nCreate `/etc/yum.repos.d/cxwidgets.repo`:\n\n```\n[cxwidgets-github]\nname=cxWidgets (GitHub Pages)\nbaseurl=https://ericoulashin.github.io/cxWidgets/linux-repo/yum/x86_64\nenabled=1\ngpgcheck=0\n```\n\nThen install the development package provided by the RPM (name may match `libcxwidgets-dev` or similar\ndepending on how `alien` named the RPM):\n\n```\nsudo dnf install 'libcxwidgets*'    # or: yum install ...\n```\n\nNew `.deb` / `.rpm` builds are appended when CI runs on `main`; refresh indexes with `sudo apt update` or\n`sudo dnf clean expire-cache \u0026\u0026 sudo dnf makecache`.\n\n## Building\nThere is a makefile in the src directory.  You can build from the command line by going into the src\ndirectory and running make.  That will build object files (*.o) which you can link your project against.\nYou can also run 'make libcxWidgets.a' to build a static library with all the cxWidgets objects that you\ncan link your project against.  You can also run 'make libcxWidgets.so' (on Linux) or 'make libcxWidgets.dylib'\n(on Mac OS X) to make a dynamic library.\nThat will also build testApp (the manual test app) as well as a utility called keys, which reports the\nkey code for any key pressed (you can press ESC or Ctrl-C to quit).\n\nSome notable make commands\n\u003cul\u003e\n\u003cli\u003e\u003cb\u003emake\u003c/b\u003e: Builds testApp and keys (this builds all the object files, as well as the static library libcxWidgets.a)\n\u003cli\u003e\u003cb\u003emake testApp\u003c/b\u003e: Builds just testApp (this builds all the object files, as well as the static library libcxWidgets.a)\n\u003cli\u003e\u003cb\u003emake libcxWidgets.a\u003c/b\u003e: Builds the static library\n\u003cli\u003e\u003cb\u003emake libcxWidgets.so\u003c/b\u003e (Linux) or \u003cb\u003emake libcxWidgets.dylib\u003c/b\u003e (Mac OS X): Builds the dynamic library\n\u003cli\u003e\u003cb\u003emake install\u003c/b\u003e: Installs the libraries to your system\n\u003cli\u003e\u003cb\u003emake clean\u003c/b\u003e: Deletes binaries\n\u003c/ul\u003e\n\nThe makefile supports using ccache if it's available on the system.\n\n## Building on Windows (Visual Studio 2022)\n\ncxWidgets also builds on Windows using Visual Studio 2022. The Windows build uses\n[PDCurses](https://github.com/wmcbrine/PDCurses) (WinCon backend) as a drop-in replacement for\nncurses, providing a ncurses-compatible API via the Windows Console API.\n\n### Prerequisites\n\n- Visual Studio 2022 (Community, Professional, or Enterprise) with the **Desktop development with C++** workload installed.\n- PDCurses is included as a **git submodule** at `vs/pdcurses/`. When cloning cxWidgets, initialize it with:\n  ```\n  git clone --recurse-submodules https://github.com/EricOulashin/cxWidgets.git\n  ```\n  Or, if you already have a clone without the submodule:\n  ```\n  git submodule update --init\n  ```\n\n### Building\n\nOpen `vs/cxWidgets.sln` in Visual Studio 2022 and build the solution (Build → Build Solution or\nRebuild Solution). Both **Debug|x64** and **Release|x64** configurations are supported.\n\nYou can also build from the command line using MSBuild:\n```\ncd vs\nmsbuild cxWidgets.sln -t:Rebuild -p:Configuration=Debug -p:Platform=x64\nmsbuild cxWidgets.sln -t:Rebuild -p:Configuration=Release -p:Platform=x64\n```\n\n### Output files\n\nAll build outputs are placed in `vs/bin/Debug/` or `vs/bin/Release/`:\n\n| File | Description |\n|------|-------------|\n| `pdcurses.lib` | PDCurses static library (ncurses-compatible for Windows) |\n| `cxWidgets_static.lib` | cxWidgets static library |\n| `cxWidgets.lib` / `cxWidgets.dll` | cxWidgets dynamic library (DLL) and its import library |\n| `testApp.exe` | Manual test application |\n\n### Linking your project against cxWidgets on Windows\n\nLink against `cxWidgets_static.lib` (static) or `cxWidgets.lib` + `cxWidgets.dll` (dynamic),\nplus `pdcurses.lib` and `user32.lib`. Add `vs/pdcurses` and `src` to your include directories.\n\n### Platform compatibility notes\n\n- **PDCurses** (WinCon backend) provides the same ncurses API used on Linux/macOS, so cxWidgets\n  source code is fully shared across platforms.\n- **WANT_TIMEOUT** (signal-based idle timeout via `SIGALRM`) is automatically disabled on Windows\n  since Windows does not support `SIGALRM`.\n- **POSIX regex** (`\u003cregex.h\u003e`) is replaced with C++17 `\u003cregex\u003e` on Windows.\n- The platform compatibility header `src/cxPlatform.h` handles all platform differences\n  automatically — no source changes are needed when porting applications between platforms.\n\n## Screenshots\nThese are some screenshots of the test app, showing examples of what you can do with cxWidgets:\n\u003cp align=\"center\"\u003e\n\t\u003cimg src=\"screenshots/cxWidgets_menu.png\" alt=\"cxMenu\" width=\"800\"\u003e\n\t\u003cimg src=\"screenshots/cxWidgets_input_box.png\" alt=\"Text input box\" width=\"800\"\u003e\n\t\u003cimg src=\"screenshots/cxWidgets_input_box_2.png\" alt=\"Text input box 2\" width=\"800\"\u003e\n\t\u003cimg src=\"screenshots/cxWidgets_input_box_2_with_OKDlg.png\" alt=\"Text input box 2 with OK dialog\" width=\"800\"\u003e\n\t\u003cimg src=\"screenshots/cxWidgets_test_form.png\" alt=\"Text form\" width=\"800\"\u003e\n\t\u003cimg src=\"screenshots/cxWidgets_test_form_filled.png\" alt=\"Text form (filled)\" width=\"800\"\u003e\n\t\u003cimg src=\"screenshots/cxWidgets_date_picker.png\" alt=\"Date picker (new: 2026-03-17)\" width=\"600\"\u003e\n\t\u003cimg src=\"screenshots/cxWidgets_file_open_dialog.png\" alt=\"File Open dialog (new: 2026-03-17)\" width=\"600\"\u003e\n\t\u003cimg src=\"screenshots/cxWidgets_cxGrid.png\" alt=\"cxGrid (new: 2026-03-18)\" width=\"500\"\u003e\n\u003c/p\u003e\n\n## Example applications\nSome example programs are included, which show example usages of cxWidgets:\n\u003cul\u003e\n\u003cli\u003eSpreadsheet:\u003cbr/\u003e\n\u003cimg src=\"screenshots/examples/spreadsheet_1.png\" alt=\"Spreadsheet\" width=\"800\"\u003e\n\u003cimg src=\"screenshots/examples/spreadsheet_2.png\" alt=\"Spreadsheet: File menu\" width=\"800\"\u003e\n\u003cimg src=\"screenshots/examples/spreadsheet_3.png\" alt=\"Spreadsheet: Picking a date\" width=\"800\"\u003e\n\u003cimg src=\"screenshots/examples/spreadsheet_4.png\" alt=\"Spreadsheet: Date entered in cell\" width=\"800\"\u003e\n\u003cli\u003eCentipede:\u003cbr/\u003e\n\u003cimg src=\"screenshots/examples/centipede.png\" alt=\"Centipede\" width=\"800\"\u003e\n\u003cli\u003eFlashcard:\u003cbr/\u003e\n\u003cimg src=\"screenshots/examples/flashcard.png\" alt=\"Centipede\" width=\"600\"\u003e\n\u003cli\u003eSnake:\u003cbr/\u003e\n\u003cimg src=\"screenshots/examples/snake.png\" alt=\"Centipede\" width=\"600\"\u003e\n\u003c/ul\u003e\n\n## Original readme (by Mike Kinney) (README.txt)\nREADME.TXT for cxWidgets - character based \"widgets\"\n\nStuff to add/change:\n- See http://www.troubleshooters.com/lpm/200405/200405.htm#_A_Simple_Menu for\n  possibly an easier way to do menus..\n\nBackground: \n  This is an attempt at an object oriented design of a character\n  user interface (or CHUI) screen library in C++. We are trying to \n  \"wrap\" the ncurses library to make it *much* easier to use. \n  We want to hide as much of the implementation as possible. \n  Note: ncurses is licensed under the \"MIT-style\" of \n  licenses. See their copyright notice in most of their source files.\n   Great resources at:\n     http://dickey.his.com/ncurses/ncurses-intro.html\n     http://www.tldp.org/HOWTO/NCURSES-Programming-HOWTO/screen.html\n     http://dickey.his.com/ncurses/ncurses.faq.html\n  Note: A few other screen libraries are slang?, and \n  Vermont Views (commercial).\n\n  We really like the wxWidgets.org framework, but needed a minimalistic\n  framework for character based terminals. This is our attempt.\n  We have not really modeled it after their frame work, though. \n\n  Our ultimate goal is to be able to merge this codebase with \n  wxWidgets some time in the future, but for now, we would be \n  simply happy if it allows people to write elegant code in c++ \n  for use in character based applications using our library.\n\n  We have tried to make cxWidgets work well in the following operating systems:\n    - IBM AIX 5.3\n    - IBM AIX 4.3.3\n    - IBM AIX 4.3.0\n       - get ncurses-5.3.tar.Z from http://aixpdslib.seas.ucla.edu/index.html\n       - compiled and tested on AIX 4.3.0 with g++/gcc 2.95.3 :-)\n    - Red Hat Enterprise Linux (3, 4 and 5) \n    - Fedora Core Linux (4, 5, and 6)\n\n  We have tried to ensure the code base works well with the following\n  terminals:\n    - Wyse 50, 50+, 55, 60\n    - IBM 3151 \n\n  We have tried to ensure the code base works well with the following\n  software emulators:\n    - GNOME Terminal (linux)\n    - ProcommPlus (wy50, ibm3151) (planned)\n    - Putty (vt100, vt220, vt320) (planned)\n    - Windows \"telnet\" (vt100-works except border lines...) (planned)\n    - Anzio (wy50, ibm3151, vt220) (planned)\n    - TinyTerm (vt220; wy50) (planned)\n    - PowerTerm (planned)\n    - QVT Term? (planned)\n\n  Note: This is heavily designed for U.S. usage, but could be adapted\n  for others. Let us know if you want to allow for different types\n  of formats. (i.e., phone number formatting, etc.)\n\nAuthors:\n   Eric Oulashin (eric.oulashin@gmail.com)\n   Mike Kinney (kinneym@redacesolutions.com)\n   Glen Thorne (gthorne@whoneedsmicrosoft.com)\n\nLicense:\n  cxWidgets Library License\n  Copyright (c) 2005-2007 Michael H. Kinney\n\n  Everyone is permitted to copy and distribute verbatim copies of this \n  license document, but changing it is not allowed.\n\n  CXWIDGETS LIBRARY LICENSE\n  TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION\n\n  This library is free software; you can redistribute it and/or modify it \n  under the terms of the GNU Library General Public License as published \n  by the Free Software Foundation; either version 2 of the License, \n  or (at your option) any later version.\n\n  This library is distributed in the hope that it will be useful, \n  but WITHOUT ANY WARRANTY; without even the implied warranty of \n  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU \n  Library General Public License for more details.\n\n  You should have received a copy of the GNU Library General Public \n  License along with this software, usually in a file named COPYING.LIB. \n  If not, write to the Free Software Foundation, Inc., 59 Temple Place, \n  Suite 330, Boston, MA 02111-1307 USA.\n\n  EXCEPTION NOTICE\n  1. As a special exception, the copyright holders of this library \n  give permission for additional uses of the text contained in this \n  release of the library as licensed under the cxWindows Library License, \n  applying either this License, or (at your option) any \n  later version of this License as published by the copyright holders \n  of the License document.\n\n  2. The exception is that you may create binary object code versions \n  of any works using this library or based on this library, \n  and use, copy, modify, link and distribute such binary object code \n  files unrestricted under terms of your choice.\n\n  3. If you copy code from files distributed under the terms of the \n  GNU General Public License or the GNU Library General Public License \n  into a copy of this library, as this license permits, the exception \n  does not apply to the code that you add in this way. To avoid \n  misleading anyone as to the status of such modified files, you must \n  delete this exception notice from such code and/or adjust the \n  licensing conditions notice accordingly.\n\n  4. If you write modifications of your own for this library, it is \n  your choice whether to permit this exception to apply to your \n  modifications. If you do not wish that, you must delete the \n  exception notice from such code and/or adjust the licensing conditions \n  notice accordingly. \n\nCode standards:\n- every file must contain this at the top:\n   // Copyright (c) 2005-2007 Michael H. Kinney\n- method variables are prefixed with \"m\" like mFoo\n- enums are prefixed with 'e' with the rest capitalized,\n  i.e., eX_ABC\n- parameter variables are prefixed with \"p\" like pFoo\n- include guards on include (.h) files\n- each class, prefixed by \"cx\" has it's own .cpp file\n- provide a unit test, when/where possible\n- use only c++ comments (i.e., //)\n- always use brackets on \"()\" and \"{}\" if commands and use like this:\n   if (status) {\n      // blah\n   }\n   else {\n      // blah\n   }\n- indentation is always 3 spaces (no tabs)\n- variable names are mixedCase not like this_variable\n- compile/test with \"-Wall\"\n- run valgrind on it regularly\n- KISS\n- if option in a derived class, add a default to the base class\n- separate options by spaces, like this \"foo(one, two, three);\" \n  *not* like this: \"foo(one,two,three);\"\n- for loops use spacing like this:\n   for (int i=0; i\u003c10; ++i) { // note: spacing!\n      x(i);\n   }\n- Adhere to wxWidget's parameter ordering...\n\ncxBase: A namespace that contains some useful \u0026 important functions.\n- When we initialize the terminal, we determine if we can do colors. If\n  we can, then we set our default color scheme. This can be overridden\n  thru the use of method calls in cxObject or a derived class.\n- There are positional helpers like:\n  Row or y-axis:\n      top() - Gives you the top row of the main screen\n      centerRow() - Gives the center row of the main screen \n      bottom() - Gives the bottom row of the main screen\n  Column or x-axis:\n      left() - Gives the leftmost column of the main screen\n      centerCol() - Gives the center column of the main screen\n      right() - Gives the rightmost column of the main screen\n  Message box functions (providing one-line message box functionality):\n      These functions use the following parameters:\n         pRow: Row for upper-left corner\n         pCol: Column for upper-left corner\n         pWidth: Message box width\n         pTitle: Message box title\n         pMessage: Message to appear in the box\n         pStatus: Status text to appear at the bottom border\n      messageBox(pRow, pCol, pHeight, pWidth, pTitle, pMessage, pStatus)\n       - Note: pStatus is optional for this one.\n      messageBox(pRow, pCol, pTitle, pMessage, pStatus)\n      messageBox(pTitle, pMessage, pStatus)\n      messageBox(pMessage, pStatus)\n      messageBox(pMessage)\n\n- Example #1: (simple message to the screen)\n    cxBase::init();              // required at the top of all progs\n    messageBox(\"Hello, world!\");\n    cxBase::cleanup();           // required at the end of all progs\n\n- Example #2: (simple splash screen)\n    cxBase::init();              // required at the top of all progs\n    splash(\"Hello, world!\", 3);\n    cxBase::cleanup();           // required at the end of all progs\n\ncxObject: \n- All cxWidgets classes are derived from this class.\n- This object sets up, initializes the screen and gets it ready for each\n  of the derived classes to do their work.\n- Can override the default function keys.\n- F5 thru F8 are not \"defined\"\n\ncxWindow:\n- Displays a text window on the screen.\n- Positions: We do everything (row,column) where row is the \"y-axis\" or \n  vertical axis and column is the \"x-axis\" or horizontal axis.\n  All from the top left corner of the screen, zero-based.  For instance,\n  using this information:\n      a..b\n      c..d\n  the positions would be: a=(0,0)  b=(0,4)  c=(1,0)  d=(1,4).\n- A window can have a title, status, warning line\n  Sample:\n   ┌Title────────────┐  (title)\n   │Test message     │  (message)\n   └Press any key...─┘  (status)\n- A cxWindow can also use another cxWindow to display the title and\n  another cxWindow to display the status.  In such cases, the other\n  window will be used instead of the title/status lines.\n- Ability to \"default\" the color scheme, as well as override it.\n- Colors: (foreground/background)\n    border, title, message, statusLine, warningLine\n- Change font to compressed print and display a file, option to\n  auto-wrap long lines (or not) (TODO)\n- Has the ability to get the contents of the window, like a snapshot\n  (including the title \u0026 status).  We want to be able to strip out\n  the attributes and return it as a string.\n- Can be added to a parent window, and can contain subwindows\n- When you call show() for a window, the window draws itself and then\n  calls show() for all its subwindows.\n- The show() method returns an int to support derived windows where\n  it would be handy to override show() and return some kind of code\n  (see cxMessageDialog).\n- Note: There are 2 methods for moving a window: move() and\n  moveRelative().  move() moves a window based on absolute screen\n  coordinates, and moveRelative() moves a window relative to itself\n  (with horizontal and vertical offsets).  moveRelative() simply\n  calls move() with the new absolute coordinates.  This has the\n  advantage that if you derive a custom class from cxWindow and\n  you need to override move(), you don't need to override\n  moveRelative().\n\n- Example #1: (implements a \"messageBox()\")\n   cxWindow aWindow(\"Some title\", \"This is a sample message box.\", \"Press any key...\");\n   cxWindow.show();\n   curs_set(0); // hide cursor\n   getchar();   // get any key\n   curs_set(1); // set cursor back to normal\n   clear();     // clear screen\n   refresh();   // repaint the screen\n\n- Example #2: Creating a parent window with a subwindow\n  cxWindow aWindow(NULL, 0, 0, 10, 20, \"Title\", \"Sample message\", \"Status\");\n  cxWindow subwin(\u0026aWindow, 2, 1, 8, 12, \"Title2\", \"Subwin message\", \"Subwin status\");\n  aWindow.show();\n  - Note: The positions are absolute.\n  - Note: Many of the other classes, such as cxButton, cxFileViewer, cxMessageDialog,\n    etc. are derived from cxWindow, which means they have all the functions of\n    cxWindow (such as show(), etc.) and can also belong to a parent window and have\n    subwindows of their own.\n\ncxButton:\n- derived from cxWindow\n- Manages buttons.\n\ncxFileViewer:\n- derived from cxWindow\n- Display the contents of a file in a window. It should be able to \n  view files larger than the window size.\n- The number of lines/characters will show in status bar.\n- The filename will show in the title bar.\n- Keys:\n   right arrow - move one character to the right (if there is more to view)\n   left arrow - move one character to the left (if there is more to view)\n   ESCAPE - cancel (Are you sure you want to quit?)\n   up arrow - scroll up one line\n   down arrow - scroll down one line\n   page up - scroll up a page\n   page down - scroll down a page\n   F10 - (Exit)\n   HOME - go to top/left\n   END - go to bottom/right\n\ncxDialog:\n- Represents a dialog\n- Derived from cxWindow\n- Overrides show() to wait for user input, and returns a\n  code based on user interaction.\n  - When the escape or cancel key is pressed, cxID_QUIT\n    is returned.\n  - When the enter or 'go' key is pressed, cxID_OK is\n    returned.\n- Defines the following return codes (returned by show()):\n  cxID_OK\n  cxID_CANCEL\n  cxID_EXIT\n  cxID_QUIT\n\ncxMessageDialog:\n- Derived from cxDialog\n- Represents a dialog box with \"OK\" and \"Cancel\" buttons\n- Can optionally show only the \"OK\" or \"Cancel\" button\n  through the style parameter\n- Can also display \"Yes\" and \"No\" on the buttons instead\n  of \"OK\" and \"Cancel\"\n- Overrides show() and waits for user input, and returns a\n  code based on user interaction.\n  - The arrow and tab keys can be used to move between the\n    2 buttons.\n  - When the escape or cancel key is pressed, cxID_QUIT\n    is returned.\n  - When the enter, space, or 'go' key is pressed a code\n    corresponding with the selected button is returned.\n    - cxID_OK is returned if the user selected the \"OK\" button.\n    - cxID_CANCEL is returned if the user selected the \"Cancel\" button.\nConstructor:\n  cxMessageDialog(pParentWindow, pRow, pCol, pHeight, pWidth,\n                  pTitle, pMessage, pStyle, pStatus)\n  pStyle can be any of the following (or multiple, bitwise OR'ed together):\n   cxYES         // Show Yes button\n   cxOK          // Show OK button\n   cxNO          // Show No button\n   cxYES_NO      // Show Yes and No buttons (equivalent to cxYES | cxNO)\n   cxCANCEL      // Show Cancel button\n   cxYES_DEFAULT // (default)\n   cxNO_DEFAULT  // Set No button to default\n\n\ncxField:\nTODO: All of this\n- Special pre-built fields for ease of use:\n   - \"phone\" - phone number entry\n      - phone entries: \"(DDD)DDD-DDDD\" \"DDD-DDD-DDDD\"\n   - \"email\" - email address (ensures valid email address, postprocessing)\n   - \"web\" - web address (ensures valid url post, processing)\n   - \"zipcode\" - zip code entry\n      - valid formats \"DDDDD\", \"DDDDD-DDDD\" (Handle Canadian provinces?)\n      - Notes: \n         - If format is \"DDDDD\" and initial value is \"1234\", then \n           after processing thru the field, it will be changed to \"01234\".\n         - If the format is \"DDDDD-DDDD\" and the the initial value is\n           \"12345\", then the data will stay that way, unless you add any\n           characters after the \"-\", in which case you must enter all four\n           digits.\n   - \"time\" - time field\n      - time formats: \"HH:MM\" (24hr), \"HH:MMam\"\n      - Note: If using \"am\" format and user enters \"20\" it should\n        convert it to \"08:00pm\"\n      - time codes: h=hour, m=minute, s=seconds\n      - Keys:\n           n - now\n        (only if \"am\" is in the format string, otherwise 24hr time is used)\n           a - change to am\n           p - change to pm\n           PAGEUP - change to am \n           PAGEDOWN - change to pm\n   - \"state\" - pick one of the states, allow entry for only one \n   - \"province\" - pick one of the Canadian provinces, allow entry for only one \n   - \"stateORprovince\" - allow either state or province\n   - \"date\" - date field\n      - date formats: \n         \"MMDDYY\", \"MM/DD/YY\", \"MM/DD/YYYY\", \"YYYY-MM-DD\", \"MMYY\", \"YYMM\"\n      - date codes: m=month, d=day, y=year, w=week\n      - Note: If you enter \"010203\" for any of the formats, it should \n        automatically convert it to the correctly displayed format. \n      - Note: 1950 is the \"split\" from \"19\" and \"20\".\n      - quick entry: If you enter the following (and the ENTER or TAB key):\n           \"0\" - today's date (in the correct format)\n           \"-1\" yesterday\n           \"1\" tomorrow\n           \"1w\" one week from today\n           \"-1w\" one week ago\n           \"-1m\" -1 month\n           PAGEUP - same as -1m \n           PAGEDOWN - same as +1m \n\ncxInput: Derived from cxWindow\n   A single-line borderless window for doing single-line input.  This\n   class would be a window that has a string that contains the user's\n   input, along with a getter method to retreive the user's input.\n   TODO: Add character validation\n- Field validation:\n   d - any digit [0-9]\n   D - Like \"d\", but each character is required\n   n - any number [0-9-.]\n   N - like \"n\", but each character is required\n       (i.e., cannot go to next field until you either clear the field\n        or enter each character)\n   @ - is a fixed decimal (for instance nnn@nn) (i.e., \"%6.2f\")\n       (where you do not have to press the decimal; i.e, \"12345 would\n        be accepted as \"123.45\")\n   : - is fixed (as in \"time\")\n   - - For dates\n   ( or ) - For stuff like phone numbers, etc.\n   [ or ]\n   . - is a decimal (for instance nnn.nn) \n       (where you enter the decimal, but it always remains aligned\n        like this \"38\" shows as \"38.00\" and \"38.1\" shows as \"38.10\".\n   p - alpha numeric plus [0-9a-zA-Z ,-.] (useful in names)\n   P - like p, but each character is required\n   a - alpha numeric [0-9a-zA-Z] (no punctuation, nor space)\n   A - like a, but each character is required\n   x - is any character [0-9a-zA-Z ,./;'[]\\-=!@#$%^\u0026*()_+\u003c\u003e?:\"{}|]\n   X - like x, but each character is required\n   r - compares each keypress with a regular expression\n   m - Masked (i.e., password)\nIf a user enters an invalid character, then beep, display a message\nin the status line.\nThe following regular expressions (if needed) could be used to\nvalidate an entire string for certain inputs:\nDigits (0-9): ^[0-9]*$\nDigits with decimal points: ^([0-9]*[0-9.][0-9]*)*$\n  (Back-quote the decimal point, but not the parenthesis, in C++ code)\n\ncxMultiLineInput: Derived from cxWindow\n  A multi-line input window, containing a label and many inputLine windows\n  for doing multi-line input.  This class would have the ability of handling\n  arrow keys for movement between the inputLine windows, and the ability to\n  concatenate all user inputs to a single string.\n  There are several functions that can set up functions to be run in the\n  input when focus is set:\n   - setOnFocusFunction() - Sets a function to be run immediately at the beginning of setFocus()\n   - setOnKeyFunction() - Sets a function to be run after each keypress (runs inside the input loop)\n   - setValidatorFunction() - Sets a function to be run to validate the input text.  The function\n         set here is run after the input loop - basically, after the user has entered all the\n         input for the field.  However, if the function set here says that the input is invalid,\n         cxMultiLineInput will re-run its input loop until the input is valid according to\n         the validator function so that the user can correct the input.\n   - setOnLeaveFunction() - Sets a function to be run right before setFocus() exits\n\ncxForm: (FORMS)\n- Diplay a form for data input. Typically you will do something with the input.\n  By default, if you leave the last field, you will exit the form. \n  (see \"quit\" vs \"exit\" below)\n- \"quit\" versus \"exit\": There is a distinction as to how a user left the\n   form. \"quit\" means you did not want to proceed. (i.e., ESCAPE was pressed)\n   \"exit\" means we completed the form. (i.e., F10, ENTER or TAB on last field\n   if the autoExit option is not set.)\n- Should we allow the following field options:\n   CLEARONKEY: Clear the field when the user types a valid key\n   LEFT: Left-align\n   RIGHT: Right-align\n   SKIP: Display the field but don't allow the user to edit it\n- You can run a function at different points in the form/field:\n   - at the beginning of the form\n   - at the end of the form\n   - upon quit\n   - upon entering a field\n   - upon leaving a field\n   - upon a non-navigation key (i.e., pageUp, pageDown, plusKey)\n   TODO: Add function pointers to cxInput to handle these functions\n- Navigation Keys:\n   Inter field:\n      TODO: ESCAPE - cancels form (should we prompt to \"Are you sure?\")\n      up arrow - previous field (if at first field, wrap to last field?)\n      down arrow - next field (if at last field, wrap to first field?)\n      F10 - go\n\n   Intra field:\n      right - move one character to the right\n      left - move one character to the left\n      backspace - erases one character to the left\n      delete - erases one character to the right\n      home - moves to the very first position in the field\n      end - moves to the last chacter in the field\n      enter - moves to next field (if on the last field then it is\n              the same thing as F10, unless you specifically \n              set autoExit to false.)\n      tab - moves to next field\n      TODO: shift-tab - moves to previous field (possibly use KEY_BTAB?)\n\n- Function Keys:\n   TODO: Function key label line: \n    (Note: Not sure how characters there are per key. Will need to \n     these this!)\n      \"F1=Hlp F2=Cho F3=Clr F4=Can                            F10=Go\"\n    Need to put this in the status area? or next to last line? Thoughts?\n\n- Choice lists:\n   TODO: Do this ..\n   Essentially a drop down \"menu\" with choices and fills in the field\n   with the selection.\n   An example would be, pick from the following printers:\n   Printer: prn100\n            prn101\n            prn102\n            prn103\n   TODO: write the example code here (after writing it in testApp.cpp).\n  \nForm Example #1: (standard form)\n   TODO: Update this example\n   cxForm aForm(NULL, 0, 0, 20, 50, \"Sample form\");\n   string name;\n   string age;\n   string city;\n\n   aForm.position(\"center\", \"center\");\n   aForm.alignFields(\"data\"); // default is \"left\"\n   aForm.append(1, 1, 1, 20, \"Name:\");\n   aForm.append(2, 1, 1, 10, \"Age:\");\n   aForm.append(3, 1, 1, 30, \"City:\");\n   name = aForm.getValue(\"Name:\");\n   age = aForm.getValue(\"Age:\");\n   city = aForm.getValue(\"City:\");\n\n   // if you define any functionKeyLabels or set aForm.funtionKeyLabels(true)\n   // then the fields will display on the last line of the window (in the\n   // border!)\n   aForm.functionKeyLabel(\"F1\",\"Hlp\");\n   aForm.functionKeyLabel(\"F10\",\"Go\");\n\n   // By default, if you enter thru the last field, you EXIT the form.\n   // This overrides that and makes you either F10 to EXIT the form\n   // or hit ESCAPE to quit the form.\n   aForm.autoExit(false); \n\n   status=aForm.process(); // display, process, and clean up after itself\n   if (status) {\n      // they either hit ENTER thru the last field or hit F10 (i.e., exit)\n      messageBox(\"Thanks for completing our form. You get a gold star!\")\n   }\n   else {\n      // they hit ESCAPE (i.e., quit)\n      messageBox(\"Can't complete anything, can you?!?\");\n   }\n\nForm Example #2: (simplest form)\n   cxForm aForm;\n   int anIQ;\n\n   aForm.title(\"R U smart?\");\n   aForm.newField(\"Enter your iq:\", \"NNN\", anIQ);\n   if (aForm.process()) {\n      messageBox(\"Your iq is:\" + toString(anIQ) + \". Wow!\");\n   }\n\nForm Example #3: \n   // Do not need to do absolute positioning of the fields, we\n   // can handle that for you. \n   // This will display a form that will create a new window that\n   // is centered and the border is the smallest necessary to allow\n   // for the form to fit.\n   aForm.title(\"Sample Form\"); // not really necessary, but it is eye candy\n   aForm.newField(\"Your name:\", \"xxxxxxxxxx\", aString, \"Enter your name.\");\n   aForm.newField(\"Number:\", \"nnnn\", aNumber, \"Enter some number.\");\n   status=aForm.process(); // display, process, and clean up after itself\n   if (status) {\n      messageBox(\"Thanks for randomly entering data!\");\n   }\n   else {\n      messageBox(\"I bet you do not answer surveys either!\");\n   }\n\ncxMenu: (MENUS)\n- Allow you to select an item from a list (it will return a code corresponding to that item).\n- Menu types: pull-right, pop-up\n- Keys:\n   up arrow - go to previous menu item (if at top, go to bottom)\n   down arrow - go to next item (if at bottom, go to top)\n   ESCAPE - quit\n   F1 - Help\n   F10 - select highlighted entry\n   ENTER - select highlighted entry\nTODO: Add hotkeys\nTODO: finish the spacebar to allow \"menu jumping\".\n\n- Example #1:\n   // functions for example below\n   void test1() {\n      // messageBox() box calls \"cxWindow aWindow; aWindow.message();\"\n      messageBox(\"center\", \"center\", \"Test1\", \"You are in test1.\");\n   }\n   void test2() {\n      messageBox(\"center\", \"center\", \"Test2\", \"You are in test2.\");\n   }\n   void test3() {\n      messageBox(\"center\", \"center\", \"Test3\", \"You are in test3.\");\n   }\n\n   TODO: Update this example\n   cxMenu aMenu;\n   // this allows you to enter a '1' or highlight the entry and hit enter\n   aMenu.add('1', \"Some test menu\", test1);\n   aMenu.add('2', \"Another test menu\", test2);\n   // can leave the 'hotkey' off\n   aMenu.add(\"Yet another test menu\", test3); \n   // Should we follow the \"windows\" way and do x\u0026 for hot key? (and color?)\n   aMenu.colors(\"blue\", \"white\");\n   aMenu.align(\"left\");\n   aMenu.border(\"lines\");\n   aMenu.position(\"center\", \"center\");\n   aMenu.process(); // display, process and clean up after itself\n\ncxFieldFunction: Derived from cxObject\n- This is basically a holder for a function pointer and was\n  designed initially for use with the cxInput and cxMultiLineInput\n  classes.  This class lets you set the function pointer in the\n  constructor, as well as whether the function's return value should\n  be used by the caller.  Note that the function must have the following\n  signature:\n   string func(void *p1, void *p2)\n  The parameters are void pointers because it can't be known by this\n  class what types of objects your functions will need.  So, any\n  function that you pass to this class must have this signature, and\n  will have to cast the pointers to the types that it uses.  The\n  function is also assumed to return a string (in the case of lookup\n  functions).\n\nPossible future projects:\n- port \"snakes\" (game)\n- port \"centipede-type\" (game)\n- Screen saver (cxScreenSaver class?)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fericoulashin%2Fcxwidgets","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fericoulashin%2Fcxwidgets","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fericoulashin%2Fcxwidgets/lists"}