mail archive of the barebox mailing list
 help / color / mirror / Atom feed
* [RFC PATCH 00/20] introduce application support
@ 2013-03-06  9:26 Jean-Christophe PLAGNIOL-VILLARD
  2013-03-06  9:29 ` [PATCH 01/20] Makefile: x_flags prepare for apps support Jean-Christophe PLAGNIOL-VILLARD
  2013-03-07  7:36 ` [RFC PATCH 00/20] introduce " Sascha Hauer
  0 siblings, 2 replies; 31+ messages in thread
From: Jean-Christophe PLAGNIOL-VILLARD @ 2013-03-06  9:26 UTC (permalink / raw)
  To: barebox

HI,

	this patch serie introduce the application support to barebox

	This will allow to run application at run time by calling barebox
	syscalls and as this will be a stable ABI the application will able
	the run against any barebox that support it

	As the application are not linked to barebox the GPLv2 licence does
	not apply.

	This patch serie provide a small libc (partialy implemented) which is
	under GPLv2 + exception

As a special exception, if other files instantiate templates or use macros
or inline functions from this file, or you compile this file and link it
with other works to produce a work based on this file, this file does not
by itself cause the resulting work to be covered by the GNU General Public
License. However the source code for this file must still be made available
in accordance with section (3) of the GNU General Public License.

This exception does not invalidate any other reasons why a work based on
this file might be covered by the GNU General Public License.

	This also provide the curses support proted against the libary with some examples

	One of the idea will be to create a curses interface bios like for barebox

The following changes since commit 94e71b843f6456abacc2fe76a5c375a461fabdf7:

  libubi: Use global mtd_all_ff function (2013-03-04 10:54:46 +0100)

are available in the git repository at:

  git://git.jcrosoft.org/barebox.git delivery/application

for you to fetch changes up to aa6566a71ec01c48ce12325e19d1027d7d11316f:

  highbank: enable application support (2013-03-04 20:02:32 +0800)

----------------------------------------------------------------
Jean-Christophe PLAGNIOL-VILLARD (20):
      Makefile: x_flags prepare for apps support
      tlsf_malloc: drop duplicate include
      kbuild: add application (app) target
      Introduce application (app) support
      app: Introduce libc support
      app: add some utils
      app: Introduce example application
      filetype: add barebox arm application
      arm: add application support
      app: printf: use HelenOS verison with wide char support
      app: printf: add version from contiki
      app: add tinycurses support
      app: curses: add pdcurses
      app: add test curses
      app: pdcurses: add libmenu
      app: pdcurses: add libform
      app: curses: add menu example
      app: curses: add panel example
      app: curses: add form example
      highbank: enable application support

 Makefile                                       |   53 ++-
 apps/Kconfig                                   |   60 +++
 apps/Makefile                                  |   32 ++
 apps/example/Makefile                          |   14 +
 apps/example/example.h                         |    7 +
 apps/example/list.c                            |   98 +++++
 apps/example/ls.c                              |  127 ++++++
 apps/example/main.c                            |  231 +++++++++++
 apps/example/setjmp.c                          |   24 ++
 apps/form_curses/Makefile                      |   11 +
 apps/form_curses/main.c                        |  113 ++++++
 apps/include/appinfo.h                         |   60 +++
 apps/include/assert.h                          |   32 ++
 apps/include/common.h                          |   28 ++
 apps/include/ctype.h                           |  100 +++++
 apps/include/dirent.h                          |   24 ++
 apps/include/errno.h                           |   24 ++
 apps/include/fcntl.h                           |   25 ++
 apps/include/getopt.h                          |   76 ++++
 apps/include/libc_config.h                     |  139 +++++++
 apps/include/limits.h                          |   38 ++
 apps/include/malloc.h                          |   30 ++
 apps/include/module.h                          |    3 +
 apps/include/sections.h                        |   29 ++
 apps/include/setjmp.h                          |   25 ++
 apps/include/stddef.h                          |    1 +
 apps/include/stdint.h                          |   23 ++
 apps/include/stdio.h                           |   69 ++++
 apps/include/stdlib.h                          |   32 ++
 apps/include/string.h                          |   53 +++
 apps/include/sys/ioctl.h                       |   12 +
 apps/include/sys/stat.h                        |   14 +
 apps/include/sys/syscall.h                     |   14 +
 apps/include/sys/types.h                       |   15 +
 apps/include/time.h                            |   27 ++
 apps/include/unistd.h                          |   46 +++
 apps/include/utils/ansi.h                      |   37 ++
 apps/include/utils/getchar.h                   |   22 ++
 apps/include/utils/list.h                      |  114 ++++++
 apps/include/utils/termcap.h                   |   23 ++
 apps/include/wchar.h                           |   33 ++
 apps/lib/Kconfig                               |    1 +
 apps/lib/Makefile                              |    1 +
 apps/lib/Makefile.include                      |    1 +
 apps/lib/curses/Kconfig                        |   29 ++
 apps/lib/curses/Makefile                       |    2 +
 apps/lib/curses/Makefile.include               |    4 +
 apps/lib/curses/pdcurses/Makefile              |   25 ++
 apps/lib/curses/pdcurses/Makefile.include      |    3 +
 apps/lib/curses/pdcurses/backend/Makefile      |    6 +
 apps/lib/curses/pdcurses/backend/barebox.h     |   21 +
 apps/lib/curses/pdcurses/backend/config.h      |  136 +++++++
 apps/lib/curses/pdcurses/backend/pdcdisp.c     |  107 ++++++
 apps/lib/curses/pdcurses/backend/pdcgetsc.c    |   47 +++
 apps/lib/curses/pdcurses/backend/pdckbd.c      |  161 ++++++++
 apps/lib/curses/pdcurses/backend/pdcscrn.c     |  162 ++++++++
 apps/lib/curses/pdcurses/backend/pdcsetsc.c    |   35 ++
 apps/lib/curses/pdcurses/backend/pdcutil.c     |   26 ++
 apps/lib/curses/pdcurses/form/Makefile         |   42 ++
 apps/lib/curses/pdcurses/form/READ.ME          |   42 ++
 apps/lib/curses/pdcurses/form/f_trace.c        |   70 ++++
 apps/lib/curses/pdcurses/form/fld_arg.c        |   98 +++++
 apps/lib/curses/pdcurses/form/fld_attr.c       |  119 ++++++
 apps/lib/curses/pdcurses/form/fld_current.c    |  137 +++++++
 apps/lib/curses/pdcurses/form/fld_def.c        |  399 +++++++++++++++++++
 apps/lib/curses/pdcurses/form/fld_dup.c        |  101 +++++
 apps/lib/curses/pdcurses/form/fld_ftchoice.c   |   70 ++++
 apps/lib/curses/pdcurses/form/fld_ftlink.c     |   87 +++++
 apps/lib/curses/pdcurses/form/fld_info.c       |  113 ++++++
 apps/lib/curses/pdcurses/form/fld_just.c       |   86 +++++
 apps/lib/curses/pdcurses/form/fld_link.c       |   96 +++++
 apps/lib/curses/pdcurses/form/fld_max.c        |   77 ++++
 apps/lib/curses/pdcurses/form/fld_move.c       |   64 ++++
 apps/lib/curses/pdcurses/form/fld_newftyp.c    |  143 +++++++
 apps/lib/curses/pdcurses/form/fld_opts.c       |  138 +++++++
 apps/lib/curses/pdcurses/form/fld_pad.c        |   85 ++++
 apps/lib/curses/pdcurses/form/fld_page.c       |   82 ++++
 apps/lib/curses/pdcurses/form/fld_stat.c       |   79 ++++
 apps/lib/curses/pdcurses/form/fld_type.c       |   97 +++++
 apps/lib/curses/pdcurses/form/fld_user.c       |   72 ++++
 apps/lib/curses/pdcurses/form/form.h           |  423 ++++++++++++++++++++
 apps/lib/curses/pdcurses/form/form.priv.h      |  299 +++++++++++++++
 apps/lib/curses/pdcurses/form/frm_cursor.c     |   70 ++++
 apps/lib/curses/pdcurses/form/frm_data.c       |  193 ++++++++++
 apps/lib/curses/pdcurses/form/frm_def.c        |  448 ++++++++++++++++++++++
 apps/lib/curses/pdcurses/form/frm_driver.c     | 4646 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 apps/lib/curses/pdcurses/form/frm_hook.c       |  142 +++++++
 apps/lib/curses/pdcurses/form/frm_opts.c       |  127 ++++++
 apps/lib/curses/pdcurses/form/frm_page.c       |  106 +++++
 apps/lib/curses/pdcurses/form/frm_post.c       |  124 ++++++
 apps/lib/curses/pdcurses/form/frm_req_name.c   |  170 ++++++++
 apps/lib/curses/pdcurses/form/frm_scale.c      |   69 ++++
 apps/lib/curses/pdcurses/form/frm_sub.c        |   86 +++++
 apps/lib/curses/pdcurses/form/frm_user.c       |   72 ++++
 apps/lib/curses/pdcurses/form/frm_win.c        |   92 +++++
 apps/lib/curses/pdcurses/form/fty_alnum.c      |  202 ++++++++++
 apps/lib/curses/pdcurses/form/fty_alpha.c      |  202 ++++++++++
 apps/lib/curses/pdcurses/form/fty_enum.c       |  442 +++++++++++++++++++++
 apps/lib/curses/pdcurses/form/fty_generic.c    |  297 ++++++++++++++
 apps/lib/curses/pdcurses/form/fty_int.c        |  293 ++++++++++++++
 apps/lib/curses/pdcurses/form/fty_ipv4.c       |  120 ++++++
 apps/lib/curses/pdcurses/form/fty_num.c        |  339 ++++++++++++++++
 apps/lib/curses/pdcurses/form/fty_regex.c      |  350 +++++++++++++++++
 apps/lib/curses/pdcurses/include/curses.h      | 1378 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 apps/lib/curses/pdcurses/include/nc_alloc.h    |    4 +
 apps/lib/curses/pdcurses/include/ncurses_cfg.h |   40 ++
 apps/lib/curses/pdcurses/include/panel.h       |   58 +++
 apps/lib/curses/pdcurses/menu/Makefile         |   26 ++
 apps/lib/curses/pdcurses/menu/READ.ME          |   42 ++
 apps/lib/curses/pdcurses/menu/eti.h            |   54 +++
 apps/lib/curses/pdcurses/menu/m_attribs.c      |  144 +++++++
 apps/lib/curses/pdcurses/menu/m_cursor.c       |  112 ++++++
 apps/lib/curses/pdcurses/menu/m_driver.c       |  556 +++++++++++++++++++++++++++
 apps/lib/curses/pdcurses/menu/m_format.c       |  131 +++++++
 apps/lib/curses/pdcurses/menu/m_global.c       |  598 +++++++++++++++++++++++++++++
 apps/lib/curses/pdcurses/menu/m_hook.c         |  151 ++++++++
 apps/lib/curses/pdcurses/menu/m_item_cur.c     |  113 ++++++
 apps/lib/curses/pdcurses/menu/m_item_nam.c     |   72 ++++
 apps/lib/curses/pdcurses/menu/m_item_new.c     |  275 +++++++++++++
 apps/lib/curses/pdcurses/menu/m_item_opt.c     |  159 ++++++++
 apps/lib/curses/pdcurses/menu/m_item_top.c     |  107 ++++++
 apps/lib/curses/pdcurses/menu/m_item_use.c     |   76 ++++
 apps/lib/curses/pdcurses/menu/m_item_val.c     |  104 +++++
 apps/lib/curses/pdcurses/menu/m_item_vis.c     |   68 ++++
 apps/lib/curses/pdcurses/menu/m_items.c        |  110 ++++++
 apps/lib/curses/pdcurses/menu/m_new.c          |  142 +++++++
 apps/lib/curses/pdcurses/menu/m_opts.c         |  183 +++++++++
 apps/lib/curses/pdcurses/menu/m_pad.c          |   95 +++++
 apps/lib/curses/pdcurses/menu/m_pattern.c      |  124 ++++++
 apps/lib/curses/pdcurses/menu/m_post.c         |  377 ++++++++++++++++++
 apps/lib/curses/pdcurses/menu/m_req_name.c     |  125 ++++++
 apps/lib/curses/pdcurses/menu/m_scale.c        |   76 ++++
 apps/lib/curses/pdcurses/menu/m_spacing.c      |  113 ++++++
 apps/lib/curses/pdcurses/menu/m_sub.c          |  100 +++++
 apps/lib/curses/pdcurses/menu/m_trace.c        |   77 ++++
 apps/lib/curses/pdcurses/menu/m_userptr.c      |   76 ++++
 apps/lib/curses/pdcurses/menu/m_win.c          |  100 +++++
 apps/lib/curses/pdcurses/menu/menu.h           |  261 +++++++++++++
 apps/lib/curses/pdcurses/menu/menu.priv.h      |  157 ++++++++
 apps/lib/curses/pdcurses/menu/mf_common.h      |   95 +++++
 apps/lib/curses/pdcurses/pdcurses/Makefile     |   39 ++
 apps/lib/curses/pdcurses/pdcurses/README       |   25 ++
 apps/lib/curses/pdcurses/pdcurses/addch.c      |  408 ++++++++++++++++++++
 apps/lib/curses/pdcurses/pdcurses/addchstr.c   |  242 ++++++++++++
 apps/lib/curses/pdcurses/pdcurses/addstr.c     |  237 ++++++++++++
 apps/lib/curses/pdcurses/pdcurses/attr.c       |  349 +++++++++++++++++
 apps/lib/curses/pdcurses/pdcurses/beep.c       |   65 ++++
 apps/lib/curses/pdcurses/pdcurses/bkgd.c       |  220 +++++++++++
 apps/lib/curses/pdcurses/pdcurses/border.c     |  408 ++++++++++++++++++++
 apps/lib/curses/pdcurses/pdcurses/clear.c      |  154 ++++++++
 apps/lib/curses/pdcurses/pdcurses/color.c      |  295 ++++++++++++++
 apps/lib/curses/pdcurses/pdcurses/curspriv.h   |  146 +++++++
 apps/lib/curses/pdcurses/pdcurses/debug.c      |   81 ++++
 apps/lib/curses/pdcurses/pdcurses/delch.c      |   93 +++++
 apps/lib/curses/pdcurses/pdcurses/deleteln.c   |  208 ++++++++++
 apps/lib/curses/pdcurses/pdcurses/deprec.c     |   29 ++
 apps/lib/curses/pdcurses/pdcurses/getch.c      |  410 ++++++++++++++++++++
 apps/lib/curses/pdcurses/pdcurses/getstr.c     |  471 +++++++++++++++++++++++
 apps/lib/curses/pdcurses/pdcurses/getyx.c      |  143 +++++++
 apps/lib/curses/pdcurses/pdcurses/inch.c       |  125 ++++++
 apps/lib/curses/pdcurses/pdcurses/inchstr.c    |  211 ++++++++++
 apps/lib/curses/pdcurses/pdcurses/initscr.c    |  339 ++++++++++++++++
 apps/lib/curses/pdcurses/pdcurses/inopts.c     |  321 ++++++++++++++++
 apps/lib/curses/pdcurses/pdcurses/insch.c      |  268 +++++++++++++
 apps/lib/curses/pdcurses/pdcurses/insstr.c     |  261 +++++++++++++
 apps/lib/curses/pdcurses/pdcurses/instr.c      |  243 ++++++++++++
 apps/lib/curses/pdcurses/pdcurses/kernel.c     |  256 +++++++++++++
 apps/lib/curses/pdcurses/pdcurses/keyname.c    |  125 ++++++
 apps/lib/curses/pdcurses/pdcurses/mouse.c      |  429 +++++++++++++++++++++
 apps/lib/curses/pdcurses/pdcurses/move.c       |   54 +++
 apps/lib/curses/pdcurses/pdcurses/outopts.c    |  156 ++++++++
 apps/lib/curses/pdcurses/pdcurses/overlay.c    |  256 +++++++++++++
 apps/lib/curses/pdcurses/pdcurses/pad.c        |  259 +++++++++++++
 apps/lib/curses/pdcurses/pdcurses/panel.c      |  630 ++++++++++++++++++++++++++++++
 apps/lib/curses/pdcurses/pdcurses/printw.c     |  123 ++++++
 apps/lib/curses/pdcurses/pdcurses/refresh.c    |  276 +++++++++++++
 apps/lib/curses/pdcurses/pdcurses/scanw.c      |  575 +++++++++++++++++++++++++++
 apps/lib/curses/pdcurses/pdcurses/scr_dump.c   |  210 ++++++++++
 apps/lib/curses/pdcurses/pdcurses/scroll.c     |   98 +++++
 apps/lib/curses/pdcurses/pdcurses/slk.c        |  643 +++++++++++++++++++++++++++++++
 apps/lib/curses/pdcurses/pdcurses/term.h       |   57 +++
 apps/lib/curses/pdcurses/pdcurses/termattr.c   |  176 +++++++++
 apps/lib/curses/pdcurses/pdcurses/terminfo.c   |  215 +++++++++++
 apps/lib/curses/pdcurses/pdcurses/touch.c      |  160 ++++++++
 apps/lib/curses/pdcurses/pdcurses/util.c       |  309 +++++++++++++++
 apps/lib/curses/pdcurses/pdcurses/window.c     |  562 +++++++++++++++++++++++++++
 apps/lib/curses/tinycurses/Makefile            |    3 +
 apps/lib/curses/tinycurses/Makefile.include    |    1 +
 apps/lib/curses/tinycurses/colors.c            |   62 +++
 apps/lib/curses/tinycurses/curses.h            | 1680 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 apps/lib/curses/tinycurses/curses.priv.h       | 1317 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 apps/lib/curses/tinycurses/keyboard.c          |  247 ++++++++++++
 apps/lib/curses/tinycurses/local.h             |   89 +++++
 apps/lib/curses/tinycurses/tinycurses.c        | 1016 ++++++++++++++++++++++++++++++++++++++++++++++++
 apps/libc/Kconfig                              |   44 +++
 apps/libc/Makefile                             |   38 ++
 apps/libc/appinfo.c                            |   35 ++
 apps/libc/contiki/Makefile                     |    1 +
 apps/libc/contiki/strformat.c                  |  621 ++++++++++++++++++++++++++++++
 apps/libc/contiki/strformat.h                  |   25 ++
 apps/libc/contiki/vsprintf.c                   |  116 ++++++
 apps/libc/dirent.c                             |   59 +++
 apps/libc/errno.c                              |   19 +
 apps/libc/fcntl.c                              |   25 ++
 apps/libc/flags.c                              |   76 ++++
 apps/libc/getopt.c                             |  127 ++++++
 apps/libc/getopt_long.c                        |  625 ++++++++++++++++++++++++++++++
 apps/libc/helenos/Makefile                     |    4 +
 apps/libc/helenos/align.h                      |   63 +++
 apps/libc/helenos/assert.h                     |    2 +
 apps/libc/helenos/ctype.c                      |   52 +++
 apps/libc/helenos/printf_core.c                |  905 +++++++++++++++++++++++++++++++++++++++++++
 apps/libc/helenos/printf_core.h                |   59 +++
 apps/libc/helenos/stdio.c                      |  153 ++++++++
 apps/libc/helenos/str.c                        | 1755 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 apps/libc/helenos/str.h                        |  135 +++++++
 apps/libc/helenos/vsnprintf.c                  |  187 +++++++++
 apps/libc/malloc.c                             |   50 +++
 apps/libc/malloc.h                             |    2 +
 apps/libc/private.h                            |   18 +
 apps/libc/stdio.c                              |  275 +++++++++++++
 apps/libc/stdlib.c                             |   77 ++++
 apps/libc/string.c                             |  159 ++++++++
 apps/libc/sys/Makefile                         |    2 +
 apps/libc/sys/stat.c                           |   25 ++
 apps/libc/syscalls.c                           |  103 +++++
 apps/libc/time.c                               |   41 ++
 apps/libc/unistd.c                             |  108 ++++++
 apps/menu_curses/Makefile                      |   11 +
 apps/menu_curses/main.c                        |  127 ++++++
 apps/panel_curses/Makefile                     |   11 +
 apps/panel_curses/main.c                       |  118 ++++++
 apps/test_curses/Makefile                      |   11 +
 apps/test_curses/main.c                        |  172 +++++++++
 apps/utils/Makefile                            |    2 +
 apps/utils/getchar.c                           |   43 +++
 apps/utils/termcap.c                           |   97 +++++
 arch/arm/Kconfig                               |    2 +
 arch/arm/Makefile                              |   13 +-
 arch/arm/apps/Kconfig                          |   11 +
 arch/arm/apps/Makefile                         |    6 +
 arch/arm/apps/apps.lds.S                       |   64 ++++
 arch/arm/apps/binfmt.c                         |  111 ++++++
 arch/arm/apps/head.S                           |   59 +++
 arch/arm/apps/include/arch/asm/macro.h         |   46 +++
 arch/arm/apps/include/arch/setjmp.h            |   26 ++
 arch/arm/apps/raise.c                          |   27 ++
 arch/arm/apps/setjmp.S                         |   60 +++
 arch/arm/apps/start.c                          |   35 ++
 arch/arm/configs/highbank_defconfig            |   21 +-
 arch/mips/Makefile                             |    8 +-
 arch/ppc/Makefile                              |    4 +-
 arch/sandbox/Makefile                          |    4 +-
 arch/x86/Makefile                              |    4 +-
 commands/Kconfig                               |    7 +
 commands/Makefile                              |    1 +
 commands/appinfo.c                             |  119 ++++++
 common/Kconfig                                 |    3 +
 common/filetype.c                              |   35 ++
 common/tlsf_malloc.c                           |    2 -
 include/apps/syscall_init.h                    |   23 ++
 include/apps/syscalls.h                        |   76 ++++
 include/apps/types.h                           |   24 ++
 include/filetype.h                             |    2 +
 include/linux/license.h                        |   14 +
 lib/Makefile                                   |    1 +
 lib/apps/Makefile                              |    1 +
 lib/apps/syscalls.c                            |  413 ++++++++++++++++++++
 scripts/Makefile.build                         |   78 +++-
 scripts/Makefile.lib                           |   36 +-
 270 files changed, 44450 insertions(+), 32 deletions(-)
 create mode 100644 apps/Kconfig
 create mode 100644 apps/Makefile
 create mode 100644 apps/example/Makefile
 create mode 100644 apps/example/example.h
 create mode 100644 apps/example/list.c
 create mode 100644 apps/example/ls.c
 create mode 100644 apps/example/main.c
 create mode 100644 apps/example/setjmp.c
 create mode 100644 apps/form_curses/Makefile
 create mode 100644 apps/form_curses/main.c
 create mode 100644 apps/include/appinfo.h
 create mode 100644 apps/include/assert.h
 create mode 100644 apps/include/common.h
 create mode 100644 apps/include/ctype.h
 create mode 100644 apps/include/dirent.h
 create mode 100644 apps/include/errno.h
 create mode 100644 apps/include/fcntl.h
 create mode 100644 apps/include/getopt.h
 create mode 100644 apps/include/libc_config.h
 create mode 100644 apps/include/limits.h
 create mode 100644 apps/include/malloc.h
 create mode 100644 apps/include/module.h
 create mode 100644 apps/include/sections.h
 create mode 100644 apps/include/setjmp.h
 create mode 100644 apps/include/stddef.h
 create mode 100644 apps/include/stdint.h
 create mode 100644 apps/include/stdio.h
 create mode 100644 apps/include/stdlib.h
 create mode 100644 apps/include/string.h
 create mode 100644 apps/include/sys/ioctl.h
 create mode 100644 apps/include/sys/stat.h
 create mode 100644 apps/include/sys/syscall.h
 create mode 100644 apps/include/sys/types.h
 create mode 100644 apps/include/time.h
 create mode 100644 apps/include/unistd.h
 create mode 100644 apps/include/utils/ansi.h
 create mode 100644 apps/include/utils/getchar.h
 create mode 100644 apps/include/utils/list.h
 create mode 100644 apps/include/utils/termcap.h
 create mode 100644 apps/include/wchar.h
 create mode 100644 apps/lib/Kconfig
 create mode 100644 apps/lib/Makefile
 create mode 100644 apps/lib/Makefile.include
 create mode 100644 apps/lib/curses/Kconfig
 create mode 100644 apps/lib/curses/Makefile
 create mode 100644 apps/lib/curses/Makefile.include
 create mode 100644 apps/lib/curses/pdcurses/Makefile
 create mode 100644 apps/lib/curses/pdcurses/Makefile.include
 create mode 100644 apps/lib/curses/pdcurses/backend/Makefile
 create mode 100644 apps/lib/curses/pdcurses/backend/barebox.h
 create mode 100644 apps/lib/curses/pdcurses/backend/config.h
 create mode 100644 apps/lib/curses/pdcurses/backend/pdcdisp.c
 create mode 100644 apps/lib/curses/pdcurses/backend/pdcgetsc.c
 create mode 100644 apps/lib/curses/pdcurses/backend/pdckbd.c
 create mode 100644 apps/lib/curses/pdcurses/backend/pdcscrn.c
 create mode 100644 apps/lib/curses/pdcurses/backend/pdcsetsc.c
 create mode 100644 apps/lib/curses/pdcurses/backend/pdcutil.c
 create mode 100644 apps/lib/curses/pdcurses/form/Makefile
 create mode 100644 apps/lib/curses/pdcurses/form/READ.ME
 create mode 100644 apps/lib/curses/pdcurses/form/f_trace.c
 create mode 100644 apps/lib/curses/pdcurses/form/fld_arg.c
 create mode 100644 apps/lib/curses/pdcurses/form/fld_attr.c
 create mode 100644 apps/lib/curses/pdcurses/form/fld_current.c
 create mode 100644 apps/lib/curses/pdcurses/form/fld_def.c
 create mode 100644 apps/lib/curses/pdcurses/form/fld_dup.c
 create mode 100644 apps/lib/curses/pdcurses/form/fld_ftchoice.c
 create mode 100644 apps/lib/curses/pdcurses/form/fld_ftlink.c
 create mode 100644 apps/lib/curses/pdcurses/form/fld_info.c
 create mode 100644 apps/lib/curses/pdcurses/form/fld_just.c
 create mode 100644 apps/lib/curses/pdcurses/form/fld_link.c
 create mode 100644 apps/lib/curses/pdcurses/form/fld_max.c
 create mode 100644 apps/lib/curses/pdcurses/form/fld_move.c
 create mode 100644 apps/lib/curses/pdcurses/form/fld_newftyp.c
 create mode 100644 apps/lib/curses/pdcurses/form/fld_opts.c
 create mode 100644 apps/lib/curses/pdcurses/form/fld_pad.c
 create mode 100644 apps/lib/curses/pdcurses/form/fld_page.c
 create mode 100644 apps/lib/curses/pdcurses/form/fld_stat.c
 create mode 100644 apps/lib/curses/pdcurses/form/fld_type.c
 create mode 100644 apps/lib/curses/pdcurses/form/fld_user.c
 create mode 100644 apps/lib/curses/pdcurses/form/form.h
 create mode 100644 apps/lib/curses/pdcurses/form/form.priv.h
 create mode 100644 apps/lib/curses/pdcurses/form/frm_cursor.c
 create mode 100644 apps/lib/curses/pdcurses/form/frm_data.c
 create mode 100644 apps/lib/curses/pdcurses/form/frm_def.c
 create mode 100644 apps/lib/curses/pdcurses/form/frm_driver.c
 create mode 100644 apps/lib/curses/pdcurses/form/frm_hook.c
 create mode 100644 apps/lib/curses/pdcurses/form/frm_opts.c
 create mode 100644 apps/lib/curses/pdcurses/form/frm_page.c
 create mode 100644 apps/lib/curses/pdcurses/form/frm_post.c
 create mode 100644 apps/lib/curses/pdcurses/form/frm_req_name.c
 create mode 100644 apps/lib/curses/pdcurses/form/frm_scale.c
 create mode 100644 apps/lib/curses/pdcurses/form/frm_sub.c
 create mode 100644 apps/lib/curses/pdcurses/form/frm_user.c
 create mode 100644 apps/lib/curses/pdcurses/form/frm_win.c
 create mode 100644 apps/lib/curses/pdcurses/form/fty_alnum.c
 create mode 100644 apps/lib/curses/pdcurses/form/fty_alpha.c
 create mode 100644 apps/lib/curses/pdcurses/form/fty_enum.c
 create mode 100644 apps/lib/curses/pdcurses/form/fty_generic.c
 create mode 100644 apps/lib/curses/pdcurses/form/fty_int.c
 create mode 100644 apps/lib/curses/pdcurses/form/fty_ipv4.c
 create mode 100644 apps/lib/curses/pdcurses/form/fty_num.c
 create mode 100644 apps/lib/curses/pdcurses/form/fty_regex.c
 create mode 100644 apps/lib/curses/pdcurses/include/curses.h
 create mode 100644 apps/lib/curses/pdcurses/include/nc_alloc.h
 create mode 100644 apps/lib/curses/pdcurses/include/ncurses_cfg.h
 create mode 100644 apps/lib/curses/pdcurses/include/panel.h
 create mode 100644 apps/lib/curses/pdcurses/menu/Makefile
 create mode 100644 apps/lib/curses/pdcurses/menu/READ.ME
 create mode 100644 apps/lib/curses/pdcurses/menu/eti.h
 create mode 100644 apps/lib/curses/pdcurses/menu/m_attribs.c
 create mode 100644 apps/lib/curses/pdcurses/menu/m_cursor.c
 create mode 100644 apps/lib/curses/pdcurses/menu/m_driver.c
 create mode 100644 apps/lib/curses/pdcurses/menu/m_format.c
 create mode 100644 apps/lib/curses/pdcurses/menu/m_global.c
 create mode 100644 apps/lib/curses/pdcurses/menu/m_hook.c
 create mode 100644 apps/lib/curses/pdcurses/menu/m_item_cur.c
 create mode 100644 apps/lib/curses/pdcurses/menu/m_item_nam.c
 create mode 100644 apps/lib/curses/pdcurses/menu/m_item_new.c
 create mode 100644 apps/lib/curses/pdcurses/menu/m_item_opt.c
 create mode 100644 apps/lib/curses/pdcurses/menu/m_item_top.c
 create mode 100644 apps/lib/curses/pdcurses/menu/m_item_use.c
 create mode 100644 apps/lib/curses/pdcurses/menu/m_item_val.c
 create mode 100644 apps/lib/curses/pdcurses/menu/m_item_vis.c
 create mode 100644 apps/lib/curses/pdcurses/menu/m_items.c
 create mode 100644 apps/lib/curses/pdcurses/menu/m_new.c
 create mode 100644 apps/lib/curses/pdcurses/menu/m_opts.c
 create mode 100644 apps/lib/curses/pdcurses/menu/m_pad.c
 create mode 100644 apps/lib/curses/pdcurses/menu/m_pattern.c
 create mode 100644 apps/lib/curses/pdcurses/menu/m_post.c
 create mode 100644 apps/lib/curses/pdcurses/menu/m_req_name.c
 create mode 100644 apps/lib/curses/pdcurses/menu/m_scale.c
 create mode 100644 apps/lib/curses/pdcurses/menu/m_spacing.c
 create mode 100644 apps/lib/curses/pdcurses/menu/m_sub.c
 create mode 100644 apps/lib/curses/pdcurses/menu/m_trace.c
 create mode 100644 apps/lib/curses/pdcurses/menu/m_userptr.c
 create mode 100644 apps/lib/curses/pdcurses/menu/m_win.c
 create mode 100644 apps/lib/curses/pdcurses/menu/menu.h
 create mode 100644 apps/lib/curses/pdcurses/menu/menu.priv.h
 create mode 100644 apps/lib/curses/pdcurses/menu/mf_common.h
 create mode 100644 apps/lib/curses/pdcurses/pdcurses/Makefile
 create mode 100644 apps/lib/curses/pdcurses/pdcurses/README
 create mode 100644 apps/lib/curses/pdcurses/pdcurses/addch.c
 create mode 100644 apps/lib/curses/pdcurses/pdcurses/addchstr.c
 create mode 100644 apps/lib/curses/pdcurses/pdcurses/addstr.c
 create mode 100644 apps/lib/curses/pdcurses/pdcurses/attr.c
 create mode 100644 apps/lib/curses/pdcurses/pdcurses/beep.c
 create mode 100644 apps/lib/curses/pdcurses/pdcurses/bkgd.c
 create mode 100644 apps/lib/curses/pdcurses/pdcurses/border.c
 create mode 100644 apps/lib/curses/pdcurses/pdcurses/clear.c
 create mode 100644 apps/lib/curses/pdcurses/pdcurses/color.c
 create mode 100644 apps/lib/curses/pdcurses/pdcurses/curspriv.h
 create mode 100644 apps/lib/curses/pdcurses/pdcurses/debug.c
 create mode 100644 apps/lib/curses/pdcurses/pdcurses/delch.c
 create mode 100644 apps/lib/curses/pdcurses/pdcurses/deleteln.c
 create mode 100644 apps/lib/curses/pdcurses/pdcurses/deprec.c
 create mode 100644 apps/lib/curses/pdcurses/pdcurses/getch.c
 create mode 100644 apps/lib/curses/pdcurses/pdcurses/getstr.c
 create mode 100644 apps/lib/curses/pdcurses/pdcurses/getyx.c
 create mode 100644 apps/lib/curses/pdcurses/pdcurses/inch.c
 create mode 100644 apps/lib/curses/pdcurses/pdcurses/inchstr.c
 create mode 100644 apps/lib/curses/pdcurses/pdcurses/initscr.c
 create mode 100644 apps/lib/curses/pdcurses/pdcurses/inopts.c
 create mode 100644 apps/lib/curses/pdcurses/pdcurses/insch.c
 create mode 100644 apps/lib/curses/pdcurses/pdcurses/insstr.c
 create mode 100644 apps/lib/curses/pdcurses/pdcurses/instr.c
 create mode 100644 apps/lib/curses/pdcurses/pdcurses/kernel.c
 create mode 100644 apps/lib/curses/pdcurses/pdcurses/keyname.c
 create mode 100644 apps/lib/curses/pdcurses/pdcurses/mouse.c
 create mode 100644 apps/lib/curses/pdcurses/pdcurses/move.c
 create mode 100644 apps/lib/curses/pdcurses/pdcurses/outopts.c
 create mode 100644 apps/lib/curses/pdcurses/pdcurses/overlay.c
 create mode 100644 apps/lib/curses/pdcurses/pdcurses/pad.c
 create mode 100644 apps/lib/curses/pdcurses/pdcurses/panel.c
 create mode 100644 apps/lib/curses/pdcurses/pdcurses/printw.c
 create mode 100644 apps/lib/curses/pdcurses/pdcurses/refresh.c
 create mode 100644 apps/lib/curses/pdcurses/pdcurses/scanw.c
 create mode 100644 apps/lib/curses/pdcurses/pdcurses/scr_dump.c
 create mode 100644 apps/lib/curses/pdcurses/pdcurses/scroll.c
 create mode 100644 apps/lib/curses/pdcurses/pdcurses/slk.c
 create mode 100644 apps/lib/curses/pdcurses/pdcurses/term.h
 create mode 100644 apps/lib/curses/pdcurses/pdcurses/termattr.c
 create mode 100644 apps/lib/curses/pdcurses/pdcurses/terminfo.c
 create mode 100644 apps/lib/curses/pdcurses/pdcurses/touch.c
 create mode 100644 apps/lib/curses/pdcurses/pdcurses/util.c
 create mode 100644 apps/lib/curses/pdcurses/pdcurses/window.c
 create mode 100644 apps/lib/curses/tinycurses/Makefile
 create mode 100644 apps/lib/curses/tinycurses/Makefile.include
 create mode 100644 apps/lib/curses/tinycurses/colors.c
 create mode 100644 apps/lib/curses/tinycurses/curses.h
 create mode 100644 apps/lib/curses/tinycurses/curses.priv.h
 create mode 100644 apps/lib/curses/tinycurses/keyboard.c
 create mode 100644 apps/lib/curses/tinycurses/local.h
 create mode 100644 apps/lib/curses/tinycurses/tinycurses.c
 create mode 100644 apps/libc/Kconfig
 create mode 100644 apps/libc/Makefile
 create mode 100644 apps/libc/appinfo.c
 create mode 100644 apps/libc/contiki/Makefile
 create mode 100644 apps/libc/contiki/strformat.c
 create mode 100644 apps/libc/contiki/strformat.h
 create mode 100644 apps/libc/contiki/vsprintf.c
 create mode 100644 apps/libc/dirent.c
 create mode 100644 apps/libc/errno.c
 create mode 100644 apps/libc/fcntl.c
 create mode 100644 apps/libc/flags.c
 create mode 100644 apps/libc/getopt.c
 create mode 100644 apps/libc/getopt_long.c
 create mode 100644 apps/libc/helenos/Makefile
 create mode 100644 apps/libc/helenos/align.h
 create mode 100644 apps/libc/helenos/assert.h
 create mode 100644 apps/libc/helenos/ctype.c
 create mode 100644 apps/libc/helenos/printf_core.c
 create mode 100644 apps/libc/helenos/printf_core.h
 create mode 100644 apps/libc/helenos/stdio.c
 create mode 100644 apps/libc/helenos/str.c
 create mode 100644 apps/libc/helenos/str.h
 create mode 100644 apps/libc/helenos/vsnprintf.c
 create mode 100644 apps/libc/malloc.c
 create mode 100644 apps/libc/malloc.h
 create mode 100644 apps/libc/private.h
 create mode 100644 apps/libc/stdio.c
 create mode 100644 apps/libc/stdlib.c
 create mode 100644 apps/libc/string.c
 create mode 100644 apps/libc/sys/Makefile
 create mode 100644 apps/libc/sys/stat.c
 create mode 100644 apps/libc/syscalls.c
 create mode 100644 apps/libc/time.c
 create mode 100644 apps/libc/unistd.c
 create mode 100644 apps/menu_curses/Makefile
 create mode 100644 apps/menu_curses/main.c
 create mode 100644 apps/panel_curses/Makefile
 create mode 100644 apps/panel_curses/main.c
 create mode 100644 apps/test_curses/Makefile
 create mode 100644 apps/test_curses/main.c
 create mode 100644 apps/utils/Makefile
 create mode 100644 apps/utils/getchar.c
 create mode 100644 apps/utils/termcap.c
 create mode 100644 arch/arm/apps/Kconfig
 create mode 100644 arch/arm/apps/Makefile
 create mode 100644 arch/arm/apps/apps.lds.S
 create mode 100644 arch/arm/apps/binfmt.c
 create mode 100644 arch/arm/apps/head.S
 create mode 100644 arch/arm/apps/include/arch/asm/macro.h
 create mode 100644 arch/arm/apps/include/arch/setjmp.h
 create mode 100644 arch/arm/apps/raise.c
 create mode 100644 arch/arm/apps/setjmp.S
 create mode 100644 arch/arm/apps/start.c
 create mode 100644 commands/appinfo.c
 create mode 100644 include/apps/syscall_init.h
 create mode 100644 include/apps/syscalls.h
 create mode 100644 include/apps/types.h
 create mode 100644 include/linux/license.h
 create mode 100644 lib/apps/Makefile
 create mode 100644 lib/apps/syscalls.c

Best Regards,
J.

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH 01/20] Makefile: x_flags prepare for apps support
  2013-03-06  9:26 [RFC PATCH 00/20] introduce application support Jean-Christophe PLAGNIOL-VILLARD
@ 2013-03-06  9:29 ` Jean-Christophe PLAGNIOL-VILLARD
  2013-03-06  9:29   ` [PATCH 02/20] tlsf_malloc: drop duplicate include Jean-Christophe PLAGNIOL-VILLARD
                     ` (18 more replies)
  2013-03-07  7:36 ` [RFC PATCH 00/20] introduce " Sascha Hauer
  1 sibling, 19 replies; 31+ messages in thread
From: Jean-Christophe PLAGNIOL-VILLARD @ 2013-03-06  9:29 UTC (permalink / raw)
  To: barebox

only include barebox header for barebox flags

Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
---
 Makefile              |    5 +++--
 arch/arm/Makefile     |    7 ++++---
 arch/mips/Makefile    |    8 ++++----
 arch/ppc/Makefile     |    4 ++--
 arch/sandbox/Makefile |    4 ++--
 arch/x86/Makefile     |    4 ++--
 scripts/Makefile.lib  |   13 +++++++++----
 7 files changed, 26 insertions(+), 19 deletions(-)

diff --git a/Makefile b/Makefile
index b5819fc..4df6464 100644
--- a/Makefile
+++ b/Makefile
@@ -297,7 +297,7 @@ LINUXINCLUDE    := -Iinclude \
                    -include include/generated/autoconf.h \
                    -include $(srctree)/include/linux/kconfig.h
 
-CPPFLAGS        := -D__KERNEL__ -D__BAREBOX__ $(LINUXINCLUDE) -fno-builtin -ffreestanding
+CPPFLAGS        := -D__KERNEL__ -D__BAREBOX__ -fno-builtin -ffreestanding
 
 CFLAGS          := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \
                    -fno-strict-aliasing -fno-common -Os -pipe
@@ -315,6 +315,7 @@ export CPP AR NM STRIP OBJCOPY OBJDUMP MAKE AWK GENKSYMS PERL UTS_MACHINE
 export HOSTCXX HOSTCXXFLAGS LDFLAGS_MODULE CHECK CHECKFLAGS
 
 export CPPFLAGS NOSTDINC_FLAGS LINUXINCLUDE OBJCOPYFLAGS LDFLAGS
+export AFLAGS_LINUXINCLUDE
 export CFLAGS CFLAGS_KERNEL
 export AFLAGS AFLAGS_KERNEL
 
@@ -1212,7 +1213,7 @@ quiet_cmd_rmfiles = $(if $(wildcard $(rm-files)),CLEAN   $(wildcard $(rm-files))
 
 
 a_flags = -Wp,-MD,$(depfile) $(AFLAGS) $(AFLAGS_KERNEL) \
-	  $(NOSTDINC_FLAGS) $(CPPFLAGS) \
+	  $(NOSTDINC_FLAGS) $(LINUXINCLUDE) $(AFLAGS_LINUXINCLUDE) $(CPPFLAGS) \
 	  $(modkern_aflags) $(EXTRA_AFLAGS) $(AFLAGS_$(basetarget).o)
 
 quiet_cmd_as_o_S = AS      $@
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index b98d6b8..100a3c4 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -47,7 +47,8 @@ AFLAGS_THUMB2	:=$(CFLAGS_THUMB2) -Wa$(comma)-mthumb
 endif
 
 CPPFLAGS += $(CFLAGS_ABI) $(arch-y) $(tune-y) -msoft-float $(CFLAGS_THUMB2)
-AFLAGS   += -include asm/unified.h -msoft-float $(AFLAGS_THUMB2)
+AFLAGS_LINUXINCLUDE += -include asm/unified.h
+AFLAGS   += -msoft-float $(AFLAGS_THUMB2)
 
 # Machine directory name.  This list is sorted alphanumerically
 # by CONFIG_* macro name.
@@ -166,9 +167,9 @@ board-$(CONFIG_MACH_SABRESD)			:= freescale-mx6-sabresd
 machdirs := $(patsubst %,arch/arm/mach-%/,$(machine-y))
 
 ifeq ($(KBUILD_SRC),)
-CPPFLAGS += $(patsubst %,-I%include,$(machdirs))
+LINUXINCLUDE += $(patsubst %,-I%include,$(machdirs))
 else
-CPPFLAGS += $(patsubst %,-I$(srctree)/%include,$(machdirs))
+LINUXINCLUDE += $(patsubst %,-I$(srctree)/%include,$(machdirs))
 endif
 
 TEXT_BASE = $(CONFIG_TEXT_BASE)
diff --git a/arch/mips/Makefile b/arch/mips/Makefile
index 3c565a4..cd83f06 100644
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
@@ -81,9 +81,9 @@ board-$(CONFIG_BOARD_RZX50)	:= rzx50
 machdirs := $(patsubst %,arch/mips/mach-%/,$(machine-y))
 
 ifeq ($(KBUILD_SRC),)
-CPPFLAGS += $(patsubst %,-I%include,$(machdirs))
+LINUXINCLUDE += $(patsubst %,-I%include,$(machdirs))
 else
-CPPFLAGS += $(patsubst %,-I$(srctree)/%include,$(machdirs))
+LINUXINCLUDE += $(patsubst %,-I$(srctree)/%include,$(machdirs))
 endif
 
 ifeq ($(incdir-y),)
@@ -98,9 +98,9 @@ BOARD :=
 endif
 
 ifeq ($(KBUILD_SRC),)
-CPPFLAGS += -I$(BOARD)/include
+LINUXINCLUDE += -I$(BOARD)/include
 else
-CPPFLAGS += -I$(srctree)/$(BOARD)/include
+LINUXINCLUDE += -I$(srctree)/$(BOARD)/include
 endif
 
 ifneq ($(machine-y),)
diff --git a/arch/ppc/Makefile b/arch/ppc/Makefile
index f0322a2..0002bc7 100644
--- a/arch/ppc/Makefile
+++ b/arch/ppc/Makefile
@@ -31,9 +31,9 @@ endif
 machdirs := $(patsubst %,arch/ppc/mach-%/,$(machine-y))
 
 ifeq ($(KBUILD_SRC),)
-CPPFLAGS += $(patsubst %,-I%include,$(machdirs))
+LINUXINCLUDE += $(patsubst %,-I%include,$(machdirs))
 else
-CPPFLAGS += $(patsubst %,-I$(srctree)/%include,$(machdirs))
+LINUXINCLUDE += $(patsubst %,-I$(srctree)/%include,$(machdirs))
 endif
 
 archprepare: maketools
diff --git a/arch/sandbox/Makefile b/arch/sandbox/Makefile
index 596c8f8..061f2a0 100644
--- a/arch/sandbox/Makefile
+++ b/arch/sandbox/Makefile
@@ -25,9 +25,9 @@ CFLAGS += -Dmalloc=barebox_malloc -Dcalloc=barebox_calloc \
 machdirs := $(patsubst %,arch/sandbox/mach-%/,$(machine-y))
 
 ifeq ($(KBUILD_SRC),)
-CPPFLAGS += $(patsubst %,-I%include,$(machdirs))
+LINUXINCLUDE += $(patsubst %,-I%include,$(machdirs))
 else
-CPPFLAGS += $(patsubst %,-I$(srctree)/%include,$(machdirs))
+LINUXINCLUDE += $(patsubst %,-I$(srctree)/%include,$(machdirs))
 endif
 
 SUBARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \
diff --git a/arch/x86/Makefile b/arch/x86/Makefile
index 518b37f..1d933b8 100644
--- a/arch/x86/Makefile
+++ b/arch/x86/Makefile
@@ -17,9 +17,9 @@ endif
 machdirs := $(patsubst %,arch/x86/mach-%/,$(machine-y))
 
 ifeq ($(KBUILD_SRC),)
-CPPFLAGS += $(patsubst %,-I%include,$(machdirs))
+LINUXINCLUDE += $(patsubst %,-I%include,$(machdirs))
 else
-CPPFLAGS += $(patsubst %,-I$(srctree)/%include,$(machdirs))
+LINUXINCLUDE += $(patsubst %,-I$(srctree)/%include,$(machdirs))
 endif
 
 ifneq ($(board-y),)
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index 871c44b..7bb769b 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -130,16 +130,21 @@ __a_flags	=                          $(call flags,_a_flags)
 __cpp_flags     =                          $(call flags,_cpp_flags)
 endif
 
-c_flags        = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(CPPFLAGS) \
+___c_flags        = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(CPPFLAGS) \
 		 $(__c_flags) $(modkern_cflags) \
 		 -D"KBUILD_STR(s)=\#s" $(basename_flags) $(modname_flags)
 
-a_flags        = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(CPPFLAGS) \
+___a_flags        = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(CPPFLAGS) \
 		 $(__a_flags) $(modkern_aflags)
 
-cpp_flags      = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(__cpp_flags)
+___cpp_flags      = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(__cpp_flags)
 
-ld_flags       = $(LDFLAGS) $(EXTRA_LDFLAGS)
+___ld_flags       = $(LDFLAGS) $(EXTRA_LDFLAGS)
+
+c_flags        = $(LINUXINCLUDE) $(___c_flags)
+a_flags        = $(LINUXINCLUDE) $(AFLAGS_LINUXINCLUDE) $(___a_flags)
+cpp_flags      = $(LINUXINCLUDE) $(___cpp_flags)
+ld_flags       = $(___ld_flags)
 
 # Finds the multi-part object the current object will be linked into
 modname-multi = $(sort $(foreach m,$(multi-used),\
-- 
1.7.10.4


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH 02/20] tlsf_malloc: drop duplicate include
  2013-03-06  9:29 ` [PATCH 01/20] Makefile: x_flags prepare for apps support Jean-Christophe PLAGNIOL-VILLARD
@ 2013-03-06  9:29   ` Jean-Christophe PLAGNIOL-VILLARD
  2013-03-07  7:37     ` Sascha Hauer
  2013-03-06  9:29   ` [PATCH 03/20] kbuild: add application (app) target Jean-Christophe PLAGNIOL-VILLARD
                     ` (17 subsequent siblings)
  18 siblings, 1 reply; 31+ messages in thread
From: Jean-Christophe PLAGNIOL-VILLARD @ 2013-03-06  9:29 UTC (permalink / raw)
  To: barebox

config.h is not need and already inclued by Makefile

Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
---
 common/tlsf_malloc.c |    2 --
 1 file changed, 2 deletions(-)

diff --git a/common/tlsf_malloc.c b/common/tlsf_malloc.c
index 5c5bb61..cd01b56 100644
--- a/common/tlsf_malloc.c
+++ b/common/tlsf_malloc.c
@@ -17,10 +17,8 @@
  *
  */
 
-#include <config.h>
 #include <malloc.h>
 #include <string.h>
-#include <malloc.h>
 
 #include <stdio.h>
 #include <module.h>
-- 
1.7.10.4


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH 03/20] kbuild: add application (app) target
  2013-03-06  9:29 ` [PATCH 01/20] Makefile: x_flags prepare for apps support Jean-Christophe PLAGNIOL-VILLARD
  2013-03-06  9:29   ` [PATCH 02/20] tlsf_malloc: drop duplicate include Jean-Christophe PLAGNIOL-VILLARD
@ 2013-03-06  9:29   ` Jean-Christophe PLAGNIOL-VILLARD
  2013-03-06  9:29   ` [PATCH 04/20] Introduce application (app) support Jean-Christophe PLAGNIOL-VILLARD
                     ` (16 subsequent siblings)
  18 siblings, 0 replies; 31+ messages in thread
From: Jean-Christophe PLAGNIOL-VILLARD @ 2013-03-06  9:29 UTC (permalink / raw)
  To: barebox

This will allow to link compiled object (app-y) to the built-in-app.o across the source
tree that will be finally link to the applications (app-final-y).

Now we compile the source %.c in app-%.o and provide -D__APP__
so we can known in the source when it's compile for barebox or pbl or app.

Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
---
 Makefile               |    5 +++-
 scripts/Makefile.build |   78 +++++++++++++++++++++++++++++++++++++++++++++---
 scripts/Makefile.lib   |   23 ++++++++++++--
 3 files changed, 99 insertions(+), 7 deletions(-)

diff --git a/Makefile b/Makefile
index 4df6464..110f7aa 100644
--- a/Makefile
+++ b/Makefile
@@ -493,6 +493,7 @@ barebox-alldirs	:= $(sort $(barebox-dirs) $(patsubst %/,%,$(filter %/, \
 		     $(core-n) $(core-) $(drivers-n) $(drivers-) \
 		     $(net-n)  $(net-)  $(libs-n)    $(libs-))))
 
+app-common-y	:= $(patsubst %/, %/built-in-app.o, $(common-y))
 pbl-common-y	:= $(patsubst %/, %/built-in-pbl.o, $(common-y))
 common-y	:= $(patsubst %/, %/built-in.o, $(common-y))
 
@@ -523,6 +524,8 @@ common-y	:= $(patsubst %/, %/built-in.o, $(common-y))
 # System.map is generated to document addresses of all kernel symbols
 
 barebox-common := $(common-y)
+barebox-app-common := $(app-common-y)
+export barebox-app-common
 barebox-pbl-common := $(pbl-common-y)
 export barebox-pbl-common
 barebox-all    := $(barebox-common)
@@ -733,7 +736,7 @@ barebox.srec: barebox
 
 # The actual objects are generated when descending,
 # make sure no implicit rule kicks in
-$(sort $(barebox-head) $(barebox-common) ) $(barebox-lds) $(barebox-pbl-common): $(barebox-dirs) ;
+$(sort $(barebox-head) $(barebox-common) ) $(barebox-lds) $(barebox-pbl-common) $(barebox-app-common): $(barebox-dirs) ;
 
 # Handle descending into subdirectories listed in $(barebox-dirs)
 # Preset locale variables to speed up the build process. Limit locale
diff --git a/scripts/Makefile.build b/scripts/Makefile.build
index a95bbe4..600d1f7 100644
--- a/scripts/Makefile.build
+++ b/scripts/Makefile.build
@@ -15,6 +15,8 @@ obj-m :=
 lib-y :=
 lib-m :=
 pbl-y :=
+app-y :=
+app-final-y :=
 always :=
 targets :=
 subdir-y :=
@@ -98,7 +100,7 @@ ifneq ($(strip $(lib-y) $(lib-m) $(lib-n) $(lib-)),)
 lib-target := $(obj)/lib.a
 endif
 
-ifneq ($(strip $(obj-y) $(obj-m) $(obj-n) $(obj-) $(lib-target) $(pbl-y)),)
+ifneq ($(strip $(obj-y) $(obj-m) $(obj-n) $(obj-) $(lib-target) $(pbl-y) $(app-y)),)
 builtin-target := $(obj)/built-in.o
 endif
 
@@ -108,11 +110,23 @@ pbl-target := $(obj)/built-in-pbl.o
 endif
 endif
 
+ifeq ($(CONFIG_APPLICATIONS), y)
+ifneq ($(strip $(app-y) $(builtin-target)),)
+app-target := $(obj)/built-in-app.o
+endif
+
+ifneq ($(strip $(app-final-y)),)
+app-final-target := $(addprefix $(obj)/,$(app-final-y))
+app-final-bin-target := $(addsuffix .app,$(app-final-bin-target))
+endif
+
+endif
+
 # We keep a list of all modules in $(MODVERDIR)
 
-__build: $(if $(KBUILD_BUILTIN),$(builtin-target) $(lib-target) $(pbl-target) $(extra-y)) \
+__build: $(if $(KBUILD_BUILTIN),$(builtin-target) $(lib-target) $(pbl-target) $(app-target) $(extra-y)) \
 	 $(if $(KBUILD_MODULES),$(obj-m)) \
-	 $(subdir-ym) $(always)
+	 $(subdir-ym) $(always) $(app-final-target) $(app-final-bin-target)
 	@:
 
 # Linus' kernel sanity checking tool
@@ -185,10 +199,12 @@ cmd_cc_symtypes_c	   = \
 
 quiet_cmd_cc_o_c = CC $(quiet_modtag)  $@
 quiet_cmd_pbl_cc_o_c = PBLCC   $@
+quiet_cmd_app_cc_o_c = APPCC   $@
 
 ifndef CONFIG_MODVERSIONS
 cmd_cc_o_c = $(CC) $(c_flags) -c -o $@ $<
 cmd_pbl_cc_o_c = $(CC) -D__PBL__ $(c_flags) $(PBL_CPPFLAGS) -c -o $@ $<
+cmd_app_cc_o_c = $(CC) -D__APP__ $(APP_CPPFLAGS) $(app_c_flags) -c -o $@ $<
 
 else
 # When module versioning is enabled the following steps are executed:
@@ -239,8 +255,23 @@ define rule_pbl_cc_o_c
 	mv -f $(dot-target).tmp $(dot-target).cmd
 endef
 
+define rule_app_cc_o_c
+	$(call echo-cmd,checksrc) $(cmd_checksrc)			  \
+	$(call echo-cmd,app_cc_o_c) $(cmd_app_cc_o_c);			  \
+	$(cmd_modversions)						  \
+	scripts/basic/fixdep $(depfile) $@ '$(call make-cmd,app_cc__o_c)' >    \
+	                                              $(dot-target).tmp;  \
+	rm -f $(depfile);						  \
+	mv -f $(dot-target).tmp $(dot-target).cmd
+
+endef
+
 # Built-in and composite module parts
 
+app-%.o: %.c FORCE
+	$(call cmd,force_checksrc)
+	$(call if_changed_rule,app_cc_o_c)
+
 pbl-%.o: %.c FORCE
 	$(call cmd,force_checksrc)
 	$(call if_changed_rule,pbl_cc_o_c)
@@ -284,13 +315,19 @@ cmd_as_o_S       = $(CC) $(a_flags) -c -o $@ $<
 quiet_cmd_pbl_as_o_S = PBLAS   $@
 cmd_pbl_as_o_S       = $(CC) -D__PBL__ $(a_flags) $(PBL_CPPFLAGS) -c -o $@ $<
 
+quiet_cmd_app_as_o_S = APPAS   $@
+cmd_app_as_o_S       = $(CC) -D__APP__ $(app_a_flags) $(APP_CPPFLAGS) -c -o $@ $<
+
+app-%.o: %.S FORCE
+	$(call if_changed_dep,app_as_o_S)
+
 pbl-%.o: %.S FORCE
 	$(call if_changed_dep,pbl_as_o_S)
 
 %.o: %.S FORCE
 	$(call if_changed_dep,as_o_S)
 
-targets += $(real-objs-y) $(real-objs-m) $(lib-y) $(pbl-y)
+targets += $(real-objs-y) $(real-objs-m) $(lib-y) $(pbl-y) $(app-y)
 targets += $(extra-y) $(MAKECMDGOALS) $(always)
 
 # Linker scripts preprocessor (.lds.S -> .lds)
@@ -336,6 +373,39 @@ $(pbl-target): $(pbl-y) FORCE
 targets += $(pbl-target)
 endif # pbl-target
 
+ifdef app-target
+quiet_cmd_app_link_o_target = APPLD   $@
+# If the list of objects to link is empty, just create an empty built-in-app.o
+cmd_app_link_o_target = $(if $(strip $(app-y)),\
+		      $(LD) $(app_ld_flags) -r -o $@ $(filter $(app-y), $^),\
+		      rm -f $@; $(AR) rcs $@)
+
+$(app-target): $(app-y) FORCE
+	$(call if_changed,app_link_o_target)
+targets += $(app-target)
+endif # app-target
+
+ifdef app-final-target
+quiet_cmd_app_final_ld = APPLD   $@
+cmd_app_final_ld = $(LD) $(LDFLAGS) $(LDFLAGS_apps) -o $@ \
+	-T $(apps-lds) \
+	--start-group $(filter-out $(apps-lds) $(barebox-app-common) FORCE ,$^) \
+	$(barebox-app-common) --end-group $(APP_LDFLAGS) \
+	$(filter-out $(apps-lds) $^ $(barebox-app-common) FORCE ,$^)
+
+$(app-final-target): $(obj)/built-in-app.o FORCE
+	$(call if_changed,app_final_ld)
+
+%.app: % FORCE
+	$(call if_changed,objcopy)
+	$(Q)$(kecho) '  Barebox Apps: $@ is ready'
+
+$(app-final-bin-target):	$(app-final-target) FORCE
+
+targets += $(app-final-target)
+targets += $(app-final-bin-target)
+endif # app-target
+
 #
 # Rule to compile a set of .o files into one .a file
 #
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index 7bb769b..90bf72b 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -40,6 +40,17 @@ pbl-y		+= $(__pbl-y)
 
 pbl-y		:= $(sort $(patsubst %/, %/built-in-pbl.o, $(pbl-y)))
 
+# for non dirs add app- prefix to the target
+# so we recompile the source with custom flags and custom quiet
+__app-y		:= $(notdir $(app-y))
+app-y		:= $(patsubst %.o,app-%.o,$(__app-y))
+# add subdir from $(obj-y) and $(pbl-y)too so we do not need to have the dir define in
+# both $(obj-y) and $(pbl-y) and $(app-y)
+__app-y		:= $(filter-out $(app-y), $(filter %/, $(sort $(obj-y) $(pbl-y))))
+app-y		+= $(__app-y)
+
+app-y		:= $(sort $(patsubst %/, %/built-in-app.o, $(app-y)))
+
 __subdir-y	:= $(patsubst %/,%,$(filter %/, $(obj-y)))
 subdir-y	+= $(__subdir-y)
 __subdir-m	:= $(patsubst %/,%,$(filter %/, $(obj-m)))
@@ -65,9 +76,11 @@ multi-objs   := $(multi-objs-y) $(multi-objs-m)
 
 # $(subdir-obj-y) is the list of objects in $(obj-y) which uses dir/ to
 # tell kbuild to descend
-__subdir-obj-y := $(filter %/built-in-pbl.o, $(pbl-y))
+__subdir-pbl-y := $(filter %/built-in-pbl.o, $(pbl-y))
+__subdir-app-y := $(filter %/built-in-app.o, $(app-y))
 subdir-obj-y := $(filter %/built-in.o, $(obj-y))
-subdir-obj-y += $(__subdir-obj-y)
+subdir-obj-y += $(__subdir-pbl-y)
+subdir-obj-y += $(__subdir-app-y)
 
 # $(obj-dirs) is a list of directories that contain object files
 obj-dirs := $(dir $(multi-objs) $(subdir-obj-y))
@@ -85,6 +98,7 @@ obj-y		:= $(addprefix $(obj)/,$(obj-y))
 obj-m		:= $(addprefix $(obj)/,$(obj-m))
 lib-y		:= $(addprefix $(obj)/,$(lib-y))
 pbl-y		:= $(addprefix $(obj)/,$(pbl-y))
+app-y		:= $(addprefix $(obj)/,$(app-y))
 subdir-obj-y	:= $(addprefix $(obj)/,$(subdir-obj-y))
 real-objs-y	:= $(addprefix $(obj)/,$(real-objs-y))
 real-objs-m	:= $(addprefix $(obj)/,$(real-objs-m))
@@ -141,6 +155,11 @@ ___cpp_flags      = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(__cpp_flags)
 
 ___ld_flags       = $(LDFLAGS) $(EXTRA_LDFLAGS)
 
+app_c_flags     = $(APPINCLUDE) $(___c_flags)
+app_a_flags     = $(APPINCLUDE) -D__ASSEMBLY__ $(___a_flags)
+app_cpp_flags   = $(APPINCLUDE) $(___cpp_flags)
+app_ld_flags    = $(___ld_flags)
+
 c_flags        = $(LINUXINCLUDE) $(___c_flags)
 a_flags        = $(LINUXINCLUDE) $(AFLAGS_LINUXINCLUDE) $(___a_flags)
 cpp_flags      = $(LINUXINCLUDE) $(___cpp_flags)
-- 
1.7.10.4


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH 04/20] Introduce application (app) support
  2013-03-06  9:29 ` [PATCH 01/20] Makefile: x_flags prepare for apps support Jean-Christophe PLAGNIOL-VILLARD
  2013-03-06  9:29   ` [PATCH 02/20] tlsf_malloc: drop duplicate include Jean-Christophe PLAGNIOL-VILLARD
  2013-03-06  9:29   ` [PATCH 03/20] kbuild: add application (app) target Jean-Christophe PLAGNIOL-VILLARD
@ 2013-03-06  9:29   ` Jean-Christophe PLAGNIOL-VILLARD
  2013-03-06  9:29   ` [PATCH 05/20] app: Introduce libc support Jean-Christophe PLAGNIOL-VILLARD
                     ` (15 subsequent siblings)
  18 siblings, 0 replies; 31+ messages in thread
From: Jean-Christophe PLAGNIOL-VILLARD @ 2013-03-06  9:29 UTC (permalink / raw)
  To: barebox

Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
---
 Makefile                    |   47 ++++-
 apps/Kconfig                |   21 +++
 apps/Makefile               |   19 ++
 apps/include/appinfo.h      |   58 ++++++
 arch/arm/Kconfig            |    1 +
 commands/Kconfig            |    7 +
 commands/Makefile           |    1 +
 commands/appinfo.c          |  119 +++++++++++++
 common/Kconfig              |    3 +
 include/apps/syscall_init.h |   23 +++
 include/apps/syscalls.h     |   76 ++++++++
 include/apps/types.h        |   24 +++
 include/linux/license.h     |   14 ++
 lib/Makefile                |    1 +
 lib/apps/Makefile           |    1 +
 lib/apps/syscalls.c         |  413 +++++++++++++++++++++++++++++++++++++++++++
 16 files changed, 825 insertions(+), 3 deletions(-)
 create mode 100644 apps/Kconfig
 create mode 100644 apps/Makefile
 create mode 100644 apps/include/appinfo.h
 create mode 100644 commands/appinfo.c
 create mode 100644 include/apps/syscall_init.h
 create mode 100644 include/apps/syscalls.h
 create mode 100644 include/apps/types.h
 create mode 100644 include/linux/license.h
 create mode 100644 lib/apps/Makefile
 create mode 100644 lib/apps/syscalls.c

diff --git a/Makefile b/Makefile
index 110f7aa..706a1d4 100644
--- a/Makefile
+++ b/Makefile
@@ -297,6 +297,18 @@ LINUXINCLUDE    := -Iinclude \
                    -include include/generated/autoconf.h \
                    -include $(srctree)/include/linux/kconfig.h
 
+# Use APPINCLUDE when you must reference the include/ directory.
+# Needed to be compatible with the O= option
+APPINCLUDE    := -Iapps/include \
+                   $(if $(KBUILD_SRC), -I$(srctree)/apps/include) \
+                   $(if $(KBUILD_SRC), -I$(objtree)/include) \
+		   -I$(srctree)/arch/$(ARCH)/include \
+		   -I$(objtree)/arch/$(ARCH)/include \
+		   -I$(srctree)/arch/$(ARCH)/apps/include \
+		   -I$(objtree)/apps/include \
+                   -include include/generated/autoconf.h \
+                   -include $(srctree)/include/linux/kconfig.h
+
 CPPFLAGS        := -D__KERNEL__ -D__BAREBOX__ -fno-builtin -ffreestanding
 
 CFLAGS          := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \
@@ -315,9 +327,10 @@ export CPP AR NM STRIP OBJCOPY OBJDUMP MAKE AWK GENKSYMS PERL UTS_MACHINE
 export HOSTCXX HOSTCXXFLAGS LDFLAGS_MODULE CHECK CHECKFLAGS
 
 export CPPFLAGS NOSTDINC_FLAGS LINUXINCLUDE OBJCOPYFLAGS LDFLAGS
-export AFLAGS_LINUXINCLUDE
+export APPINCLUDE AFLAGS_LINUXINCLUDE
 export CFLAGS CFLAGS_KERNEL
 export AFLAGS AFLAGS_KERNEL
+export APP_LDFLAGS
 
 # Files to ignore in find ... statements
 
@@ -482,7 +495,18 @@ export KBUILD_BINARY ?= barebox.bin
 barebox-flash-image: $(KBUILD_IMAGE) FORCE
 	$(call if_changed,ln)
 
-all: barebox-flash-image
+ifdef CONFIG_APPLICATIONS
+apps-lds    := $(apps-lds-y)
+export apps-lds
+
+apps := apps
+application: barebox-flash-image
+	$(Q)$(MAKE) $(build)=$(apps) $(apps)/$@
+
+APPS-y += application
+endif
+
+all: barebox-flash-image $(APPS-y)
 
 common-$(CONFIG_PBL_IMAGE)	+= pbl/
 
@@ -493,7 +517,7 @@ barebox-alldirs	:= $(sort $(barebox-dirs) $(patsubst %/,%,$(filter %/, \
 		     $(core-n) $(core-) $(drivers-n) $(drivers-) \
 		     $(net-n)  $(net-)  $(libs-n)    $(libs-))))
 
-app-common-y	:= $(patsubst %/, %/built-in-app.o, $(common-y))
+app-common-y	:= $(patsubst %/, %/built-in-app.o, $(common-y) apps/)
 pbl-common-y	:= $(patsubst %/, %/built-in-pbl.o, $(common-y))
 common-y	:= $(patsubst %/, %/built-in.o, $(common-y))
 
@@ -840,6 +864,23 @@ ifneq ($(KBUILD_SRC),)
 		/bin/false; \
 	fi;
 	$(Q)if [ ! -d include2 ]; then mkdir -p include2; fi;
+	$(Q)if [ ! -d apps/include ]; then mkdir -p apps/include; fi;
+	$(Q)if [ ! -d apps/include/barebox ]; then mkdir -p apps/include/barebox; fi;
+	$(Q)if [ ! -h apps/include/linux ]; then  \
+	    ln -fsn $(srctree)/include/linux apps/include/linux;     \
+	    fi;
+	$(Q)if [ ! -h apps/include/asm-generic ]; then  \
+	    ln -fsn $(srctree)/include/asm-generic apps/include/asm-generic;     \
+	    fi;
+	$(Q)if [ ! -h apps/include/generated ]; then  \
+	    ln -fsn $(objtree)/include/generated apps/include/generated;     \
+	    fi;
+	$(Q)if [ ! -e apps/include/barebox/fcntl.h ]; then  \
+	    ln -fsn $(srctree)/include/fcntl.h apps/include/barebox/fcntl.h;     \
+	    fi;
+	$(Q)if [ ! -e apps/include/barebox/types.h ]; then  \
+	    ln -fsn $(srctree)/include/apps/types.h apps/include/barebox/types.h;     \
+	    fi;
 	$(Q)if [ -e $(srctree)/include/asm-$(SRCARCH)/barebox.h ]; then  \
 	    ln -fsn $(srctree)/include/asm-$(SRCARCH) include2/asm;     \
 	    fi
diff --git a/apps/Kconfig b/apps/Kconfig
new file mode 100644
index 0000000..92899b5
--- /dev/null
+++ b/apps/Kconfig
@@ -0,0 +1,21 @@
+menuconfig APPLICATIONS
+	bool "Applications"
+	depends on HAS_APPLICATIONS
+	depends on EXPERIMENTAL
+	help
+	  This option enables support for running applications.
+
+if APPLICATIONS
+
+menu "memory layout"
+
+source "arch/$SRCARCH/apps/Kconfig"
+
+config APP_MALLOC_SIZE
+	hex
+	default 0x400000
+	prompt "malloc area size"
+
+endmenu
+
+endif
diff --git a/apps/Makefile b/apps/Makefile
new file mode 100644
index 0000000..65adfdc
--- /dev/null
+++ b/apps/Makefile
@@ -0,0 +1,19 @@
+
+CPPFLAGS += -I$(srctree)/apps/include
+
+$(obj)/application: $(apps-lds) $(apps-y)
+
+APP_CPPFLAGS		+= -fdata-sections -ffunction-sections
+
+$(obj)/include/types.h: $(srctree)/include/types.h
+	$(call cmd,shipped)
+
+$(obj)/include/barebox/syscalls.h: $(srctree)/include/apps/syscalls.h
+	$(call cmd,shipped)
+
+$(obj)/include/errno.h: $(srctree)/include/asm-generic/errno.h
+	$(call cmd,shipped)
+
+barebox-app-header += $(obj)/include/types.h
+barebox-app-header += $(obj)/include/errno.h
+barebox-app-header += $(obj)/include/barebox/syscalls.h
diff --git a/apps/include/appinfo.h b/apps/include/appinfo.h
new file mode 100644
index 0000000..94409d7
--- /dev/null
+++ b/apps/include/appinfo.h
@@ -0,0 +1,58 @@
+#ifndef __APPINFO_H__
+#define __APPINFO_H__
+
+/* Indirect macros required for expanded argument pasting, eg. __LINE__. */
+#define ___PASTE(a,b) a##b
+#define __PASTE(a,b) ___PASTE(a,b)
+
+# define __UNIQUE_ID(prefix) __PASTE(__PASTE(__UNIQUE_ID_, prefix), __LINE__)
+
+#define __APP_INFO(tag, name, info)	\
+ static const char __UNIQUE_ID(name)[] \
+ __attribute__((__used__))\
+ __attribute__((section(".appinfo"), unused, aligned(1))) = \
+ #tag "=" info;
+
+/* Generic info of form tag = "info" */
+#define APP_INFO(tag, info)	__APP_INFO(tag, tag, info)
+
+/*
+ * The following license idents are currently accepted as indicating free
+ * software applications
+*
+ *      "GPL"                           [GNU Public License v2 or later]
+ *      "GPL v2"                        [GNU Public License v2]
+ *      "GPL and additional rights"     [GNU Public License v2 rights and more]
+ *      "Dual BSD/GPL"                  [GNU Public License v2
+ *                                       or BSD license choice]
+ *      "Dual MIT/GPL"                  [GNU Public License v2
+ *                                       or MIT license choice]
+ *      "Dual MPL/GPL"                  [GNU Public License v2
+ *                                       or Mozilla license choice]
+ *
+ * The following other idents are available
+ *
+ *      "Proprietary"                   [Non free products]
+ *
+ * There are dual licensed components, but when running with Linux it is
+ * GPL that is relevant so this is a non issue. Similarly LGPL linked with GPL
+ * is a GPL combined work.
+ *
+ * This exists for several reasons
+ * 1.   So appinfo can show license info for users wanting to vet their setup 
+ *      is free
+ * 2.   So the community can ignore bug reports including proprietary applications
+ * 3.   So vendors can do likewise based on their own policies
+ */
+
+#define APP_LICENSE(_license)	APP_INFO(license, _license)
+/*
+ * Author(s), use "Name <email>" or just "Name", for multiple
+ * authors use multiple MODULE_AUTHOR() statements/lines.
+ */
+#define APP_AUTHOR(_author)	APP_INFO(author, _author)
+
+/* What your application does. */
+#define APP_DESCRIPTION(_description) APP_INFO(description, _description)
+
+#endif /* __APPINFO_H__ */
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 7ac134e..f25dcf7 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -236,3 +236,4 @@ source drivers/Kconfig
 source fs/Kconfig
 source lib/Kconfig
 source crypto/Kconfig
+source apps/Kconfig
diff --git a/commands/Kconfig b/commands/Kconfig
index c1454c7..b10a8c1 100644
--- a/commands/Kconfig
+++ b/commands/Kconfig
@@ -242,6 +242,13 @@ config CMD_FILETYPE
 	select FILETYPE
 	prompt "filetype"
 
+config CMD_APPINFO
+	tristate
+	depends on APPLICATIONS
+	prompt "appinfo"
+	help
+	  dump barebox applicaion info
+
 endmenu
 
 menu "console"
diff --git a/commands/Makefile b/commands/Makefile
index 0ae6b95..b9280eb 100644
--- a/commands/Makefile
+++ b/commands/Makefile
@@ -1,3 +1,4 @@
+obj-$(CONFIG_CMD_APPINFO)	+= appinfo.o
 obj-$(CONFIG_STDDEV)		+= stddev.o
 obj-$(CONFIG_CMD_BOOTM)		+= bootm.o
 obj-$(CONFIG_CMD_UIMAGE)	+= uimage.o
diff --git a/commands/appinfo.c b/commands/appinfo.c
new file mode 100644
index 0000000..9736fce
--- /dev/null
+++ b/commands/appinfo.c
@@ -0,0 +1,119 @@
+/*
+ *
+ * Copyright (c) 2013 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+ *
+ */
+
+#include <common.h>
+#include <command.h>
+#include <fs.h>
+#include <fcntl.h>
+#include <malloc.h>
+#include <errno.h>
+
+/*
+ * first search for #info and then we get the section size
+ * the #info is within the first 512 bytes of the file if present
+ */
+
+#define FILE_APP_BUF 512
+
+static int dump_apping(int fd, int offset, int size)
+{
+	char *buf, *tmp;
+	int ret;
+
+	tmp = buf = xzalloc(size);
+
+	ret = lseek(fd, offset, SEEK_SET);
+	if (ret < 0) {
+		perror("lseek");
+		goto err_out;
+	}
+
+	ret = read(fd, buf, size);
+	if (ret < 0) {
+		perror("read");
+		goto err_out;
+	}
+
+	for (; tmp < buf + size || !strcmp(tmp, "appinf#");
+			tmp += strlen(tmp) + 1) {
+		if (tstc())
+			break;
+		if (strlen(tmp) == 0)
+			break;
+		printf("%s\n", tmp);
+	}
+
+	ret = 0;
+
+err_out:
+	free(buf);
+
+	return ret;
+}
+
+static int do_appinfo(int argc, char *argv[])
+{
+	int fd;
+	char *buf, *tmp;
+	int ret = 1;
+
+	if (argc == 1)
+		return COMMAND_ERROR_USAGE;
+
+	fd = open(argv[1], O_RDONLY);
+
+	if (fd < 0) {
+		perror("open");
+		return fd;
+	}
+
+	tmp = buf = xzalloc(FILE_APP_BUF);
+
+	ret = read(fd, buf, FILE_APP_BUF);
+	if (ret < 0) {
+		perror("read");
+		goto err_out;
+	}
+
+	for (; ret-- ; ++tmp) {
+		if (*tmp != '#')
+			continue;
+
+		if (ret < 8)
+			goto no_app_info;
+
+		if (!strcmp(tmp, "#appinf")) {
+			int size = *((uint32_t*)(tmp + 8));
+			int offset = tmp - buf;
+
+			free(buf);
+			ret = dump_apping(fd, offset + 12, size);
+			goto out;
+		}
+	}
+
+no_app_info:
+	printf("no appinfo found\n");
+
+	ret = 0;
+err_out:
+	free(buf);
+out:
+	close(fd);
+
+	return ret;
+}
+
+BAREBOX_CMD_HELP_START(appinfo)
+BAREBOX_CMD_HELP_USAGE("appinfo <file>\n")
+BAREBOX_CMD_HELP_SHORT("display the barebox application information\n")
+BAREBOX_CMD_HELP_END
+
+BAREBOX_CMD_START(appinfo)
+	.cmd		= do_appinfo,
+	.usage		= "display the barebox application informatio",
+	BAREBOX_CMD_HELP(cmd_appinfo_help)
+BAREBOX_CMD_END
diff --git a/common/Kconfig b/common/Kconfig
index 3a55e01..6defdbe 100644
--- a/common/Kconfig
+++ b/common/Kconfig
@@ -21,6 +21,9 @@ config HAS_KALLSYMS
 config HAS_MODULES
 	bool
 
+config HAS_APPLICATIONS
+	bool
+
 config CMD_MEMORY
 	bool
 
diff --git a/include/apps/syscall_init.h b/include/apps/syscall_init.h
new file mode 100644
index 0000000..4c496ef
--- /dev/null
+++ b/include/apps/syscall_init.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2013 Jean-Christophe PLAGNIOL-VILLARD <plagnio@jcrosoft.com>
+ *
+ * Under GPLv2 only
+*/
+
+#ifndef __APPS_SYSCALL_INIT_H__
+#define __APPS_SYSCALL_INIT_H__
+
+#include <types.h>
+
+struct syscall_trace {
+	struct list_head dirs;
+	struct list_head fds;
+	void *dest;
+	uint64_t malloc_base;
+	uint32_t malloc_size;
+};
+
+void syscalls_init(struct syscall_trace *t);
+void syscalls_exit(struct syscall_trace *t);
+
+#endif /* __APPS_SYSCALL_INIT_H__ */
diff --git a/include/apps/syscalls.h b/include/apps/syscalls.h
new file mode 100644
index 0000000..e3b10a8
--- /dev/null
+++ b/include/apps/syscalls.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2013 Jean-Christophe PLAGNIOL-VILLARD <plagnio@jcrosoft.com>
+ *
+ * Under GPLv2 only
+*/
+
+#ifndef __APPS_SYSCALLS_H__
+#define __APPS_SYSCALLS_H__
+
+#include <types.h>
+#include <stdarg.h>
+
+#define SYSCALLS_MAGIC "bsyscall"
+
+#define SYS_putchar		0
+#define SYS_getchar		1
+#define SYS_eputc		2
+#define SYS_tstc		3
+
+/* file */
+#define SYS_open		4
+#define SYS_close		5
+#define SYS_read		6
+#define SYS_write		7
+#define SYS_unlink		8
+#define SYS_stat		9
+#define SYS_lstat		10
+#define SYS_lseek		11
+
+/* dir */
+#define SYS_mkdir		12
+#define SYS_rmdir		13
+#define SYS_getcwd		14
+#define SYS_chdir		15
+#define SYS_opendir		16
+#define SYS_readdir		17
+#define SYS_closedir		18
+
+/* symlink */
+#define SYS_symlink		19
+#define SYS_readlink		20
+
+/* mount */
+#define SYS_mount		21
+#define SYS_umount		22
+
+/* device */
+#define SYS_ioctl		23
+
+/* env */
+#define SYS_getenv		24
+#define SYS_setenv		25
+
+/* time */
+#define SYS_ndelay		26
+
+/* exec */
+#define SYS_system		27
+
+/* barebox */
+#define SYS_memmap		100
+
+#ifndef __ASSEMBLY__
+
+struct syscalls_header {
+	char			magic[8];
+	uint32_t		major;
+	uint32_t		minor;
+	uint64_t		malloc_base;
+	uint32_t		malloc_size;
+	uint32_t		nb_syscalls;
+	void			*syscalls;
+};
+#endif
+
+#endif /* __APPS_SYSCALLS_H__ */
diff --git a/include/apps/types.h b/include/apps/types.h
new file mode 100644
index 0000000..2bb6ee6
--- /dev/null
+++ b/include/apps/types.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2013 Jean-Christophe PLAGNIOL-VILLARD <plagnio@jcrosoft.com>
+ *
+ * Under GPLv2 only
+*/
+
+#ifndef __APPS_TYPES_H__
+#define __APPS_TYPES_H__
+
+#ifndef __APP__
+#define APP_TYPE_(x) APP_##x
+#else
+#define APP_TYPE_(x) x
+#endif
+
+struct APP_TYPE_(dirent) {
+	char d_name[256];
+};
+
+typedef struct APP_TYPE_(dir) {
+	struct APP_TYPE_(dirent) d;
+} APP_TYPE_(DIR);
+
+#endif /* __APPS_TYPES_H__ */
diff --git a/include/linux/license.h b/include/linux/license.h
new file mode 100644
index 0000000..decdbf4
--- /dev/null
+++ b/include/linux/license.h
@@ -0,0 +1,14 @@
+#ifndef __LICENSE_H
+#define __LICENSE_H
+
+static inline int license_is_gpl_compatible(const char *license)
+{
+	return (strcmp(license, "GPL") == 0
+		|| strcmp(license, "GPL v2") == 0
+		|| strcmp(license, "GPL and additional rights") == 0
+		|| strcmp(license, "Dual BSD/GPL") == 0
+		|| strcmp(license, "Dual MIT/GPL") == 0
+		|| strcmp(license, "Dual MPL/GPL") == 0);
+}
+
+#endif
diff --git a/lib/Makefile b/lib/Makefile
index 3c94542..731bc5b 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -42,3 +42,4 @@ obj-$(CONFIG_LIBMTD)	+= libmtd.o
 obj-y			+= gui/
 obj-$(CONFIG_XYMODEM)	+= xymodem.o
 obj-y			+= unlink-recursive.o
+obj-$(CONFIG_APPLICATIONS)	+= apps/
diff --git a/lib/apps/Makefile b/lib/apps/Makefile
new file mode 100644
index 0000000..86e7071
--- /dev/null
+++ b/lib/apps/Makefile
@@ -0,0 +1 @@
+obj-y += syscalls.o
diff --git a/lib/apps/syscalls.c b/lib/apps/syscalls.c
new file mode 100644
index 0000000..832ba02
--- /dev/null
+++ b/lib/apps/syscalls.c
@@ -0,0 +1,413 @@
+/*
+ * Copyright (C) 2013 Jean-Christophe PLAGNIOL-VILLARD <plagnio@jcrosoft.com>
+ *
+ * Under GPLv2 only
+*/
+
+#include <common.h>
+#include <fs.h>
+#include <apps/syscalls.h>
+#include <apps/syscall_init.h>
+#include <apps/types.h>
+#include <linux/stat.h>
+#include <environment.h>
+#include <malloc.h>
+#include <clock.h>
+
+static struct syscall_trace *st_current;
+/* 
+ * keep traking of what is open to close it
+ * when returning
+ */
+struct app_dir_opendir {
+	DIR *d;
+	APP_TYPE_(DIR) *app_d;
+	struct list_head list;
+};
+
+struct app_fd_open {
+	int fd;
+	struct list_head list;
+};
+
+static long sys_putchar(char c)
+{
+	putchar(c);
+
+	return 0;
+}
+
+static long sys_getchar(void)
+{
+	return getc();
+}
+
+static long sys_eputc(char c)
+{
+	eputc(c);
+
+	return 0;
+}
+
+static long sys_tstc(void)
+{
+	return tstc();
+}
+
+static struct app_fd_open *sys_get_file(int fd)
+{
+	struct app_fd_open *af;
+
+	list_for_each_entry(af, &(st_current->fds), list) {
+		if (af->fd == fd)
+			return af;
+	}
+
+	return NULL;
+}
+
+/* barebox does not handle the last optionnal arg */
+static long sys_open(const char *filename, int flags, mode_t mode)
+{
+	struct app_fd_open *af;
+	int fd;
+
+	af = calloc(1, sizeof(*af));
+	if (!af)
+		return -ENOMEM;
+
+	fd = open(filename, flags, mode);
+	if (fd < 3) {
+		free(af);
+	} else {
+		af->fd = fd;
+		list_add_tail(&af->list, &st_current->fds);
+	}
+
+	return fd;
+}
+
+static long sys_close(unsigned int fd)
+{
+	struct app_fd_open *af;
+
+	if (fd > 2) {
+		af = sys_get_file(fd);
+		if (!af)
+			return -EINVAL;
+
+		list_del(&af->list);
+	}
+
+	return close(fd);
+}
+
+static long sys_read(unsigned int fd, char *buf, size_t count)
+{
+	return read(fd, buf, count);
+}
+
+static long sys_write(unsigned int fd, char *buf, size_t count)
+{
+	return write(fd, buf, count);
+}
+
+static long sys_unlink(const char *name)
+{
+	return unlink(name);
+}
+
+static long sys_stat(const char *name, struct stat *s)
+{
+	return lstat(name, s);
+}
+
+static long sys_lstat(const char *name, struct stat *s)
+{
+	return lstat(name, s);
+}
+
+static loff_t sys_lseek(int fd, loff_t offset, int whence)
+{
+	return lseek(fd, offset, whence);
+}
+
+static long sys_mkdir(char *name, mode_t mode)
+{
+	return mkdir(name, mode);
+}
+
+static long sys_rmdir(char *name)
+{
+	return rmdir(name);
+}
+
+/* int getcwd(char* buf, size_t size) */
+static long sys_getcwd(char* buf, size_t size)
+{
+	const char *path;
+	int len;
+
+	if (!buf)
+		return -ENOMEM;
+
+	path = getcwd();
+	len = strlen(path);
+
+	strncpy(buf, path, min(len, (int)size));
+
+	return 0;
+}
+
+static long sys_chdir(char *name)
+{
+	return chdir(name);
+}
+
+static struct app_dir_opendir *sys_get_dir(APP_TYPE_(DIR) *d)
+{
+	struct app_dir_opendir *ad;
+
+	list_for_each_entry(ad, &st_current->dirs, list) {
+		if (ad->app_d == d)
+			return ad;
+	}
+
+	return NULL;
+}
+
+/*
+ * int opendir(DIR *, char *name)
+ *
+ * Do not expose barebox internal struct
+ */
+static long sys_opendir(APP_TYPE_(DIR) *dir, const char *name)
+{
+	DIR *d;
+	struct app_dir_opendir *ad;
+	int ret;
+
+	ad = calloc(1, sizeof(*ad));
+	if (!ad)
+		return -ENOMEM;
+
+
+	d = opendir(name);
+	if (!d) {
+		ret = -ENOENT;
+		goto err;
+	}
+
+	strcpy(dir->d.d_name, d->d.d_name);
+
+	ad->app_d = dir;
+	ad->d = d;
+
+	list_add_tail(&ad->list, &st_current->dirs);
+
+	return 0;
+
+err:
+	free(ad);
+	return ret;
+}
+
+static long sys_readdir(APP_TYPE_(DIR) *app_dir, struct APP_TYPE_(dirent) *app_d)
+{
+	struct app_dir_opendir *ad;
+	struct dirent *d;
+
+	ad = sys_get_dir(app_dir);
+	if (!ad) {
+		app_d = NULL;
+		return -EINVAL;
+	}
+
+	d = readdir(ad->d);
+
+	if (!d || !d->d_name) {
+		app_d = NULL;
+		return -ENOENT;
+	}
+
+	strcpy(app_d->d_name, d->d_name);
+
+	return 0;
+}
+
+static long sys_closedir(APP_TYPE_(DIR) *app_dir)
+{
+	struct app_dir_opendir *ad;
+	int ret;
+
+	ad = sys_get_dir(app_dir);
+	if (!ad)
+		return -EINVAL;
+
+	ret = closedir(ad->d);
+
+	list_del(&ad->list);
+
+	return ret;
+}
+
+static long sys_symlink(const char *src, const char *dest)
+{
+	return symlink(src, dest);
+}
+
+static long sys_readlink(const char * path, char * buf, u32 bufsiz)
+{
+	return readlink(path, buf, bufsiz);
+}
+
+/*
+ * libc mount
+ * int mount(const char *source, const char *target,
+ *           const char *fstype, unsigned long mountflags,
+ *	     const void *data);
+ * barebox
+ * int mount(const char *device, const char *fsname, const char *_path)
+ */
+static long sys_mount(char *dev_name, char *dir_name,
+		char *type, unsigned long flags,
+		void *data)
+{
+	return mount(dev_name, type, dir_name);
+}
+
+static long sys_umount(char *name, int flags)
+{
+	return umount(name);
+}
+
+static long sys_ioctl(unsigned int fd, unsigned int cmd,
+				unsigned long arg)
+{
+	return ioctl(fd, cmd, (void*)arg);
+}
+
+static long sys_getenv(char *value, const char *name)
+{
+	strcpy(value, getenv(name));
+
+	return 0;
+}
+
+static long sys_setenv(const char *name, const char *value)
+{
+	return setenv(name, value);
+}
+
+static long sys_ndelay(unsigned long nsecs)
+{
+	uint64_t start = get_time_ns();
+
+	while(!is_timeout(start, nsecs));
+
+	return 0;
+}
+
+static long sys_nil(unsigned long arg0, unsigned long arg1, unsigned long arg2)
+{
+	pr_err("%s(0x%lx, 0x%lx, 0x%lx)\n", __func__, arg0, arg1, arg2);
+	return -ENOSYS;
+}
+
+#define __SYSCALL(name) [SYS_##name] = sys_##name
+
+static void *sys_funcs[] = {
+	__SYSCALL(putchar),
+	__SYSCALL(getchar),
+	__SYSCALL(eputc),
+	__SYSCALL(tstc),
+	/* file */
+	__SYSCALL(open),
+	__SYSCALL(close),
+	__SYSCALL(read),
+	__SYSCALL(write),
+	__SYSCALL(unlink),
+	__SYSCALL(stat),
+	__SYSCALL(lstat),
+	__SYSCALL(lseek),
+	/* dir */
+	__SYSCALL(mkdir),
+	__SYSCALL(rmdir),
+	__SYSCALL(getcwd),
+	__SYSCALL(chdir),
+	__SYSCALL(opendir),
+	__SYSCALL(readdir),
+	__SYSCALL(closedir),
+	/* symlink */
+	__SYSCALL(symlink),
+	__SYSCALL(readlink),
+	/* mount */
+	__SYSCALL(mount),
+	__SYSCALL(umount),
+	/* device */
+	__SYSCALL(ioctl),
+	/* env */
+	__SYSCALL(getenv),
+	__SYSCALL(setenv),
+	/* env */
+	__SYSCALL(ndelay),
+};
+
+struct syscalls_header syscalls = {
+	.magic = SYSCALLS_MAGIC,
+	.major = 1,
+	.minor = 0,
+	.nb_syscalls = ARRAY_SIZE(sys_funcs),
+	.syscalls = sys_funcs,
+};
+
+void syscalls_init(struct syscall_trace *t)
+{
+	struct syscalls_header *app_syscalls = t->dest;
+	int size = sizeof(syscalls);
+	void **dest;
+	int i;
+
+	pr_debug("t->dest = 0x%p\n", t->dest);
+
+	pr_debug("sizeof = %d\n", size);
+	memcpy(t->dest, &syscalls, sizeof(syscalls));
+
+	app_syscalls->malloc_base = t->malloc_base;
+	app_syscalls->malloc_size = t->malloc_size;
+	dest = t->dest + size;
+
+	size = sizeof(void*) * syscalls.nb_syscalls;
+	pr_debug("dest = 0x%p\n", dest);
+	pr_debug("size = %d\n", size);
+
+	app_syscalls->syscalls = dest;
+	memcpy(dest, sys_funcs, size);
+
+	for (i = 0; i < syscalls.nb_syscalls; i++) {
+		if (!dest[i]) {
+			pr_debug("syscall %d not implemented\n", i);
+			dest[i] = sys_nil;
+		}
+	}
+
+	INIT_LIST_HEAD(&t->dirs);
+	INIT_LIST_HEAD(&t->fds);
+}
+
+void syscalls_exit(struct syscall_trace *t)
+{
+	struct app_dir_opendir *ad, *tmpd;
+	struct app_fd_open *af, *tmpf;
+
+	list_for_each_entry_safe(ad, tmpd, &t->dirs, list) {
+		closedir(ad->d);
+		list_del(&ad->list);
+	}
+
+	list_for_each_entry_safe(af, tmpf, &t->fds, list) {
+		close(af->fd);
+		list_del(&af->list);
+	}
+}
+
-- 
1.7.10.4


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH 05/20] app: Introduce libc support
  2013-03-06  9:29 ` [PATCH 01/20] Makefile: x_flags prepare for apps support Jean-Christophe PLAGNIOL-VILLARD
                     ` (2 preceding siblings ...)
  2013-03-06  9:29   ` [PATCH 04/20] Introduce application (app) support Jean-Christophe PLAGNIOL-VILLARD
@ 2013-03-06  9:29   ` Jean-Christophe PLAGNIOL-VILLARD
  2013-03-06  9:29   ` [PATCH 06/20] app: add some utils Jean-Christophe PLAGNIOL-VILLARD
                     ` (14 subsequent siblings)
  18 siblings, 0 replies; 31+ messages in thread
From: Jean-Christophe PLAGNIOL-VILLARD @ 2013-03-06  9:29 UTC (permalink / raw)
  To: barebox

with dummy malloc or tslf malloc

and provide a pseudo libc to simplify application porting

Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
---
 apps/Kconfig               |   19 ++
 apps/Makefile              |   10 +-
 apps/include/appinfo.h     |    2 +
 apps/include/assert.h      |   32 +++
 apps/include/common.h      |   28 ++
 apps/include/ctype.h       |  100 +++++++
 apps/include/dirent.h      |   24 ++
 apps/include/errno.h       |   24 ++
 apps/include/fcntl.h       |   25 ++
 apps/include/getopt.h      |   76 ++++++
 apps/include/libc_config.h |  139 ++++++++++
 apps/include/limits.h      |   38 +++
 apps/include/malloc.h      |   30 +++
 apps/include/module.h      |    3 +
 apps/include/sections.h    |   29 ++
 apps/include/setjmp.h      |   25 ++
 apps/include/stddef.h      |    1 +
 apps/include/stdint.h      |   23 ++
 apps/include/stdio.h       |   70 +++++
 apps/include/stdlib.h      |   29 ++
 apps/include/string.h      |   53 ++++
 apps/include/sys/ioctl.h   |   12 +
 apps/include/sys/stat.h    |   14 +
 apps/include/sys/syscall.h |   14 +
 apps/include/sys/types.h   |   15 ++
 apps/include/time.h        |   27 ++
 apps/include/unistd.h      |   46 ++++
 apps/libc/Kconfig          |   25 ++
 apps/libc/Makefile         |   36 +++
 apps/libc/appinfo.c        |   35 +++
 apps/libc/dirent.c         |   59 +++++
 apps/libc/errno.c          |   19 ++
 apps/libc/fcntl.c          |   25 ++
 apps/libc/flags.c          |   76 ++++++
 apps/libc/getopt.c         |  127 +++++++++
 apps/libc/getopt_long.c    |  625 ++++++++++++++++++++++++++++++++++++++++++++
 apps/libc/malloc.c         |   50 ++++
 apps/libc/malloc.h         |    2 +
 apps/libc/private.h        |   18 ++
 apps/libc/stdio.c          |  275 +++++++++++++++++++
 apps/libc/stdlib.c         |   77 ++++++
 apps/libc/string.c         |  159 +++++++++++
 apps/libc/sys/Makefile     |    2 +
 apps/libc/sys/stat.c       |   25 ++
 apps/libc/syscalls.c       |  103 ++++++++
 apps/libc/time.c           |   41 +++
 apps/libc/unistd.c         |  108 ++++++++
 47 files changed, 2791 insertions(+), 4 deletions(-)
 create mode 100644 apps/include/assert.h
 create mode 100644 apps/include/common.h
 create mode 100644 apps/include/ctype.h
 create mode 100644 apps/include/dirent.h
 create mode 100644 apps/include/errno.h
 create mode 100644 apps/include/fcntl.h
 create mode 100644 apps/include/getopt.h
 create mode 100644 apps/include/libc_config.h
 create mode 100644 apps/include/limits.h
 create mode 100644 apps/include/malloc.h
 create mode 100644 apps/include/module.h
 create mode 100644 apps/include/sections.h
 create mode 100644 apps/include/setjmp.h
 create mode 100644 apps/include/stddef.h
 create mode 100644 apps/include/stdint.h
 create mode 100644 apps/include/stdio.h
 create mode 100644 apps/include/stdlib.h
 create mode 100644 apps/include/string.h
 create mode 100644 apps/include/sys/ioctl.h
 create mode 100644 apps/include/sys/stat.h
 create mode 100644 apps/include/sys/syscall.h
 create mode 100644 apps/include/sys/types.h
 create mode 100644 apps/include/time.h
 create mode 100644 apps/include/unistd.h
 create mode 100644 apps/libc/Kconfig
 create mode 100644 apps/libc/Makefile
 create mode 100644 apps/libc/appinfo.c
 create mode 100644 apps/libc/dirent.c
 create mode 100644 apps/libc/errno.c
 create mode 100644 apps/libc/fcntl.c
 create mode 100644 apps/libc/flags.c
 create mode 100644 apps/libc/getopt.c
 create mode 100644 apps/libc/getopt_long.c
 create mode 100644 apps/libc/malloc.c
 create mode 100644 apps/libc/malloc.h
 create mode 100644 apps/libc/private.h
 create mode 100644 apps/libc/stdio.c
 create mode 100644 apps/libc/stdlib.c
 create mode 100644 apps/libc/string.c
 create mode 100644 apps/libc/sys/Makefile
 create mode 100644 apps/libc/sys/stat.c
 create mode 100644 apps/libc/syscalls.c
 create mode 100644 apps/libc/time.c
 create mode 100644 apps/libc/unistd.c

diff --git a/apps/Kconfig b/apps/Kconfig
index 92899b5..4805c50 100644
--- a/apps/Kconfig
+++ b/apps/Kconfig
@@ -7,6 +7,8 @@ menuconfig APPLICATIONS
 
 if APPLICATIONS
 
+source "apps/libc/Kconfig"
+
 menu "memory layout"
 
 source "arch/$SRCARCH/apps/Kconfig"
@@ -16,6 +18,23 @@ config APP_MALLOC_SIZE
 	default 0x400000
 	prompt "malloc area size"
 
+config APP_PATH_MAX
+	hex
+	default 4096
+	prompt "path max"
+
+config APP_ENV_MAX
+	hex
+	default 4096
+	prompt "env var max size"
+
+config APP_FILE_MAX
+	int
+	default 128
+	prompt "maximun number of FILE"
+	help
+	  this does not include stdin, stderr, stdout
+
 endmenu
 
 endif
diff --git a/apps/Makefile b/apps/Makefile
index 65adfdc..c5c5c48 100644
--- a/apps/Makefile
+++ b/apps/Makefile
@@ -1,5 +1,9 @@
 
-CPPFLAGS += -I$(srctree)/apps/include
+APP_CPPFLAGS += -include $(srctree)/apps/include/libc_config.h
+APP_CPPFLAGS += -I$(srctree)/apps/include
+export APP_CPPFLAGS
+
+apps-$(CONFIG_APP_EXAMPLE) += example
 
 $(obj)/application: $(apps-lds) $(apps-y)
 
@@ -11,9 +15,7 @@ $(obj)/include/types.h: $(srctree)/include/types.h
 $(obj)/include/barebox/syscalls.h: $(srctree)/include/apps/syscalls.h
 	$(call cmd,shipped)
 
-$(obj)/include/errno.h: $(srctree)/include/asm-generic/errno.h
-	$(call cmd,shipped)
+obj-y += libc/
 
 barebox-app-header += $(obj)/include/types.h
-barebox-app-header += $(obj)/include/errno.h
 barebox-app-header += $(obj)/include/barebox/syscalls.h
diff --git a/apps/include/appinfo.h b/apps/include/appinfo.h
index 94409d7..ba95e65 100644
--- a/apps/include/appinfo.h
+++ b/apps/include/appinfo.h
@@ -55,4 +55,6 @@
 /* What your application does. */
 #define APP_DESCRIPTION(_description) APP_INFO(description, _description)
 
+void print_appinfo(void);
+
 #endif /* __APPINFO_H__ */
diff --git a/apps/include/assert.h b/apps/include/assert.h
new file mode 100644
index 0000000..a5d1bdd
--- /dev/null
+++ b/apps/include/assert.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2013 Jean-Christophe PLAGNIOL-VILLARD <plagnio@jcrosoft.com>
+ *
+ * Under GPLv2 only
+ *
+ * As a special exception, if other files instantiate templates or use macros
+ * or inline functions from this file, or you compile this file and link it
+ * with other works to produce a work based on this file, this file does not
+ * by itself cause the resulting work to be covered by the GNU General Public
+ * License. However the source code for this file must still be made available
+ * in accordance with section (3) of the GNU General Public License.
+
+ * This exception does not invalidate any other reasons why a work based on
+ * this file might be covered by the GNU General Public License.
+ */
+
+#ifndef __ASSERT_H__
+#define __ASSERT_H__
+
+#define NDEBUG
+#if defined(NDEBUG) || defined(CONFIG_APP_NDEBUG)
+#define assert(expression)
+#else
+#define assert(expression) do {	\
+	if (expression) { \
+		fprintf(stderr, "%s:%d: ", str(expression), __FUNCTION__, __LINE__); \
+		exit(EXIT_FAILURE); \
+	} \
+} while(0)
+#endif
+
+#endif /* __ASSERT_H__ */
diff --git a/apps/include/common.h b/apps/include/common.h
new file mode 100644
index 0000000..6e991e8
--- /dev/null
+++ b/apps/include/common.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2013 Jean-Christophe PLAGNIOL-VILLARD <plagnio@jcrosoft.com>
+ *
+ * Under GPLv2 only
+ *
+ * As a special exception, if other files instantiate templates or use macros
+ * or inline functions from this file, or you compile this file and link it
+ * with other works to produce a work based on this file, this file does not
+ * by itself cause the resulting work to be covered by the GNU General Public
+ * License. However the source code for this file must still be made available
+ * in accordance with section (3) of the GNU General Public License.
+
+ * This exception does not invalidate any other reasons why a work based on
+ * this file might be covered by the GNU General Public License.
+ */
+
+#ifndef __COMMON_H__
+#define __COMMON_H__
+
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/stddef.h>
+#include <stdio.h>
+
+#define BUG() do { \
+} while (0)
+
+#endif /* __COMMON_H__ */
diff --git a/apps/include/ctype.h b/apps/include/ctype.h
new file mode 100644
index 0000000..09eb175
--- /dev/null
+++ b/apps/include/ctype.h
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2013 Jean-Christophe PLAGNIOL-VILLARD <plagnio@jcrosoft.com>
+ *
+ * Under GPLv2 only
+ *
+ * As a special exception, if other files instantiate templates or use macros
+ * or inline functions from this file, or you compile this file and link it
+ * with other works to produce a work based on this file, this file does not
+ * by itself cause the resulting work to be covered by the GNU General Public
+ * License. However the source code for this file must still be made available
+ * in accordance with section (3) of the GNU General Public License.
+
+ * This exception does not invalidate any other reasons why a work based on
+ * this file might be covered by the GNU General Public License.
+ */
+
+#ifndef __CTYPE_H__
+#define __CTYPE_H__
+
+static inline int tolower(int c)
+{
+	return (c >= 'A' && c <= 'Z') ? (c + 32) : c;
+}
+
+static inline int toupper(int c)
+{
+	return (c >= 'a' && c <= 'z') ? (c - 32) : c;
+}
+
+static inline int toascii(int c)
+{
+	return ((unsigned char)c) & 0x7f;
+}
+
+static inline int isalpha(int c)
+{
+	return ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'));
+}
+
+static inline int isascii(int c)
+{
+	return (c >= 0 && c <= 127);
+}
+
+static inline int isblank(int c)
+{
+	return (c == ' ' || c == '\t');
+}
+
+static inline int iscntrl(int c)
+{
+	return (c <= 31 || c == 127);
+}
+
+static inline int isdigit(int c)
+{
+	return (c >= '0' && c <= '9');
+}
+
+static inline int isalnum(int c)
+{
+	return isalpha(c) || isdigit(c);
+}
+
+static inline int isgraph(int c)
+{
+	return (c >= 33 && c <= 126);
+}
+
+static inline int islower(int c)
+{
+	return (c >= 'a' && c <= 'z');
+}
+
+static inline int isprint(int c)
+{
+	return (c >= 32 && c <= 126);
+}
+
+static inline int isspace(int c)
+{
+	return (c == ' ' || (c >= '\t' && c <= '\r'));
+}
+
+static inline int ispunct(int c)
+{
+	return isprint(c) && !isspace(c) && !isalnum(c);
+}
+
+static inline int isupper(int c)
+{
+	return (c >= 'A' && c <= 'Z');
+}
+
+static inline int isxdigit(int c)
+{
+	return isdigit(c) || (tolower(c) >= 'a' && tolower(c) <= 'f');
+}
+
+#endif /* __CTYPE_H__ */
diff --git a/apps/include/dirent.h b/apps/include/dirent.h
new file mode 100644
index 0000000..df26461
--- /dev/null
+++ b/apps/include/dirent.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2013 Jean-Christophe PLAGNIOL-VILLARD <plagnio@jcrosoft.com>
+ *
+ * Under GPLv2 only
+ *
+ * As a special exception, if other files instantiate templates or use macros
+ * or inline functions from this file, or you compile this file and link it
+ * with other works to produce a work based on this file, this file does not
+ * by itself cause the resulting work to be covered by the GNU General Public
+ * License. However the source code for this file must still be made available
+ * in accordance with section (3) of the GNU General Public License.
+
+ * This exception does not invalidate any other reasons why a work based on
+ * this file might be covered by the GNU General Public License.
+ */
+
+#ifndef __DIRENT_H__
+#define __DIRENT_H__
+
+DIR *opendir(const char *name);
+struct dirent *readdir(DIR *dir);
+int closedir(DIR *dir);
+
+#endif /* __DIRENT_H__ */
diff --git a/apps/include/errno.h b/apps/include/errno.h
new file mode 100644
index 0000000..e7d5c90
--- /dev/null
+++ b/apps/include/errno.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2013 Jean-Christophe PLAGNIOL-VILLARD <plagnio@jcrosoft.com>
+ *
+ * Under GPLv2 only
+ *
+ * As a special exception, if other files instantiate templates or use macros
+ * or inline functions from this file, or you compile this file and link it
+ * with other works to produce a work based on this file, this file does not
+ * by itself cause the resulting work to be covered by the GNU General Public
+ * License. However the source code for this file must still be made available
+ * in accordance with section (3) of the GNU General Public License.
+
+ * This exception does not invalidate any other reasons why a work based on
+ * this file might be covered by the GNU General Public License.
+ */
+
+#ifndef __ERRNO_H__
+#define __ERRNO_H__
+
+#include <asm-generic/errno.h>
+
+extern int errno;
+
+#endif /* __ERRNO_H__ */
diff --git a/apps/include/fcntl.h b/apps/include/fcntl.h
new file mode 100644
index 0000000..7bc8980
--- /dev/null
+++ b/apps/include/fcntl.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2013 Jean-Christophe PLAGNIOL-VILLARD <plagnio@jcrosoft.com>
+ *
+ * Under GPLv2 only
+ *
+ * As a special exception, if other files instantiate templates or use macros
+ * or inline functions from this file, or you compile this file and link it
+ * with other works to produce a work based on this file, this file does not
+ * by itself cause the resulting work to be covered by the GNU General Public
+ * License. However the source code for this file must still be made available
+ * in accordance with section (3) of the GNU General Public License.
+
+ * This exception does not invalidate any other reasons why a work based on
+ * this file might be covered by the GNU General Public License.
+ */
+
+#ifndef __FCNTL_H__
+#define __FCNTL_H__
+
+#include <barebox/fcntl.h>
+
+/* barebox does not handle the last optionnal arg */
+int open(const char *name, int flags, ...);
+
+#endif /* __FCNTL_H__ */
diff --git a/apps/include/getopt.h b/apps/include/getopt.h
new file mode 100644
index 0000000..b6c03d1
--- /dev/null
+++ b/apps/include/getopt.h
@@ -0,0 +1,76 @@
+/*	$OpenBSD: getopt.h,v 1.2 2008/06/26 05:42:04 ray Exp $	*/
+/*	$NetBSD: getopt.h,v 1.4 2000/07/07 10:43:54 ad Exp $	*/
+
+/*-
+ * Copyright (c) 2000 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Dieter Baron and Thomas Klausner.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _GETOPT_H_
+#define _GETOPT_H_
+
+#include <sys/types.h>
+
+/*
+ * GNU-like getopt_long() and 4.4BSD getsubopt()/optreset extensions
+ */
+#define no_argument        0
+#define required_argument  1
+#define optional_argument  2
+
+struct option {
+	/* name of long option */
+	const char *name;
+	/*
+	 * one of no_argument, required_argument, and optional_argument:
+	 * whether option takes an argument
+	 */
+	int has_arg;
+	/* if not NULL, set *flag to val when option found */
+	int *flag;
+	/* if flag not NULL, value to set *flag to; else return value */
+	int val;
+};
+
+int	 getopt_long(int, char * const *, const char *,
+	    const struct option *, int *);
+int	 getopt_long_only(int, char * const *, const char *,
+	    const struct option *, int *);
+#ifndef _GETOPT_DEFINED_
+#define _GETOPT_DEFINED_
+int	 getopt(int, char * const *, const char *);
+int	 getsubopt(char **, char * const *, char **);
+
+extern   char *optarg;                  /* getopt(3) external variables */
+extern   int opterr;
+extern   int optind;
+extern   int optopt;
+extern   int optreset;
+extern   char *suboptarg;               /* getsubopt(3) external variable */
+#endif
+
+#endif /* !_GETOPT_H_ */
diff --git a/apps/include/libc_config.h b/apps/include/libc_config.h
new file mode 100644
index 0000000..752a417
--- /dev/null
+++ b/apps/include/libc_config.h
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2013 Jean-Christophe PLAGNIOL-VILLARD <plagnio@jcrosoft.com>
+ *
+ * Under GPLv2 only
+ *
+ * As a special exception, if other files instantiate templates or use macros
+ * or inline functions from this file, or you compile this file and link it
+ * with other works to produce a work based on this file, this file does not
+ * by itself cause the resulting work to be covered by the GNU General Public
+ * License. However the source code for this file must still be made available
+ * in accordance with section (3) of the GNU General Public License.
+
+ * This exception does not invalidate any other reasons why a work based on
+ * this file might be covered by the GNU General Public License.
+ */
+
+#ifndef __LIBC_CONFIG_H__
+#define __LIBC_CONFIG_H__
+
+#define LIBC_MAJOR	0
+#define LIBC_MINOR	1
+#define LIBC_SUBMINOR	0
+
+#define __str(x) #x
+#define str(x) __str(x)
+
+#define LIBC_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
+#define LIBC_VERSION_CODE LIBC_VERSION(LIBC_MAJOR, LIBC_MINOR, LIBC_SUBMINOR)
+#define LIBC_VERSION_STRING str(LIBC_MAJOR) "." str(LIBC_MINOR) "." str(LIBC_SUBMINOR)
+
+/* dirent.h */
+#define LIBC_HAVE_DIRENT_H 1
+
+#define LIBC_HAVE_OPENDIR 1
+#define LIBC_HAVE_READDIR 1
+#define LIBC_HAVE_CLOSEDIR 1
+
+/* fcntl.h */
+#define LIBC_HAVE_FCNTL_H 1
+
+#define LIBC_HAVE_OPEN 1
+
+/* getopt.h */
+#define LIBC_HAVE_GETOPT_H 1
+
+#define LIBC_HAVE_GETOPT_LONG 1
+#define LIBC_HAVE_GETOPT_LONG_ONLY 1
+//#define LIBC_HAVE_GETOPT 1
+#define LIBC_HAVE_GETSUBOPT 1
+
+/* malloc.h */
+#define LIBC_HAVE_MALLOC_H 1
+
+#define LIBC_HAVE_MALLOC 1
+#define LIBC_HAVE_FREE 1
+#define LIBC_HAVE_REALLOC 1
+#define LIBC_HAVE_MEMALIGN 1
+#define LIBC_HAVE_CALLOC 1
+#define LIBC_HAVE_CFREE 1
+
+/* stdio.h */
+#define LIBC_HAVE_STDIO_H 1
+
+#define LIBC_HAVE_PUTCHAR 1
+#define LIBC_HAVE_GETCHAR 1
+#define LIBC_HAVE_PUTS 1
+
+#define LIBC_HAVE_FPRINTF 1
+#define LIBC_HAVE_VFPRINTF 1
+#define LIBC_HAVE_FPUTS 1
+#define LIBC_HAVE_FPUTC 1
+#define LIBC_HAVE_FOPEN 1
+#define LIBC_HAVE_FCLOSE 1
+#define LIBC_HAVE_FREAD 1
+#define LIBC_HAVE_FWRITE 1
+#define LIBC_HAVE_FSEEK 1
+
+#define LIBC_HAVE_PRINTF 1
+#define LIBC_HAVE_VPRINTF 1
+#define LIBC_HAVE_SPRINTF 1
+#define LIBC_HAVE_SNPRINTF 1
+#define LIBC_HAVE_VSPRINTF 1
+#define LIBC_HAVE_ASPRINTF 1
+#define LIBC_HAVE_VASPRINTF 1
+#define LIBC_HAVE_VSNPRINTF 1
+#define LIBC_HAVE_VSCNPRINTF 1
+
+/* barebox API */
+#define LIBC_HAVE_BAREBOX_API 1
+
+#define LIBC_HAVE_EPUTC 1
+#define LIBC_HAVE_EPUTS 1
+#define LIBC_HAVE_TSTC 1
+#define LIBC_HAVE_FLUSH 1
+#define LIBC_HAVE_ITOA 1
+
+/* stdlib.h */
+#define LIBC_HAVE_STDLIB_H 1
+
+#define LIBC_HAVE_GETENV 1
+#define LIBC_HAVE_EXIT 1
+
+/* unistd.h */
+#define LIBC_HAVE_UNISTD_H 1
+
+#define LIBC_HAVE_READ 1
+#define LIBC_HAVE_WRITE 1
+#define LIBC_HAVE_CLOSE 1
+#define LIBC_HAVE_STAT 1
+#define LIBC_HAVE_LSTAT 1
+
+#define LIBC_HAVE_LSEEK 1
+#define LIBC_HAVE_UNLINK 1
+#define LIBC_HAVE_SYMLINK 1
+#define LIBC_HAVE_READLINK 1
+#define LIBC_HAVE_RMDIR 1
+#define LIBC_HAVE_GETCWD 1
+#define LIBC_HAVE_GET_CURRENT_DIR_NAME 1
+#define LIBC_HAVE_CHDIR 1
+#define LIBC_HAVE_USLEEP 1
+
+#define LIBC_HAVE_GETOPT 1
+
+/* sys/ioctl.h */
+#define LIBC_HAVE_SYS_IOCTL_H 1
+
+#define LIBC_HAVE_IOCTL 1
+
+/* sys/stat.h */
+#define LIBC_HAVE_SYS_STAT_H 1
+
+#define LIBC_HAVE_MKDIR 1
+
+/* sys/syscall.h */
+#define LIBC_HAVE_SYS_SYSCALL_H 1
+
+#define LIBC_HAVE_SYSCALL 1
+
+#endif /* __LIBC_CONFIG_H__ */
diff --git a/apps/include/limits.h b/apps/include/limits.h
new file mode 100644
index 0000000..3625d07
--- /dev/null
+++ b/apps/include/limits.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2013 Jean-Christophe PLAGNIOL-VILLARD <plagnio@jcrosoft.com>
+ *
+ * Under GPLv2 only
+ *
+ * As a special exception, if other files instantiate templates or use macros
+ * or inline functions from this file, or you compile this file and link it
+ * with other works to produce a work based on this file, this file does not
+ * by itself cause the resulting work to be covered by the GNU General Public
+ * License. However the source code for this file must still be made available
+ * in accordance with section (3) of the GNU General Public License.
+
+ * This exception does not invalidate any other reasons why a work based on
+ * this file might be covered by the GNU General Public License.
+ */
+
+#ifndef __LIMITS_H__
+#define __LIMITS_H__
+
+#include <sys/types.h>
+
+#define USHORT_MAX	((u16)(~0U))
+#define SHORT_MAX	((s16)(USHORT_MAX>>1))
+#define SHORT_MIN	(-SHORT_MAX - 1)
+#define INT_MAX		((int)(~0U>>1))
+#define INT_MIN		(-INT_MAX - 1)
+#define UINT_MAX	(~0U)
+#define LONG_MAX	((long)(~0UL>>1))
+#define LONG_MIN	(-LONG_MAX - 1)
+#define ULONG_MAX	(~0UL)
+#define LLONG_MAX	((long long)(~0ULL>>1))
+#define LLONG_MIN	(-LLONG_MAX - 1)
+#define ULLONG_MAX	(~0ULL)
+
+#define PATH_MAX	CONFIG_APP_PATH_MAX
+#define ENV_MAX		CONFIG_APP_ENV_MAX
+
+#endif /* __LIMITS_H__ */
diff --git a/apps/include/malloc.h b/apps/include/malloc.h
new file mode 100644
index 0000000..0017419
--- /dev/null
+++ b/apps/include/malloc.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2013 Jean-Christophe PLAGNIOL-VILLARD <plagnio@jcrosoft.com>
+ *
+ * Under GPLv2 only
+ *
+ * As a special exception, if other files instantiate templates or use macros
+ * or inline functions from this file, or you compile this file and link it
+ * with other works to produce a work based on this file, this file does not
+ * by itself cause the resulting work to be covered by the GNU General Public
+ * License. However the source code for this file must still be made available
+ * in accordance with section (3) of the GNU General Public License.
+
+ * This exception does not invalidate any other reasons why a work based on
+ * this file might be covered by the GNU General Public License.
+ */
+
+#ifndef __MALLOC_H
+#define __MALLOC_H
+
+#include <types.h>
+
+void* malloc(size_t);
+void free(void*);
+void* realloc(void*, size_t);
+void* memalign(size_t, size_t);
+void* calloc(size_t, size_t);
+void cfree(void*);
+
+#endif
+
diff --git a/apps/include/module.h b/apps/include/module.h
new file mode 100644
index 0000000..c62d65b
--- /dev/null
+++ b/apps/include/module.h
@@ -0,0 +1,3 @@
+#define EXPORT_SYMBOL(sym)
+#define EXPORT_SYMBOL_GPL(sym)
+
diff --git a/apps/include/sections.h b/apps/include/sections.h
new file mode 100644
index 0000000..fc262a6
--- /dev/null
+++ b/apps/include/sections.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2013 Jean-Christophe PLAGNIOL-VILLARD <plagnio@jcrosoft.com>
+ *
+ * Under GPLv2 only
+ *
+ * As a special exception, if other files instantiate templates or use macros
+ * or inline functions from this file, or you compile this file and link it
+ * with other works to produce a work based on this file, this file does not
+ * by itself cause the resulting work to be covered by the GNU General Public
+ * License. However the source code for this file must still be made available
+ * in accordance with section (3) of the GNU General Public License.
+
+ * This exception does not invalidate any other reasons why a work based on
+ * this file might be covered by the GNU General Public License.
+ */
+
+#ifndef _APPS_GENERIC_SECTIONS_H_
+#define _APPS_GENERIC_SECTIONS_H_
+
+extern char _text[], _stext[], _etext[];
+extern char __bss_start[], __bss_stop[];
+extern char _sdata[], _edata[];
+extern char _end[];
+extern void *_barebox_app_image_size;
+extern char __appinfo_start[], __appinfo_end[];
+
+#define _barebox_app_image_size	(unsigned int)&_barebox_app_image_size
+
+#endif /* _APPS_GENERIC_SECTIONS_H_ */
diff --git a/apps/include/setjmp.h b/apps/include/setjmp.h
new file mode 100644
index 0000000..ff9dd8d
--- /dev/null
+++ b/apps/include/setjmp.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2013 Jean-Christophe PLAGNIOL-VILLARD <plagnio@jcrosoft.com>
+ *
+ * Under GPLv2 only
+ *
+ * As a special exception, if other files instantiate templates or use macros
+ * or inline functions from this file, or you compile this file and link it
+ * with other works to produce a work based on this file, this file does not
+ * by itself cause the resulting work to be covered by the GNU General Public
+ * License. However the source code for this file must still be made available
+ * in accordance with section (3) of the GNU General Public License.
+
+ * This exception does not invalidate any other reasons why a work based on
+ * this file might be covered by the GNU General Public License.
+ */
+
+#ifndef __SETJMP_H__
+#define __SETJMP_H__
+
+#include <arch/setjmp.h>
+
+int setjmp(jmp_buf);
+void __attribute__((noreturn)) longjmp(jmp_buf, int);
+
+#endif /* __SETJMP_H__ */
diff --git a/apps/include/stddef.h b/apps/include/stddef.h
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/apps/include/stddef.h
@@ -0,0 +1 @@
+
diff --git a/apps/include/stdint.h b/apps/include/stdint.h
new file mode 100644
index 0000000..f5ad912
--- /dev/null
+++ b/apps/include/stdint.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2013 Jean-Christophe PLAGNIOL-VILLARD <plagnio@jcrosoft.com>
+ *
+ * Under GPLv2 only
+ *
+ * As a special exception, if other files instantiate templates or use macros
+ * or inline functions from this file, or you compile this file and link it
+ * with other works to produce a work based on this file, this file does not
+ * by itself cause the resulting work to be covered by the GNU General Public
+ * License. However the source code for this file must still be made available
+ * in accordance with section (3) of the GNU General Public License.
+
+ * This exception does not invalidate any other reasons why a work based on
+ * this file might be covered by the GNU General Public License.
+ */
+
+#ifndef __STDINT_H__
+#define __STDINT_H__
+
+#define INT64_C(c) (c ## LL)
+#define UINT64_C(c) (c ## ULL)
+
+#endif /* __STDINT_H__ */
diff --git a/apps/include/stdio.h b/apps/include/stdio.h
new file mode 100644
index 0000000..32a7d25
--- /dev/null
+++ b/apps/include/stdio.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2013 Jean-Christophe PLAGNIOL-VILLARD <plagnio@jcrosoft.com>
+ *
+ * Under GPLv2 only
+ *
+ * As a special exception, if other files instantiate templates or use macros
+ * or inline functions from this file, or you compile this file and link it
+ * with other works to produce a work based on this file, this file does not
+ * by itself cause the resulting work to be covered by the GNU General Public
+ * License. However the source code for this file must still be made available
+ * in accordance with section (3) of the GNU General Public License.
+
+ * This exception does not invalidate any other reasons why a work based on
+ * this file might be covered by the GNU General Public License.
+ */
+
+#ifndef __STDIO_H__
+#define __STDIO_H__
+
+#include <stdarg.h>
+#include <sys/types.h>
+
+#define EXIT_FAILURE	1
+#define EXIT_SUCCESS	0
+#define EOF -1
+
+void putchar(char c);
+int getchar(void);
+int puts(const char *str);
+
+struct __file;
+typedef struct __file FILE;
+
+extern FILE stdin;
+extern FILE stdout;
+extern FILE stderr;
+
+#define stdin (&stdin)
+#define stdout (&stdout)
+#define stderr (&stderr)
+
+int fprintf(FILE *f, const char *fmt, ...) __attribute__ ((format(__printf__, 2, 3)));
+int vfprintf(FILE *f, const char *fmt, va_list args);
+int fputs(const char *s, FILE *f);
+int fputc(int c, FILE *f);
+FILE *fopen(const char *path, const char *mode);
+int fclose(FILE *f);
+size_t fread(void *buf, size_t size, size_t nb, FILE *f);
+size_t fwrite(const void *buf, size_t size, size_t nb, FILE *f);
+int fseek(FILE *stream, long offset, int whence);
+
+/* barebox API */
+void eputc(char c);
+int eputs(const char *str);
+int tstc(void);
+int flush(int fd);
+char* itoa(int i);
+
+static int printf(const char *fmt, ...) __attribute__ ((format(__printf__, 1, 2)));
+static inline int printf(const char *fmt, ...)
+{
+	return 0;
+}
+
+static inline int vprintf(const char *fmt, va_list args)
+{
+	return 0;
+}
+
+#endif /* __STDIO_H__ */
diff --git a/apps/include/stdlib.h b/apps/include/stdlib.h
new file mode 100644
index 0000000..7ae78ad
--- /dev/null
+++ b/apps/include/stdlib.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2013 Jean-Christophe PLAGNIOL-VILLARD <plagnio@jcrosoft.com>
+ *
+ * Under GPLv2 only
+ *
+ * As a special exception, if other files instantiate templates or use macros
+ * or inline functions from this file, or you compile this file and link it
+ * with other works to produce a work based on this file, this file does not
+ * by itself cause the resulting work to be covered by the GNU General Public
+ * License. However the source code for this file must still be made available
+ * in accordance with section (3) of the GNU General Public License.
+
+ * This exception does not invalidate any other reasons why a work based on
+ * this file might be covered by the GNU General Public License.
+ */
+
+#ifndef __STDLIB_H__
+#define __STDLIB_H__
+
+#define EXIT_FAILURE 1
+#define EXIT_SUCCESS 0
+
+char *getenv(const char *name);
+void exit(int num);
+int atoi(const char *s);
+long atol(const char *s);
+long long atoll(const char *s);
+
+#endif /* __STDLIB_H__ */
diff --git a/apps/include/string.h b/apps/include/string.h
new file mode 100644
index 0000000..95b94a3
--- /dev/null
+++ b/apps/include/string.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2013 Jean-Christophe PLAGNIOL-VILLARD <plagnio@jcrosoft.com>
+ *
+ * Under GPLv2 only
+ *
+ * As a special exception, if other files instantiate templates or use macros
+ * or inline functions from this file, or you compile this file and link it
+ * with other works to produce a work based on this file, this file does not
+ * by itself cause the resulting work to be covered by the GNU General Public
+ * License. However the source code for this file must still be made available
+ * in accordance with section (3) of the GNU General Public License.
+
+ * This exception does not invalidate any other reasons why a work based on
+ * this file might be covered by the GNU General Public License.
+ */
+
+#ifndef __STRING_H
+#define __STRING_H
+
+#include <types.h>
+
+extern char * ___strtok;
+extern char * strpbrk(const char *,const char *);
+extern char * strtok(char *,const char *);
+extern char * strsep(char **,const char *);
+extern size_t strspn(const char *,const char *);
+
+extern char * strcpy(char *,const char *);
+extern char * strncpy(char *,const char *, size_t);
+size_t strlcpy(char *, const char *, size_t);
+extern char * strcat(char *, const char *);
+extern char * strncat(char *, const char *, size_t);
+extern int strcmp(const char *,const char *);
+extern int strncmp(const char *,const char *,size_t);
+extern char * strchr(const char *,int);
+extern char * strrchr(const char *,int);
+extern char * strstr(const char *,const char *);
+extern size_t strlen(const char *);
+extern size_t strnlen(const char *,size_t);
+extern char * strdup(const char *);
+extern char * strswab(const char *);
+
+extern void * memset(void *,int,size_t);
+extern void * memcpy(void *,const void *,size_t);
+extern void * memmove(void *,const void *,size_t);
+extern void * memscan(void *,int,size_t);
+extern int memcmp(const void *,const void *,size_t);
+extern void * memchr(const void *,int,size_t);
+extern char * skip_spaces(const char *);
+
+extern char *strim(char *);
+
+#endif /* __STRING_H */
diff --git a/apps/include/sys/ioctl.h b/apps/include/sys/ioctl.h
new file mode 100644
index 0000000..58e9760
--- /dev/null
+++ b/apps/include/sys/ioctl.h
@@ -0,0 +1,12 @@
+/*
+ * Copyright (C) 2013 Jean-Christophe PLAGNIOL-VILLARD <plagnio@jcrosoft.com>
+ *
+ * Under GPLv2 only
+*/
+
+#ifndef __SYS_IOCTL_H__
+#define __SYS_IOCTL_H__
+
+int ioctl(int fd, int request, void *buf);
+
+#endif /* __SYS_IOCTL_H__ */
diff --git a/apps/include/sys/stat.h b/apps/include/sys/stat.h
new file mode 100644
index 0000000..c1cecf9
--- /dev/null
+++ b/apps/include/sys/stat.h
@@ -0,0 +1,14 @@
+/*
+ * Copyright (C) 2013 Jean-Christophe PLAGNIOL-VILLARD <plagnio@jcrosoft.com>
+ *
+ * Under GPLv2 only
+*/
+
+#ifndef __SYS_STAT_H__
+#define __SYS_STAT_H__
+
+#include <linux/stat.h>
+
+int mkdir(const char *path, mode_t mode);
+
+#endif /* __SYS_STAT_H__ */
diff --git a/apps/include/sys/syscall.h b/apps/include/sys/syscall.h
new file mode 100644
index 0000000..4ffb09a
--- /dev/null
+++ b/apps/include/sys/syscall.h
@@ -0,0 +1,14 @@
+/*
+ * Copyright (C) 2013 Jean-Christophe PLAGNIOL-VILLARD <plagnio@jcrosoft.com>
+ *
+ * Under GPLv2 only
+*/
+
+#ifndef __SYS_SYSCALL_H__
+#define __SYS_SYSCALL_H__
+
+#include <errno.h>
+
+int syscall(int num, ...);
+
+#endif /* __SYS_SYSCALL_H__ */
diff --git a/apps/include/sys/types.h b/apps/include/sys/types.h
new file mode 100644
index 0000000..ec48b2e
--- /dev/null
+++ b/apps/include/sys/types.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (C) 2013 Jean-Christophe PLAGNIOL-VILLARD <plagnio@jcrosoft.com>
+ *
+ * Under GPLv2 only
+*/
+
+#ifndef __SYS_TYPES_H__
+#define __SYS_TYPES_H__
+
+#include <linux/types.h>
+#include <barebox/types.h>
+
+typedef unsigned int useconds_t;
+
+#endif /* __SYS_TYPES_H__ */
diff --git a/apps/include/time.h b/apps/include/time.h
new file mode 100644
index 0000000..d067e25
--- /dev/null
+++ b/apps/include/time.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2013 Jean-Christophe PLAGNIOL-VILLARD <plagnio@jcrosoft.com>
+ *
+ * Under GPLv2 only
+ *
+ * As a special exception, if other files instantiate templates or use macros
+ * or inline functions from this file, or you compile this file and link it
+ * with other works to produce a work based on this file, this file does not
+ * by itself cause the resulting work to be covered by the GNU General Public
+ * License. However the source code for this file must still be made available
+ * in accordance with section (3) of the GNU General Public License.
+
+ * This exception does not invalidate any other reasons why a work based on
+ * this file might be covered by the GNU General Public License.
+ */
+
+#ifndef __TIME_H__
+#define __TIME_H__
+
+struct timespec {
+	time_t	tv_sec;		/* seconds */
+	long	tv_nsec;	/* nanoseconds */
+};
+
+int nanosleep(const struct timespec *req, struct timespec *rem);
+
+#endif /* __TIME_H__ */
diff --git a/apps/include/unistd.h b/apps/include/unistd.h
new file mode 100644
index 0000000..dbd8cef
--- /dev/null
+++ b/apps/include/unistd.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2013 Jean-Christophe PLAGNIOL-VILLARD <plagnio@jcrosoft.com>
+ *
+ * Under GPLv2 only
+ *
+ * As a special exception, if other files instantiate templates or use macros
+ * or inline functions from this file, or you compile this file and link it
+ * with other works to produce a work based on this file, this file does not
+ * by itself cause the resulting work to be covered by the GNU General Public
+ * License. However the source code for this file must still be made available
+ * in accordance with section (3) of the GNU General Public License.
+
+ * This exception does not invalidate any other reasons why a work based on
+ * this file might be covered by the GNU General Public License.
+ */
+
+#ifndef __UNISTD_H__
+#define __UNISTD_H__
+
+struct stat;
+
+ssize_t read(int fd, void *buf, size_t count);
+ssize_t write(int fd, const void *buf, size_t count);
+int close(int fd);
+int stat(const char *path, struct stat *buf);
+int lstat(const char *path, struct stat *buf);
+
+#define SEEK_SET        1
+#define SEEK_CUR        2
+#define SEEK_END        3
+
+loff_t lseek(int fd, loff_t offset, int whence);
+int unlink(const char *pathname);
+int symlink(const char *pathname, const char *newpath);
+ssize_t readlink(const char *path, char *buf, size_t bufsiz);
+int rmdir(const char *path);
+char *getcwd(char *buf, size_t size);
+char *get_current_dir_name(void);
+int chdir(const char *path);
+int usleep(unsigned int usec);
+
+int getopt(int argc, char * const argv[], const char *optstring);
+extern char *optarg;
+extern int optind, opterr, optopt;
+
+#endif /* __UNISTD_H__ */
diff --git a/apps/libc/Kconfig b/apps/libc/Kconfig
new file mode 100644
index 0000000..b9478b5
--- /dev/null
+++ b/apps/libc/Kconfig
@@ -0,0 +1,25 @@
+menu "libc"
+
+choice
+	prompt "malloc implementation"
+
+config APPS_MALLOC_TLSF
+	bool "tlsf"
+
+config APPS_MALLOC_DUMMY
+	bool "dummy malloc"
+	help
+	  select this option to use a dummy malloc implementation. With this
+	  memory is never freed. This is suitable for well tested noninteractive
+	  environments only.
+
+endchoice
+
+config APP_GETOPT_LONG_AS_GETOPT
+	bool "use getopt_long as getopt"
+
+config APP_PRINTF_STACK_SIZE
+	hex "printf stack size"
+	default 0x1000
+
+endmenu
diff --git a/apps/libc/Makefile b/apps/libc/Makefile
new file mode 100644
index 0000000..844ea9b
--- /dev/null
+++ b/apps/libc/Makefile
@@ -0,0 +1,36 @@
+app-y += appinfo.o
+app-y += dirent.o
+app-y += errno.o
+app-y += fcntl.o
+app-y += flags.o
+ifneq ($(CONFIG_APP_GETOPT_LONG_AS_GETOPT),y)
+app-y += getopt.o
+endif
+app-y += getopt_long.o
+app-y += malloc.o
+app-y += stdio.o
+app-y += stdlib.o
+app-y += syscalls.o
+app-y += unistd.o
+app-$(CONFIG_APPS_MALLOC_DUMMY) += dummy_malloc.o
+app-$(CONFIG_APPS_MALLOC_TLSF) += tlsf_malloc.o tlsf.o
+app-y += string.o
+obj-y += sys/
+app-y += time.o
+
+$(obj)/dummy_malloc.c: $(srctree)/common/dummy_malloc.c FORCE
+	$(call cmd,shipped)
+
+$(obj)/tlsf.c: $(srctree)/common/tlsf.c $(obj)/tlsfbits.h FORCE
+	$(call cmd,shipped)
+
+$(obj)/tlsf_malloc.c: $(srctree)/common/tlsf_malloc.c $(obj)/tlsf.h FORCE
+	$(call cmd,shipped)
+
+$(obj)/tlsfbits.h: $(srctree)/common/tlsfbits.h FORCE
+	$(call cmd,shipped)
+
+$(obj)/tlsf.h: $(srctree)/include/tlsf.h FORCE
+	$(call cmd,shipped)
+
+$(obj)/app-malloc.o: $(obj)/tlsfbits.h
diff --git a/apps/libc/appinfo.c b/apps/libc/appinfo.c
new file mode 100644
index 0000000..7eff526
--- /dev/null
+++ b/apps/libc/appinfo.c
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2013 Jean-Christophe PLAGNIOL-VILLARD <plagnio@jcrosoft.com>
+ *
+ * Under GPLv2 only
+ *
+ * As a special exception, if other files instantiate templates or use macros
+ * or inline functions from this file, or you compile this file and link it
+ * with other works to produce a work based on this file, this file does not
+ * by itself cause the resulting work to be covered by the GNU General Public
+ * License. However the source code for this file must still be made available
+ * in accordance with section (3) of the GNU General Public License.
+
+ * This exception does not invalidate any other reasons why a work based on
+ * this file might be covered by the GNU General Public License.
+ */
+
+#include <sections.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <appinfo.h>
+#include <libc_config.h>
+
+void print_appinfo(void)
+{
+	char *info = (char*)&__appinfo_start;
+
+	for (; info < (char*)&__appinfo_end; info += strlen(info) + 1)
+		printf("%s\n", info);
+}
+
+APP_INFO(libc, "barebox libc")
+APP_INFO(libc_author, "Jean-Christophe PLANGIOL-VILLARD <plagnioj@jcrosoft.com>")
+APP_INFO(libc_license, "GPLv2 + exception")
+APP_INFO(libc_version, LIBC_VERSION_STRING)
diff --git a/apps/libc/dirent.c b/apps/libc/dirent.c
new file mode 100644
index 0000000..b2a78ad
--- /dev/null
+++ b/apps/libc/dirent.c
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2013 Jean-Christophe PLAGNIOL-VILLARD <plagnio@jcrosoft.com>
+ *
+ * Under GPLv2 only
+ *
+ * As a special exception, if other files instantiate templates or use macros
+ * or inline functions from this file, or you compile this file and link it
+ * with other works to produce a work based on this file, this file does not
+ * by itself cause the resulting work to be covered by the GNU General Public
+ * License. However the source code for this file must still be made available
+ * in accordance with section (3) of the GNU General Public License.
+
+ * This exception does not invalidate any other reasons why a work based on
+ * this file might be covered by the GNU General Public License.
+ */
+
+#include <barebox/syscalls.h>
+#include <sys/syscall.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <malloc.h>
+#include <errno.h>
+
+DIR *opendir(const char *name)
+{
+	DIR *d = malloc(sizeof(DIR));
+
+	if (!d)
+		return NULL;
+
+	if (syscall(SYS_opendir, d, name))
+		goto err;
+
+	return d;
+err:
+	free(d);
+	return NULL;
+}
+
+static struct dirent d_read;
+
+struct dirent *readdir(DIR *dir)
+{
+	if (!dir)
+		return NULL;
+
+	if (syscall(SYS_readdir, dir, &d_read))
+		return NULL;
+
+	return &d_read;
+}
+
+int closedir(DIR *dir)
+{
+	if (!dir)
+		return -EINVAL;
+
+	return syscall(SYS_closedir, dir);
+}
diff --git a/apps/libc/errno.c b/apps/libc/errno.c
new file mode 100644
index 0000000..640d09c
--- /dev/null
+++ b/apps/libc/errno.c
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2013 Jean-Christophe PLAGNIOL-VILLARD <plagnio@jcrosoft.com>
+ *
+ * Under GPLv2 only
+ *
+ * As a special exception, if other files instantiate templates or use macros
+ * or inline functions from this file, or you compile this file and link it
+ * with other works to produce a work based on this file, this file does not
+ * by itself cause the resulting work to be covered by the GNU General Public
+ * License. However the source code for this file must still be made available
+ * in accordance with section (3) of the GNU General Public License.
+
+ * This exception does not invalidate any other reasons why a work based on
+ * this file might be covered by the GNU General Public License.
+ */
+
+#include <errno.h>
+
+int errno;
diff --git a/apps/libc/fcntl.c b/apps/libc/fcntl.c
new file mode 100644
index 0000000..da26955
--- /dev/null
+++ b/apps/libc/fcntl.c
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2013 Jean-Christophe PLAGNIOL-VILLARD <plagnio@jcrosoft.com>
+ *
+ * Under GPLv2 only
+ *
+ * As a special exception, if other files instantiate templates or use macros
+ * or inline functions from this file, or you compile this file and link it
+ * with other works to produce a work based on this file, this file does not
+ * by itself cause the resulting work to be covered by the GNU General Public
+ * License. However the source code for this file must still be made available
+ * in accordance with section (3) of the GNU General Public License.
+
+ * This exception does not invalidate any other reasons why a work based on
+ * this file might be covered by the GNU General Public License.
+ */
+
+#include <barebox/syscalls.h>
+#include <sys/syscall.h>
+#include <fcntl.h>
+
+/* barebox does not handle the last optionnal arg */
+int open(const char *name, int flags, ...)
+{
+	return syscall(SYS_open, name, flags);
+}
diff --git a/apps/libc/flags.c b/apps/libc/flags.c
new file mode 100644
index 0000000..4d4487b
--- /dev/null
+++ b/apps/libc/flags.c
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2013 Jean-Christophe PLAGNIOL-VILLARD <plagnio@jcrosoft.com>
+ *
+ * Under GPLv2 only
+ *
+ * As a special exception, if other files instantiate templates or use macros
+ * or inline functions from this file, or you compile this file and link it
+ * with other works to produce a work based on this file, this file does not
+ * by itself cause the resulting work to be covered by the GNU General Public
+ * License. However the source code for this file must still be made available
+ * in accordance with section (3) of the GNU General Public License.
+
+ * This exception does not invalidate any other reasons why a work based on
+ * this file might be covered by the GNU General Public License.
+ */
+
+#include <sys/types.h>
+#include <fcntl.h>
+#include <errno.h>
+
+int __str_to_flags(const char *mode, int *flag)
+{
+	int _mode;
+	int opt;
+
+	switch (*mode++) {
+	case 'r':
+		_mode = O_RDONLY;
+		opt = 0;
+		break;
+
+	case 'w':
+		_mode = O_WRONLY;
+		opt = O_CREAT | O_TRUNC;
+		break;
+
+	case 'a':
+		_mode = O_WRONLY;
+		opt = O_CREAT | O_APPEND;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	/* binary ingnore it */
+	if (*mode == 'b')
+		mode++;
+
+	/* read/write */
+	if (*mode == '+') {
+		mode++;
+		_mode = O_RDWR;
+	}
+
+	/* binary ingnore it */
+	if (*mode == 'b')
+		mode++;
+
+	/*
+	 * barebox does not supprot it
+	 * just check we are not it RO mode
+	 */
+	if (*mode == 'x') {
+		mode++;
+		if (_mode == O_RDONLY)
+			return -EINVAL;
+	}
+
+	/* barebox does not support it */
+	if (*mode == 'e')
+		mode++;
+
+	*flag = _mode | opt;
+	return 0;
+}
diff --git a/apps/libc/getopt.c b/apps/libc/getopt.c
new file mode 100644
index 0000000..b445af8
--- /dev/null
+++ b/apps/libc/getopt.c
@@ -0,0 +1,127 @@
+/*	$NetBSD: getopt.c,v 1.26 2003/08/07 16:43:40 agc Exp $	*/
+
+/*
+ * Copyright (c) 1987, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "private.h"
+
+int	opterr = 1,		/* if error message should be printed */
+	optind = 1,		/* index into parent argv vector */
+	optopt,			/* character checked for validity */
+	optreset;		/* reset getopt */
+char	*optarg;		/* argument associated with option */
+
+#define	BADCH	(int)'?'
+#define	BADARG	(int)':'
+#define	EMSG	""
+
+/*
+ * getopt --
+ *	Parse argc/argv argument vector.
+ */
+int
+getopt(nargc, nargv, ostr)
+	int nargc;
+	char * const nargv[];
+	const char *ostr;
+{
+	static char *place = EMSG;		/* option letter processing */
+	char *oli;				/* option letter list index */
+
+	if (optreset || *place == 0) {		/* update scanning pointer */
+		optreset = 0;
+		place = nargv[optind];
+		if (optind >= nargc || *place++ != '-') {
+			/* Argument is absent or is not an option */
+			place = EMSG;
+			return (-1);
+		}
+		optopt = *place++;
+		if (optopt == '-' && *place == 0) {
+			/* "--" => end of options */
+			++optind;
+			place = EMSG;
+			return (-1);
+		}
+		if (optopt == 0) {
+			/* Solitary '-', treat as a '-' option
+			   if the program (eg su) is looking for it. */
+			place = EMSG;
+			if (strchr(ostr, '-') == NULL)
+				return (-1);
+			optopt = '-';
+		}
+	} else
+		optopt = *place++;
+
+	/* See if option letter is one the caller wanted... */
+	if (optopt == ':' || (oli = (char*)strchr(ostr, optopt)) == NULL) {
+		if (*place == 0)
+			++optind;
+		if (opterr && *ostr != ':')
+			(void)fprintf(stderr,
+			    "%s: illegal option -- %c\n", __progname,
+			    optopt);
+		return (BADCH);
+	}
+
+	/* Does this option need an argument? */
+	if (oli[1] != ':') {
+		/* don't need argument */
+		optarg = NULL;
+		if (*place == 0)
+			++optind;
+	} else {
+		/* Option-argument is either the rest of this argument or the
+		   entire next argument. */
+		if (*place)
+			optarg = place;
+		else if (nargc > ++optind)
+			optarg = nargv[optind];
+		else {
+			/* option-argument absent */
+			place = EMSG;
+			if (*ostr == ':')
+				return (BADARG);
+			if (opterr)
+				(void)fprintf(stderr,
+				    "%s: option requires an argument -- %c\n",
+				    __progname, optopt);
+			return (BADCH);
+		}
+		place = EMSG;
+		++optind;
+	}
+	return (optopt);			/* return option letter */
+}
diff --git a/apps/libc/getopt_long.c b/apps/libc/getopt_long.c
new file mode 100644
index 0000000..ed7add7
--- /dev/null
+++ b/apps/libc/getopt_long.c
@@ -0,0 +1,625 @@
+/*	$OpenBSD: getopt_long.c,v 1.22 2006/10/04 21:29:04 jmc Exp $	*/
+/*	$NetBSD: getopt_long.c,v 1.15 2002/01/31 22:43:40 tv Exp $	*/
+
+/*
+ * Copyright (c) 2002 Todd C. Miller <Todd.Miller@courtesan.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Sponsored in part by the Defense Advanced Research Projects
+ * Agency (DARPA) and Air Force Research Laboratory, Air Force
+ * Materiel Command, USAF, under agreement number F39502-99-1-0512.
+ */
+/*-
+ * Copyright (c) 2000 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Dieter Baron and Thomas Klausner.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <errno.h>
+#include <getopt.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+
+#include "private.h"
+
+#define GNU_COMPATIBLE		/* Be more compatible, configure's use us! */
+
+#ifdef CONFIG_APP_GETOPT_LONG_AS_GETOPT	/* we prefer to keep our getopt(3) */
+#define	REPLACE_GETOPT		/* use this getopt as the system getopt(3) */
+#endif
+
+#ifdef REPLACE_GETOPT
+int	opterr = 1;		/* if error message should be printed */
+int	optind = 1;		/* index into parent argv vector */
+int	optopt = '?';		/* character checked for validity */
+int	optreset;		/* reset getopt */
+char    *optarg;		/* argument associated with option */
+#endif
+
+#define PRINT_ERROR	((opterr) && (*options != ':'))
+
+#define FLAG_PERMUTE	0x01	/* permute non-options to the end of argv */
+#define FLAG_ALLARGS	0x02	/* treat non-options as args to option "-1" */
+#define FLAG_LONGONLY	0x04	/* operate as getopt_long_only */
+
+/* return values */
+#define	BADCH		(int)'?'
+#define	BADARG		((*options == ':') ? (int)':' : (int)'?')
+#define	INORDER 	(int)1
+
+#define	EMSG		""
+
+#ifdef GNU_COMPATIBLE
+#define NO_PREFIX	(-1)
+#define D_PREFIX	0
+#define DD_PREFIX	1
+#define W_PREFIX	2
+#endif
+
+static int getopt_internal(int, char * const *, const char *,
+			   const struct option *, int *, int);
+static int parse_long_options(char * const *, const char *,
+			      const struct option *, int *, int, int);
+static int gcd(int, int);
+static void permute_args(int, int, int, char * const *);
+
+static char *place = EMSG; /* option letter processing */
+
+/* XXX: set optreset to 1 rather than these two */
+static int nonopt_start = -1; /* first non option argument (for permute) */
+static int nonopt_end = -1;   /* first option after non options (for permute) */
+
+/* Error messages */
+static const char recargchar[] = "option requires an argument -- %c";
+static const char illoptchar[] = "illegal option -- %c"; /* From P1003.2 */
+#ifdef GNU_COMPATIBLE
+static int dash_prefix = NO_PREFIX;
+static const char gnuoptchar[] = "invalid option -- %c";
+
+static const char recargstring[] = "option `%s%s' requires an argument";
+static const char ambig[] = "option `%s%.*s' is ambiguous";
+static const char noarg[] = "option `%s%.*s' doesn't allow an argument";
+static const char illoptstring[] = "unrecognized option `%s%s'";
+#else
+static const char recargstring[] = "option requires an argument -- %s";
+static const char ambig[] = "ambiguous option -- %.*s";
+static const char noarg[] = "option doesn't take an argument -- %.*s";
+static const char illoptstring[] = "unknown option -- %s";
+#endif
+
+void warnx(const char *fmt, ...)
+{
+	va_list ap;
+	va_start(ap, fmt);
+
+	(void)fprintf(stderr, "%s: ", __progname);
+	if (fmt != NULL)
+		(void)vfprintf(stderr, fmt, ap);
+	(void)fprintf(stderr, "\n");
+	va_end(ap);
+}
+
+/*
+ * Compute the greatest common divisor of a and b.
+ */
+static int
+gcd(int a, int b)
+{
+	int c;
+
+	c = a % b;
+	while (c != 0) {
+		a = b;
+		b = c;
+		c = a % b;
+	}
+
+	return (b);
+}
+
+/*
+ * Exchange the block from nonopt_start to nonopt_end with the block
+ * from nonopt_end to opt_end (keeping the same order of arguments
+ * in each block).
+ */
+static void
+permute_args(int panonopt_start, int panonopt_end, int opt_end,
+	char * const *nargv)
+{
+	int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos;
+	char *swap;
+
+	/*
+	 * compute lengths of blocks and number and size of cycles
+	 */
+	nnonopts = panonopt_end - panonopt_start;
+	nopts = opt_end - panonopt_end;
+	ncycle = gcd(nnonopts, nopts);
+	cyclelen = (opt_end - panonopt_start) / ncycle;
+
+	for (i = 0; i < ncycle; i++) {
+		cstart = panonopt_end+i;
+		pos = cstart;
+		for (j = 0; j < cyclelen; j++) {
+			if (pos >= panonopt_end)
+				pos -= nnonopts;
+			else
+				pos += nopts;
+			swap = nargv[pos];
+			/* LINTED const cast */
+			((char **) nargv)[pos] = nargv[cstart];
+			/* LINTED const cast */
+			((char **)nargv)[cstart] = swap;
+		}
+	}
+}
+
+/*
+ * parse_long_options --
+ *	Parse long options in argc/argv argument vector.
+ * Returns -1 if short_too is set and the option does not match long_options.
+ */
+static int
+parse_long_options(char * const *nargv, const char *options,
+	const struct option *long_options, int *idx, int short_too, int flags)
+{
+	char *current_argv, *has_equal;
+#ifdef GNU_COMPATIBLE
+	char *current_dash;
+#endif
+	size_t current_argv_len;
+	int i, match, exact_match, second_partial_match;
+
+	current_argv = place;
+#ifdef GNU_COMPATIBLE
+	switch (dash_prefix) {
+		case D_PREFIX:
+			current_dash = "-";
+			break;
+		case DD_PREFIX:
+			current_dash = "--";
+			break;
+		case W_PREFIX:
+			current_dash = "-W ";
+			break;
+		default:
+			current_dash = "";
+			break;
+	}
+#endif
+	match = -1;
+	exact_match = 0;
+	second_partial_match = 0;
+
+	optind++;
+
+	if ((has_equal = strchr(current_argv, '=')) != NULL) {
+		/* argument found (--option=arg) */
+		current_argv_len = has_equal - current_argv;
+		has_equal++;
+	} else
+		current_argv_len = strlen(current_argv);
+
+	for (i = 0; long_options[i].name; i++) {
+		/* find matching long option */
+		if (strncmp(current_argv, long_options[i].name,
+		    current_argv_len))
+			continue;
+
+		if (strlen(long_options[i].name) == current_argv_len) {
+			/* exact match */
+			match = i;
+			exact_match = 1;
+			break;
+		}
+		/*
+		 * If this is a known short option, don't allow
+		 * a partial match of a single character.
+		 */
+		if (short_too && current_argv_len == 1)
+			continue;
+
+		if (match == -1)        /* first partial match */
+			match = i;
+		else if ((flags & FLAG_LONGONLY) ||
+			 long_options[i].has_arg !=
+			     long_options[match].has_arg ||
+			 long_options[i].flag != long_options[match].flag ||
+			 long_options[i].val != long_options[match].val)
+			second_partial_match = 1;
+	}
+	if (!exact_match && second_partial_match) {
+		/* ambiguous abbreviation */
+		if (PRINT_ERROR)
+			warnx(ambig,
+#ifdef GNU_COMPATIBLE
+			     current_dash,
+#endif
+			     (int)current_argv_len,
+			     current_argv);
+		optopt = 0;
+		return (BADCH);
+	}
+	if (match != -1) {		/* option found */
+		if (long_options[match].has_arg == no_argument
+		    && has_equal) {
+			if (PRINT_ERROR)
+				warnx(noarg,
+#ifdef GNU_COMPATIBLE
+				     current_dash,
+#endif
+				     (int)current_argv_len,
+				     current_argv);
+			/*
+			 * XXX: GNU sets optopt to val regardless of flag
+			 */
+			if (long_options[match].flag == NULL)
+				optopt = long_options[match].val;
+			else
+				optopt = 0;
+#ifdef GNU_COMPATIBLE
+			return (BADCH);
+#else
+			return (BADARG);
+#endif
+		}
+		if (long_options[match].has_arg == required_argument ||
+		    long_options[match].has_arg == optional_argument) {
+			if (has_equal)
+				optarg = has_equal;
+			else if (long_options[match].has_arg ==
+			    required_argument) {
+				/*
+				 * optional argument doesn't use next nargv
+				 */
+				optarg = nargv[optind++];
+			}
+		}
+		if ((long_options[match].has_arg == required_argument)
+		    && (optarg == NULL)) {
+			/*
+			 * Missing argument; leading ':' indicates no error
+			 * should be generated.
+			 */
+			if (PRINT_ERROR)
+				warnx(recargstring,
+#ifdef GNU_COMPATIBLE
+				    current_dash,
+#endif
+				    current_argv);
+			/*
+			 * XXX: GNU sets optopt to val regardless of flag
+			 */
+			if (long_options[match].flag == NULL)
+				optopt = long_options[match].val;
+			else
+				optopt = 0;
+			--optind;
+			return (BADARG);
+		}
+	} else {			/* unknown option */
+		if (short_too) {
+			--optind;
+			return (-1);
+		}
+		if (PRINT_ERROR)
+			warnx(illoptstring,
+#ifdef GNU_COMPATIBLE
+			      current_dash,
+#endif
+			      current_argv);
+		optopt = 0;
+		return (BADCH);
+	}
+	if (idx)
+		*idx = match;
+	if (long_options[match].flag) {
+		*long_options[match].flag = long_options[match].val;
+		return (0);
+	} else
+		return (long_options[match].val);
+}
+
+/*
+ * getopt_internal --
+ *	Parse argc/argv argument vector.  Called by user level routines.
+ */
+static int
+getopt_internal(int nargc, char * const *nargv, const char *options,
+	const struct option *long_options, int *idx, int flags)
+{
+	char *oli;				/* option letter list index */
+	int optchar, short_too;
+	int posixly_correct;	/* no static, can be changed on the fly */
+
+	if (options == NULL)
+		return (-1);
+
+	/*
+	 * Disable GNU extensions if POSIXLY_CORRECT is set or options
+	 * string begins with a '+'.
+	 */
+	posixly_correct = (getenv("POSIXLY_CORRECT") != NULL);
+#ifdef GNU_COMPATIBLE
+	if (*options == '-')
+		flags |= FLAG_ALLARGS;
+	else if (posixly_correct || *options == '+')
+		flags &= ~FLAG_PERMUTE;
+#else
+	if (posixly_correct || *options == '+')
+		flags &= ~FLAG_PERMUTE;
+	else if (*options == '-')
+		flags |= FLAG_ALLARGS;
+#endif
+	if (*options == '+' || *options == '-')
+		options++;
+
+	/*
+	 * XXX Some GNU programs (like cvs) set optind to 0 instead of
+	 * XXX using optreset.  Work around this braindamage.
+	 */
+	if (optind == 0)
+		optind = optreset = 1;
+
+	optarg = NULL;
+	if (optreset)
+		nonopt_start = nonopt_end = -1;
+start:
+	if (optreset || !*place) {		/* update scanning pointer */
+		optreset = 0;
+		if (optind >= nargc) {          /* end of argument vector */
+			place = EMSG;
+			if (nonopt_end != -1) {
+				/* do permutation, if we have to */
+				permute_args(nonopt_start, nonopt_end,
+				    optind, nargv);
+				optind -= nonopt_end - nonopt_start;
+			}
+			else if (nonopt_start != -1) {
+				/*
+				 * If we skipped non-options, set optind
+				 * to the first of them.
+				 */
+				optind = nonopt_start;
+			}
+			nonopt_start = nonopt_end = -1;
+			return (-1);
+		}
+		if (*(place = nargv[optind]) != '-' ||
+#ifdef GNU_COMPATIBLE
+		    place[1] == '\0') {
+#else
+		    (place[1] == '\0' && strchr(options, '-') == NULL)) {
+#endif
+			place = EMSG;		/* found non-option */
+			if (flags & FLAG_ALLARGS) {
+				/*
+				 * GNU extension:
+				 * return non-option as argument to option 1
+				 */
+				optarg = nargv[optind++];
+				return (INORDER);
+			}
+			if (!(flags & FLAG_PERMUTE)) {
+				/*
+				 * If no permutation wanted, stop parsing
+				 * at first non-option.
+				 */
+				return (-1);
+			}
+			/* do permutation */
+			if (nonopt_start == -1)
+				nonopt_start = optind;
+			else if (nonopt_end != -1) {
+				permute_args(nonopt_start, nonopt_end,
+				    optind, nargv);
+				nonopt_start = optind -
+				    (nonopt_end - nonopt_start);
+				nonopt_end = -1;
+			}
+			optind++;
+			/* process next argument */
+			goto start;
+		}
+		if (nonopt_start != -1 && nonopt_end == -1)
+			nonopt_end = optind;
+
+		/*
+		 * If we have "-" do nothing, if "--" we are done.
+		 */
+		if (place[1] != '\0' && *++place == '-' && place[1] == '\0') {
+			optind++;
+			place = EMSG;
+			/*
+			 * We found an option (--), so if we skipped
+			 * non-options, we have to permute.
+			 */
+			if (nonopt_end != -1) {
+				permute_args(nonopt_start, nonopt_end,
+				    optind, nargv);
+				optind -= nonopt_end - nonopt_start;
+			}
+			nonopt_start = nonopt_end = -1;
+			return (-1);
+		}
+	}
+
+	/*
+	 * Check long options if:
+	 *  1) we were passed some
+	 *  2) the arg is not just "-"
+	 *  3) either the arg starts with -- we are getopt_long_only()
+	 */
+	if (long_options != NULL && place != nargv[optind] &&
+	    (*place == '-' || (flags & FLAG_LONGONLY))) {
+		short_too = 0;
+#ifdef GNU_COMPATIBLE
+		dash_prefix = D_PREFIX;
+#endif
+		if (*place == '-') {
+			place++;		/* --foo long option */
+#ifdef GNU_COMPATIBLE
+			dash_prefix = DD_PREFIX;
+#endif
+		} else if (*place != ':' && strchr(options, *place) != NULL)
+			short_too = 1;		/* could be short option too */
+
+		optchar = parse_long_options(nargv, options, long_options,
+		    idx, short_too, flags);
+		if (optchar != -1) {
+			place = EMSG;
+			return (optchar);
+		}
+	}
+
+	if ((optchar = (int)*place++) == (int)':' ||
+	    (optchar == (int)'-' && *place != '\0') ||
+	    (oli = (char*)strchr(options, optchar)) == NULL) {
+		/*
+		 * If the user specified "-" and  '-' isn't listed in
+		 * options, return -1 (non-option) as per POSIX.
+		 * Otherwise, it is an unknown option character (or ':').
+		 */
+		if (optchar == (int)'-' && *place == '\0')
+			return (-1);
+		if (!*place)
+			++optind;
+#ifdef GNU_COMPATIBLE
+		if (PRINT_ERROR)
+			warnx(posixly_correct ? illoptchar : gnuoptchar,
+			      optchar);
+#else
+		if (PRINT_ERROR)
+			warnx(illoptchar, optchar);
+#endif
+		optopt = optchar;
+		return (BADCH);
+	}
+	if (long_options != NULL && optchar == 'W' && oli[1] == ';') {
+		/* -W long-option */
+		if (*place)			/* no space */
+			/* NOTHING */;
+		else if (++optind >= nargc) {	/* no arg */
+			place = EMSG;
+			if (PRINT_ERROR)
+				warnx(recargchar, optchar);
+			optopt = optchar;
+			return (BADARG);
+		} else				/* white space */
+			place = nargv[optind];
+#ifdef GNU_COMPATIBLE
+		dash_prefix = W_PREFIX;
+#endif
+		optchar = parse_long_options(nargv, options, long_options,
+		    idx, 0, flags);
+		place = EMSG;
+		return (optchar);
+	}
+	if (*++oli != ':') {			/* doesn't take argument */
+		if (!*place)
+			++optind;
+	} else {				/* takes (optional) argument */
+		optarg = NULL;
+		if (*place)			/* no white space */
+			optarg = place;
+		else if (oli[1] != ':') {	/* arg not optional */
+			if (++optind >= nargc) {	/* no arg */
+				place = EMSG;
+				if (PRINT_ERROR)
+					warnx(recargchar, optchar);
+				optopt = optchar;
+				return (BADARG);
+			} else
+				optarg = nargv[optind];
+		}
+		place = EMSG;
+		++optind;
+	}
+	/* dump back option letter */
+	return (optchar);
+}
+
+#ifdef REPLACE_GETOPT
+/*
+ * getopt --
+ *	Parse argc/argv argument vector.
+ *
+ * [eventually this will replace the BSD getopt]
+ */
+int
+getopt(int nargc, char * const *nargv, const char *options)
+{
+
+	/*
+	 * We don't pass FLAG_PERMUTE to getopt_internal() since
+	 * the BSD getopt(3) (unlike GNU) has never done this.
+	 *
+	 * Furthermore, since many privileged programs call getopt()
+	 * before dropping privileges it makes sense to keep things
+	 * as simple (and bug-free) as possible.
+	 */
+	return (getopt_internal(nargc, nargv, options, NULL, NULL, 0));
+}
+#endif /* REPLACE_GETOPT */
+
+/*
+ * getopt_long --
+ *	Parse argc/argv argument vector.
+ */
+int
+getopt_long(int nargc, char * const *nargv, const char *options,
+	const struct option *long_options, int *idx)
+{
+
+	return (getopt_internal(nargc, nargv, options, long_options, idx,
+	    FLAG_PERMUTE));
+}
+
+/*
+ * getopt_long_only --
+ *	Parse argc/argv argument vector.
+ */
+int
+getopt_long_only(int nargc, char * const *nargv, const char *options,
+	const struct option *long_options, int *idx)
+{
+
+	return (getopt_internal(nargc, nargv, options, long_options, idx,
+	    FLAG_PERMUTE|FLAG_LONGONLY));
+}
diff --git a/apps/libc/malloc.c b/apps/libc/malloc.c
new file mode 100644
index 0000000..ab4b8b5
--- /dev/null
+++ b/apps/libc/malloc.c
@@ -0,0 +1,50 @@
+#include <malloc.h>
+#include <types.h>
+#include <string.h>
+
+#include "malloc.h"
+/*
+ * Begin and End of memory area for malloc(), and current "brk"
+ */
+static unsigned long malloc_start;
+static unsigned long malloc_end;
+static unsigned long malloc_brk;
+
+static void *sbrk_no_zero(ptrdiff_t increment)
+{
+	unsigned long old = malloc_brk;
+	unsigned long new = old + increment;
+
+	if ((new < malloc_start) || (new > malloc_end))
+		return NULL;
+
+	malloc_brk = new;
+
+	return (void *)old;
+}
+
+void *sbrk(ptrdiff_t increment)
+{
+	void *old = sbrk_no_zero(increment);
+
+	/* Only clear increment, if valid address was returned */
+	if (old != NULL)
+		memset(old, 0, increment);
+
+	return old;
+}
+
+#ifdef CONFIG_APPS_MALLOC_TLSF
+#include <tlsf.h>
+tlsf_pool tlsf_mem_pool;
+#endif
+
+void mem_malloc_init(void *start, void *end)
+{
+	malloc_start = (unsigned long)start;
+	malloc_end = (unsigned long)end;
+	malloc_brk = malloc_start;
+#ifdef CONFIG_APPS_MALLOC_TLSF
+	tlsf_mem_pool = tlsf_create(start, end - start + 1);
+#endif
+}
diff --git a/apps/libc/malloc.h b/apps/libc/malloc.h
new file mode 100644
index 0000000..7995fb1
--- /dev/null
+++ b/apps/libc/malloc.h
@@ -0,0 +1,2 @@
+
+void mem_malloc_init(void *start, void *end);
diff --git a/apps/libc/private.h b/apps/libc/private.h
new file mode 100644
index 0000000..9a56544
--- /dev/null
+++ b/apps/libc/private.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) 2013 Jean-Christophe PLAGNIOL-VILLARD <plagnio@jcrosoft.com>
+ *
+ * Under GPLv2 only
+*/
+
+#ifndef __LIBC_PRIVATE_H__
+#define __LIBC_PRIVATE_H__
+
+extern char *__progname;
+int __str_to_flags(const char *mode, int *flag);
+
+struct __file {
+	int fd;
+	struct __file *cookie; /* to check the file is open */
+};
+
+#endif /* __LIBC_PRIVATE_H__ */
diff --git a/apps/libc/stdio.c b/apps/libc/stdio.c
new file mode 100644
index 0000000..82233f7
--- /dev/null
+++ b/apps/libc/stdio.c
@@ -0,0 +1,275 @@
+/*
+ * Copyright (C) 2013 Jean-Christophe PLAGNIOL-VILLARD <plagnio@jcrosoft.com>
+ *
+ * Under GPLv2 only
+ *
+ * As a special exception, if other files instantiate templates or use macros
+ * or inline functions from this file, or you compile this file and link it
+ * with other works to produce a work based on this file, this file does not
+ * by itself cause the resulting work to be covered by the GNU General Public
+ * License. However the source code for this file must still be made available
+ * in accordance with section (3) of the GNU General Public License.
+
+ * This exception does not invalidate any other reasons why a work based on
+ * this file might be covered by the GNU General Public License.
+ */
+
+#include <barebox/syscalls.h>
+#include <sys/syscall.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <malloc.h>
+#include <fcntl.h>
+
+#include "private.h"
+
+#undef stderr
+#undef stdin
+#undef stdout
+
+FILE stdin = { .fd = 0, .cookie = &stdin, };
+FILE stdout = { .fd = 1, .cookie = &stdout, };
+FILE stderr = { .fd = 2, .cookie = &stderr, };
+
+void putchar(char c)
+{
+	syscall(SYS_putchar, c);
+}
+
+void eputc(char c)
+{
+	syscall(SYS_eputc, c);
+}
+
+int getchar(void)
+{
+	return syscall(SYS_getchar);
+}
+
+int tstc(void)
+{
+	return syscall(SYS_tstc);
+}
+
+int ioctl(int fd, int request, void *buf)
+{
+	return syscall(SYS_ioctl, fd, request, buf);
+}
+
+int eputs(const char *str)
+{
+	const char *s = str;
+	int i = 0;
+
+	while (*s) {
+		eputc(*s);
+		if (*s == '\n')
+			eputc('\r');
+		s++;
+		i++;
+	}
+
+	return i;
+}
+
+int puts(const char *str)
+{
+	const char *s = str;
+	int i = 0;
+
+	while (*s) {
+		putchar(*s);
+		if (*s == '\n')
+			putchar('\r');
+		s++;
+		i++;
+	}
+
+	return i;
+}
+
+int printf(const char *fmt, ...)
+{
+	va_list args;
+	uint i;
+	char printbuffer[CONFIG_APP_PRINTF_STACK_SIZE];
+
+	va_start(args, fmt);
+	i = vsprintf (printbuffer, fmt, args);
+	va_end(args);
+
+	puts(printbuffer);
+
+	return i;
+}
+
+int vprintf(const char *fmt, va_list args)
+{
+	uint i;
+	char printbuffer[CONFIG_APP_PRINTF_STACK_SIZE];
+
+	i = vsprintf(printbuffer, fmt, args);
+
+	puts(printbuffer);
+
+	return i;
+}
+
+/* FILE implementation */
+
+static int __files_used = 0;
+
+static void __file_free(FILE *f)
+{
+	free(f);
+	f = NULL;
+	__files_used--;
+}
+
+static bool __file_sanity_check(FILE *f)
+{
+	return f->cookie != NULL;
+}
+
+static FILE *__file_malloc(void)
+{
+	FILE *f;
+
+	if (__files_used >= CONFIG_APP_FILE_MAX)
+		return NULL;
+
+	f = calloc(1, sizeof(*f));	
+	if (!f)
+		return NULL;
+
+	f->cookie = f;
+	__files_used++;
+	return f;
+}
+
+int fputs(const char *s, FILE *f)
+{
+	if (!__file_sanity_check(f))
+		return -EINVAL;
+
+	if (f == &stdout)
+		return puts(s);
+	else if (f == &stderr)
+		return eputs(s);
+	else
+		return write(f->fd, s, strlen(s));
+}
+
+int fputc(int c, FILE *f)
+{
+	if (!__file_sanity_check(f))
+		return -EINVAL;
+
+	if (f == &stdout)
+		putchar(c);
+	else if (f == &stderr)
+		eputc(c);
+	else
+		return write(f->fd, &c, 1);
+
+	return 1;
+}
+
+int vfprintf(FILE *file, const char *fmt, va_list args)
+{
+	char printbuffer[CONFIG_APP_PRINTF_STACK_SIZE];
+
+	vsprintf(printbuffer, fmt, args);
+
+	return fputs(printbuffer, file);
+}
+
+int fprintf(FILE *file, const char *fmt, ...)
+{
+	va_list args;
+	int ret;
+
+	va_start(args, fmt);
+	ret = vfprintf(file, fmt, args);
+	va_end(args);
+
+	return ret;
+}
+
+FILE *fopen(const char *path, const char *mode)
+{
+	int flags;
+	int fd;
+	FILE *f;
+
+	fd = __str_to_flags(mode, &flags);
+	if (fd)
+		return NULL;
+
+	f = __file_malloc();
+	if (!f)
+		return NULL;
+
+	fd = open(mode, flags); 
+	if (fd < 0) {
+		__file_free(f);
+		return NULL;
+	}
+
+	f->fd = fd;
+
+	return f;
+}
+
+int fclose(FILE *f)
+{
+	if (!__file_sanity_check(f))
+		return -EINVAL;
+
+	if (f == &stderr || f == &stdout || f == &stdin)
+		return -EINVAL;
+
+	close(f->fd);
+
+	__file_free(f);
+
+	return 0;
+}
+
+size_t fread(void *buf, size_t size, size_t nb, FILE *f)
+{
+	if (!__file_sanity_check(f))
+		return -EINVAL;
+
+	return read(f->fd, buf, size * nb);
+}
+
+size_t fwrite(const void *buf, size_t size, size_t nb, FILE *f)
+{
+	if (!__file_sanity_check(f))
+		return -EINVAL;
+
+	return write(f->fd, buf, size * nb);
+}
+
+int fseek(FILE *f, long offset, int whence)
+{
+	if (!__file_sanity_check(f))
+		return -EINVAL;
+
+	return lseek(f->fd, offset, whence);
+}
+
+char* itoa(int i)
+{
+	char printbuffer[26];
+	char *p = &printbuffer[25];
+	*p-- = '\0';
+	do {
+		*p-- = '0' + i % 10;
+		i /= 10;
+	} while (i > 0);
+	return p + 1;
+}
diff --git a/apps/libc/stdlib.c b/apps/libc/stdlib.c
new file mode 100644
index 0000000..0ec07ac
--- /dev/null
+++ b/apps/libc/stdlib.c
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2013 Jean-Christophe PLAGNIOL-VILLARD <plagnio@jcrosoft.com>
+ *
+ * Under GPLv2 only
+ *
+ * As a special exception, if other files instantiate templates or use macros
+ * or inline functions from this file, or you compile this file and link it
+ * with other works to produce a work based on this file, this file does not
+ * by itself cause the resulting work to be covered by the GNU General Public
+ * License. However the source code for this file must still be made available
+ * in accordance with section (3) of the GNU General Public License.
+
+ * This exception does not invalidate any other reasons why a work based on
+ * this file might be covered by the GNU General Public License.
+ */
+
+#include <barebox/syscalls.h>
+#include <sys/syscall.h>
+#include <limits.h>
+#include <malloc.h>
+#include <errno.h>
+#include <ctype.h>
+
+static char env[ENV_MAX];
+
+char *getenv(const char *name)
+{
+	if (syscall(SYS_getenv, name, env))
+		return NULL;
+
+	return env;
+}
+
+int atoi(const char *s)
+{
+	int i = 0;
+	bool minus;
+
+	if (*s == '-') {
+		minus = true;
+		s++;
+	}
+
+	while (isdigit(*s))
+		i = i * 10 + *(s++) - '0';
+	return (minus) ? -i : i;
+}
+
+long atol(const char *s)
+{
+	long i = 0;
+	bool minus;
+
+	if (*s == '-') {
+		minus = true;
+		s++;
+	}
+
+	while (isdigit(*s))
+		i = i * 10 + *(s++) - '0';
+	return (minus) ? -i : i;
+}
+
+long long atoll(const char *s)
+{
+	long long i = 0;
+	bool minus;
+
+	if (*s == '-') {
+		minus = true;
+		s++;
+	}
+
+	while (isdigit(*s))
+		i = i * 10 + *(s++) - '0';
+	return (minus) ? -i : i;
+}
diff --git a/apps/libc/string.c b/apps/libc/string.c
new file mode 100644
index 0000000..67a34f9
--- /dev/null
+++ b/apps/libc/string.c
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2013 Jean-Christophe PLAGNIOL-VILLARD <plagnio@jcrosoft.com>
+ *
+ * Under GPLv2 only
+ *
+ * As a special exception, if other files instantiate templates or use macros
+ * or inline functions from this file, or you compile this file and link it
+ * with other works to produce a work based on this file, this file does not
+ * by itself cause the resulting work to be covered by the GNU General Public
+ * License. However the source code for this file must still be made available
+ * in accordance with section (3) of the GNU General Public License.
+
+ * This exception does not invalidate any other reasons why a work based on
+ * this file might be covered by the GNU General Public License.
+ */
+
+#include <sys/types.h>
+#include <string.h>
+#include <malloc.h>
+
+void *memcpy(void *dst, const void *src, size_t count)
+{
+	char *d = (char *)dst;
+	const char *s = (const char *)src;
+
+	while (count--)
+		*d++ = *s++;
+
+	return d;
+}
+
+void *memset(void *dst, int val, size_t count)
+{
+	char *d = (char *)dst;
+
+	while (count--)
+		*d++ = (char)val;
+
+	return d;
+}
+
+int memcmp(const void *dst, const void *src, size_t count)
+{
+	const char *d = (const char *)dst;
+	const char *s = (const char *)src;
+	int r = 0;
+
+	while (count-- && (r = *d++ - *s++) == 0) ;
+
+	return r;
+}
+
+unsigned int strlen(const char *s)
+{
+	const char *p;
+
+	for (p = s; *p != '\0'; p++)
+		;
+	return p - s;
+}
+
+char *strcpy(char *dst, const char *src)
+{
+	char *tmp = dst;
+
+	while ((*dst++ = *src++) != '\0')
+		;
+
+	return tmp;
+}
+
+int strcmp(const char *s1, const char *s2)
+{
+	signed char res;
+
+	while (1) {
+		res = *s1 - *s2++;
+		
+		if (res)
+			break;
+
+		if (!*s1++)
+			break;
+	}
+
+	return res;
+}
+
+int strncmp(const char *s1, const char *s2, size_t count)
+{
+	signed char res;
+
+	while (count--) {
+		res = *s1 - *s2++;
+		
+		if (res)
+			break;
+
+		if (!*s1++)
+			break;
+	}
+
+	return res;
+}
+
+char *strchr(const char *s, int c)
+{
+	for (; *s != (char) c; ++s)
+		if (*s == '\0')
+			return NULL;
+
+	return (char *)s;
+}
+
+void *memchr(const void *src, int val, size_t count)
+{
+	const char *s = src;
+
+	while (count--) {
+		if (*s++ == val)
+			return (void*)(s - 1);
+	}
+
+	return NULL;
+}
+
+void *memmove(void *dst, const void *src, size_t count)
+{
+	char *p, *s;
+
+	if (dst <= src) {
+		p = (char *)dst;
+		s = (char *)src;
+		while (count--)
+			*p++ = *s++;
+	} else {
+		p = (char *)dst + count;
+		s = (char *)src + count;
+		while (count--)
+			*--p = *--s;
+	}
+
+	return dst;
+}
+
+char *strdup(const char *s)
+{
+	char *p;
+
+	if (!s)
+		return NULL;
+		
+	p = malloc (strlen(s) + 1);
+	if (!p)
+		return NULL;
+
+	strcpy (p, s);
+	return p;
+}
diff --git a/apps/libc/sys/Makefile b/apps/libc/sys/Makefile
new file mode 100644
index 0000000..119f373
--- /dev/null
+++ b/apps/libc/sys/Makefile
@@ -0,0 +1,2 @@
+
+app-y += stat.o
diff --git a/apps/libc/sys/stat.c b/apps/libc/sys/stat.c
new file mode 100644
index 0000000..decc227
--- /dev/null
+++ b/apps/libc/sys/stat.c
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2013 Jean-Christophe PLAGNIOL-VILLARD <plagnio@jcrosoft.com>
+ *
+ * Under GPLv2 only
+ *
+ * As a special exception, if other files instantiate templates or use macros
+ * or inline functions from this file, or you compile this file and link it
+ * with other works to produce a work based on this file, this file does not
+ * by itself cause the resulting work to be covered by the GNU General Public
+ * License. However the source code for this file must still be made available
+ * in accordance with section (3) of the GNU General Public License.
+
+ * This exception does not invalidate any other reasons why a work based on
+ * this file might be covered by the GNU General Public License.
+ */
+
+#include <barebox/syscalls.h>
+#include <sys/syscall.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+int mkdir(const char *path, mode_t mode)
+{
+	return syscall(SYS_mkdir, path, mode);
+}
diff --git a/apps/libc/syscalls.c b/apps/libc/syscalls.c
new file mode 100644
index 0000000..796a681
--- /dev/null
+++ b/apps/libc/syscalls.c
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2013 Jean-Christophe PLAGNIOL-VILLARD <plagnio@jcrosoft.com>
+ *
+ * Under GPLv2 only
+ *
+ * As a special exception, if other files instantiate templates or use macros
+ * or inline functions from this file, or you compile this file and link it
+ * with other works to produce a work based on this file, this file does not
+ * by itself cause the resulting work to be covered by the GNU General Public
+ * License. However the source code for this file must still be made available
+ * in accordance with section (3) of the GNU General Public License.
+
+ * This exception does not invalidate any other reasons why a work based on
+ * this file might be covered by the GNU General Public License.
+ */
+
+#include <barebox/syscalls.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <sections.h>
+
+#include "malloc.h"
+#include "private.h"
+
+int main(int argc, char **argv);
+
+static bool is_valid_syscall(void *addr)
+{
+	return strncmp(addr, SYSCALLS_MAGIC, 8) == 0;
+}
+
+void panic(char *s)
+{
+	puts(s);
+	exit(10);
+}
+
+static void **syscalls;
+static uint32_t nb_syscalls;
+
+int syscall(int num, ...)
+{
+	long (*__syscall)(unsigned long arg0, unsigned long arg1, unsigned long arg2);
+	va_list args;
+	unsigned long arg0;
+	unsigned long arg1;
+	unsigned long arg2;
+	int ret;
+
+	if (num >= nb_syscalls)
+		return -1;
+
+	va_start(args, num);
+	arg0 = va_arg(args, unsigned long);
+	arg1 = va_arg(args, unsigned long);
+	arg2 = va_arg(args, unsigned long);
+	__syscall = syscalls[num];
+	ret = __syscall(arg0, arg1, arg2);
+
+	va_end(args);
+
+	return ret;
+}
+
+int syscalls_parse(struct syscalls_header *sys)
+{
+#ifndef	CONFIG_PHYS_ADDR_T_64BIT
+	uint32_t malloc_base = sys->malloc_base & 0xffffffff;
+	uint32_t malloc_end = malloc_base + sys->malloc_size - 1;
+#else
+	uint64_t malloc_base = sys->malloc_base;
+	uint64_t malloc_end = malloc_base + sys->malloc_size - 1;
+#endif
+
+	if (!sys->syscalls)
+		return 1;
+
+	syscalls = sys->syscalls;
+	nb_syscalls = sys->nb_syscalls;
+
+	mem_malloc_init((void *)malloc_base, (void *)malloc_end);
+
+	return 0;
+}
+
+char *__progname;
+
+int app_start(int argc, char **argv)
+{
+	void *sys = _text - 0x2000;
+
+	if (!is_valid_syscall(sys))
+		return EXIT_FAILURE;
+
+	if (syscalls_parse(sys))
+		return EXIT_FAILURE;
+
+	__progname = argv[0];
+
+	return main(argc, argv);
+}
diff --git a/apps/libc/time.c b/apps/libc/time.c
new file mode 100644
index 0000000..6bb57da
--- /dev/null
+++ b/apps/libc/time.c
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2013 Jean-Christophe PLAGNIOL-VILLARD <plagnio@jcrosoft.com>
+ *
+ * Under GPLv2 only
+ *
+ * As a special exception, if other files instantiate templates or use macros
+ * or inline functions from this file, or you compile this file and link it
+ * with other works to produce a work based on this file, this file does not
+ * by itself cause the resulting work to be covered by the GNU General Public
+ * License. However the source code for this file must still be made available
+ * in accordance with section (3) of the GNU General Public License.
+
+ * This exception does not invalidate any other reasons why a work based on
+ * this file might be covered by the GNU General Public License.
+ */
+
+#include <barebox/syscalls.h>
+#include <sys/syscall.h>
+#include <time.h>
+#include <types.h>
+
+#define SECOND	1000 * 1000 * 1000
+
+int nanosleep(const struct timespec *req, struct timespec *rem)
+{
+	int ret;
+
+	if (req->tv_sec) {
+		ret = syscall(SYS_ndelay, req->tv_sec * SECOND);
+		if (ret)
+			return ret;
+	}
+
+	if (!req->tv_nsec)
+		return 0;
+
+	if (req->tv_nsec > 999999999)
+		return -1;
+
+	return syscall(SYS_ndelay, req->tv_nsec);
+}
diff --git a/apps/libc/unistd.c b/apps/libc/unistd.c
new file mode 100644
index 0000000..ea92604
--- /dev/null
+++ b/apps/libc/unistd.c
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2013 Jean-Christophe PLAGNIOL-VILLARD <plagnio@jcrosoft.com>
+ *
+ * Under GPLv2 only
+ *
+ * As a special exception, if other files instantiate templates or use macros
+ * or inline functions from this file, or you compile this file and link it
+ * with other works to produce a work based on this file, this file does not
+ * by itself cause the resulting work to be covered by the GNU General Public
+ * License. However the source code for this file must still be made available
+ * in accordance with section (3) of the GNU General Public License.
+
+ * This exception does not invalidate any other reasons why a work based on
+ * this file might be covered by the GNU General Public License.
+ */
+
+#include <barebox/syscalls.h>
+#include <sys/syscall.h>
+#include <unistd.h>
+#include <string.h>
+#include <malloc.h>
+#include <limits.h>
+
+int read(int fd, void *buf, size_t count)
+{
+	return syscall(SYS_read, fd, buf, count);
+}
+
+ssize_t write(int fd, const void *buf, size_t count)
+{
+	return syscall(SYS_write, fd, buf, count);
+}
+
+int close(int fd)
+{
+	return syscall(SYS_close, fd);
+}
+
+int unlink(const char *pathname)
+{
+	return syscall(SYS_unlink, pathname);
+}
+
+int stat(const char *path, struct stat *buf)
+{
+	return syscall(SYS_stat, path, buf);
+}
+
+int lstat(const char *path, struct stat *buf)
+{
+	return syscall(SYS_lstat, path, buf);
+}
+
+loff_t lseek(int fd, loff_t offset, int whence)
+{
+	return syscall(SYS_lseek, fd, offset, whence);
+}
+
+int symlink(const char *pathname, const char *newpath)
+{
+	return syscall(SYS_symlink, pathname, newpath);
+}
+
+ssize_t readlink(const char *path, char *buf, size_t bufsiz)
+{
+	return syscall(SYS_readlink, path, buf, bufsiz);
+}
+
+int rmdir(const char *path)
+{
+	return syscall(SYS_rmdir, path);
+}
+
+char *get_current_dir_name(void)
+{
+	size_t size = sizeof(char) * PATH_MAX;
+	char *cwd = malloc(size);
+
+	if (!cwd)
+		return NULL;
+
+	if (syscall(SYS_getcwd, cwd, size))
+		goto err;
+
+	return cwd;
+
+err:
+	free(cwd);
+	return NULL;
+}
+
+char *getcwd(char *buf, size_t size)
+{
+	if (syscall(SYS_getcwd, buf, size))
+		return NULL;
+
+	return buf;
+}
+
+int chdir(const char *path)
+{
+	return syscall(SYS_chdir, path);
+}
+
+int usleep(unsigned int usec)
+{
+	return syscall(SYS_ndelay, usec * 1000);
+}
-- 
1.7.10.4


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH 06/20] app: add some utils
  2013-03-06  9:29 ` [PATCH 01/20] Makefile: x_flags prepare for apps support Jean-Christophe PLAGNIOL-VILLARD
                     ` (3 preceding siblings ...)
  2013-03-06  9:29   ` [PATCH 05/20] app: Introduce libc support Jean-Christophe PLAGNIOL-VILLARD
@ 2013-03-06  9:29   ` Jean-Christophe PLAGNIOL-VILLARD
  2013-03-06 21:21     ` Sascha Hauer
  2013-03-06  9:29   ` [PATCH 07/20] app: Introduce example application Jean-Christophe PLAGNIOL-VILLARD
                     ` (13 subsequent siblings)
  18 siblings, 1 reply; 31+ messages in thread
From: Jean-Christophe PLAGNIOL-VILLARD @ 2013-03-06  9:29 UTC (permalink / raw)
  To: barebox

 - getchar_timeout
 - term (try to detect terminal size, position, ansi helper)
 - list

Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
---
 apps/Makefile                |    1 +
 apps/include/utils/ansi.h    |   37 ++++++++++++++
 apps/include/utils/getchar.h |   22 ++++++++
 apps/include/utils/list.h    |  114 ++++++++++++++++++++++++++++++++++++++++++
 apps/include/utils/termcap.h |   23 +++++++++
 apps/utils/Makefile          |    2 +
 apps/utils/getchar.c         |   43 ++++++++++++++++
 apps/utils/termcap.c         |   97 +++++++++++++++++++++++++++++++++++
 8 files changed, 339 insertions(+)
 create mode 100644 apps/include/utils/ansi.h
 create mode 100644 apps/include/utils/getchar.h
 create mode 100644 apps/include/utils/list.h
 create mode 100644 apps/include/utils/termcap.h
 create mode 100644 apps/utils/Makefile
 create mode 100644 apps/utils/getchar.c
 create mode 100644 apps/utils/termcap.c

diff --git a/apps/Makefile b/apps/Makefile
index c5c5c48..28efb0d 100644
--- a/apps/Makefile
+++ b/apps/Makefile
@@ -16,6 +16,7 @@ $(obj)/include/barebox/syscalls.h: $(srctree)/include/apps/syscalls.h
 	$(call cmd,shipped)
 
 obj-y += libc/
+obj-y += utils/
 
 barebox-app-header += $(obj)/include/types.h
 barebox-app-header += $(obj)/include/barebox/syscalls.h
diff --git a/apps/include/utils/ansi.h b/apps/include/utils/ansi.h
new file mode 100644
index 0000000..64f81a8
--- /dev/null
+++ b/apps/include/utils/ansi.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2013 Jean-Christophe PLAGNIOL-VILLARD <plagnio@jcrosoft.com>
+ *
+ * Under GPLv2 only
+ *
+ * As a special exception, if other files instantiate templates or use macros
+ * or inline functions from this file, or you compile this file and link it
+ * with other works to produce a work based on this file, this file does not
+ * by itself cause the resulting work to be covered by the GNU General Public
+ * License. However the source code for this file must still be made available
+ * in accordance with section (3) of the GNU General Public License.
+
+ * This exception does not invalidate any other reasons why a work based on
+ * this file might be covered by the GNU General Public License.
+ */
+
+#ifndef __UTILS_ANSI_H__
+#define __UTILS_ANSI_H__
+
+#define ansi_escape_m(d)		printf("\e[%dm", d);
+#define ansi_save_cusror()		printf("\e[s")
+#define ansi_restore_cusror()		printf("\e[u")
+#define ansi_set_cursor(row, col)	printf("\e[%d;%dH", row, col)
+#define ansi_reverse(on)		ansi_escape_m((on) ? 7 : 27)
+#define ansi_start_reverse()		ansi_escape_m(7)
+#define ansi_end_reverse()		ansi_escape_m(27)
+#define ansi_cursor_enable(on)		printf( "\e[?25%c", ( on ) ? 'h' : 'l' );
+#define ansi_clear()			printf("\e[2J\e[;H");
+#define ansi_bold(on)			ansi_escape_m((on) ? 1 : 22)
+#define ansi_blink(on)			ansi_escape_m((on) ? 5 : 25)
+#define ansi_start_bold()		ansi_escape_m(1)
+#define ansi_end_bold()			ansi_escape_m(22)
+#define ansi_start_altcharset()		ansi_escape_m(14)
+#define ansi_end_altcharset()		ansi_escape_m(10)
+#define ansi_set_color(fg,bg)		printf("\e[%d;%dm", fg, bg)
+
+#endif /* __UTILS_ANSI_H__ */
diff --git a/apps/include/utils/getchar.h b/apps/include/utils/getchar.h
new file mode 100644
index 0000000..074d6b2
--- /dev/null
+++ b/apps/include/utils/getchar.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2013 Jean-Christophe PLAGNIOL-VILLARD <plagnio@jcrosoft.com>
+ *
+ * Under GPLv2 only
+ *
+ * As a special exception, if other files instantiate templates or use macros
+ * or inline functions from this file, or you compile this file and link it
+ * with other works to produce a work based on this file, this file does not
+ * by itself cause the resulting work to be covered by the GNU General Public
+ * License. However the source code for this file must still be made available
+ * in accordance with section (3) of the GNU General Public License.
+
+ * This exception does not invalidate any other reasons why a work based on
+ * this file might be covered by the GNU General Public License.
+ */
+
+#ifndef __UTILS_GETCHAR_H__
+#define __UTILS_GETCHAR_H__
+
+int getchar_timeout(int ms);
+
+#endif /* __UTILS_GETCHAR_H__ */
diff --git a/apps/include/utils/list.h b/apps/include/utils/list.h
new file mode 100644
index 0000000..8a18dae
--- /dev/null
+++ b/apps/include/utils/list.h
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2013 Jean-Christophe PLAGNIOL-VILLARD <plagnio@jcrosoft.com>
+ *
+ * Under GPLv2 only
+ *
+ * As a special exception, if other files instantiate templates or use macros
+ * or inline functions from this file, or you compile this file and link it
+ * with other works to produce a work based on this file, this file does not
+ * by itself cause the resulting work to be covered by the GNU General Public
+ * License. However the source code for this file must still be made available
+ * in accordance with section (3) of the GNU General Public License.
+
+ * This exception does not invalidate any other reasons why a work based on
+ * this file might be covered by the GNU General Public License.
+ */
+
+#ifndef __UTILS_LIST_H__
+#define __UTILS_LIST_H__
+
+struct list_entry {
+	struct list_entry *prev;
+	struct list_entry *next;
+};
+
+struct list {
+	struct list_entry head;
+};
+
+#define LIST_HEAD_INIT(name) \
+	{ \
+		.head = { \
+			.prev = &(name).head, \
+			.next = &(name).head \
+		} \
+	}
+
+#define LIST_HEAD(name) \
+	struct list name = LIST_HEAD_INIT(name)
+
+#define container_of(ptr, type, member) \
+	((type *) (((void *)(ptr)) - ((void *) &(((type *)0)->member))))
+
+#define list_entry(ptr, type, member) \
+	container_of(ptr, type, member)
+
+#define list_first_entry(ptr, type, member) \
+	list_entry((ptr)->head.next, type, member)
+
+#define list_last_entry(head, type, member) \
+	list_entry((head)->head.prev, type, member)
+
+#define list_for_each(pos, list) \
+	for (pos = (list).head.next; pos != &(list).head; pos = pos->next)
+
+#define list_foreach_safe(pos, n, list) \
+	for (pos = (list).head.next, *n = pos->next; \
+		pos != &(list).head; pos = n, n = pos->next)
+
+#define list_for_each_entry(pos, list, member)				\
+	for (pos = list_entry((list)->head.next, typeof(*pos), member);	\
+	      &pos->member != (&(list)->head);				\
+	     pos = list_entry(pos->member.next, typeof(*pos), member))
+
+
+#define list_for_each_entry_safe(pos, n, list, member)			\
+	for (pos = list_entry((list)->head.next, typeof(*pos), member),	\
+		n = list_entry(pos->member.next, typeof(*pos), member);	\
+	     &pos->member != (&(list)->head);				\
+	     pos = n, n = list_entry(n->member.next, typeof(*n), member))
+
+
+static inline bool list_empty(struct list *list)
+{
+	struct list_entry *head = &list->head;
+
+	return head->next == head;
+}
+
+static inline void __list_add(struct list_entry *new,
+			      struct list_entry *prev,
+			      struct list_entry *next)
+{
+	next->prev = new;
+	new->next = next;
+	new->prev = prev;
+	prev->next = new;
+}
+
+static inline void list_add(struct list_entry *new, struct list *list)
+{
+	struct list_entry *head = &list->head;
+
+	__list_add(new, head, head->next);
+}
+
+static inline void list_add_tail(struct list_entry *new, struct list *list)
+{
+	struct list_entry *head = &list->head;
+
+	__list_add(new, head->prev, head);
+}
+
+static inline void list_del(struct list_entry *entry)
+{
+	struct list_entry *prev = entry->prev;
+	struct list_entry *next = entry->next;
+
+	next->prev = prev;
+	prev->next = next;
+	entry->next = NULL;
+	entry->prev = NULL;
+}
+	
+#endif /* __UTILS_LIST_H__ */
diff --git a/apps/include/utils/termcap.h b/apps/include/utils/termcap.h
new file mode 100644
index 0000000..b4305a2
--- /dev/null
+++ b/apps/include/utils/termcap.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2013 Jean-Christophe PLAGNIOL-VILLARD <plagnio@jcrosoft.com>
+ *
+ * Under GPLv2 only
+ *
+ * As a special exception, if other files instantiate templates or use macros
+ * or inline functions from this file, or you compile this file and link it
+ * with other works to produce a work based on this file, this file does not
+ * by itself cause the resulting work to be covered by the GNU General Public
+ * License. However the source code for this file must still be made available
+ * in accordance with section (3) of the GNU General Public License.
+
+ * This exception does not invalidate any other reasons why a work based on
+ * this file might be covered by the GNU General Public License.
+ */
+
+#ifndef __TERMCAP_H__
+#define __TERMCAP_H__
+
+int term_get_size(int *row, int *col);
+int term_get_cursor_pos(int *row, int *col);
+
+#endif /* __TERMCAP_H__ */
diff --git a/apps/utils/Makefile b/apps/utils/Makefile
new file mode 100644
index 0000000..f5b7476
--- /dev/null
+++ b/apps/utils/Makefile
@@ -0,0 +1,2 @@
+app-y += termcap.o
+app-y += getchar.o
diff --git a/apps/utils/getchar.c b/apps/utils/getchar.c
new file mode 100644
index 0000000..e511613
--- /dev/null
+++ b/apps/utils/getchar.c
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2013 Jean-Christophe PLAGNIOL-VILLARD <plagnio@jcrosoft.com>
+ *
+ * Under GPLv2 only
+ *
+ * As a special exception, if other files instantiate templates or use macros
+ * or inline functions from this file, or you compile this file and link it
+ * with other works to produce a work based on this file, this file does not
+ * by itself cause the resulting work to be covered by the GNU General Public
+ * License. However the source code for this file must still be made available
+ * in accordance with section (3) of the GNU General Public License.
+
+ * This exception does not invalidate any other reasons why a work based on
+ * this file might be covered by the GNU General Public License.
+ */
+
+#include <types.h>
+#include <stdio.h>
+#include <time.h>
+#include <ctype.h>
+#include <errno.h>
+#include <utils/getchar.h>
+
+int getchar_timeout(int ms)
+{
+	struct timespec req, rem;
+	int ret;
+
+	req.tv_nsec = 10;
+	req.tv_sec = 0;
+	ms *= 100;
+
+	while (!tstc()) {
+		ret = nanosleep(&req, &rem);
+		if (ret)
+			return ret;
+
+		if (!ms--)
+			return -ETIMEDOUT;
+	}
+
+	return getchar();
+}
diff --git a/apps/utils/termcap.c b/apps/utils/termcap.c
new file mode 100644
index 0000000..dd24f66
--- /dev/null
+++ b/apps/utils/termcap.c
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2013 Jean-Christophe PLAGNIOL-VILLARD <plagnio@jcrosoft.com>
+ *
+ * Under GPLv2 only
+ *
+ * As a special exception, if other files instantiate templates or use macros
+ * or inline functions from this file, or you compile this file and link it
+ * with other works to produce a work based on this file, this file does not
+ * by itself cause the resulting work to be covered by the GNU General Public
+ * License. However the source code for this file must still be made available
+ * in accordance with section (3) of the GNU General Public License.
+
+ * This exception does not invalidate any other reasons why a work based on
+ * this file might be covered by the GNU General Public License.
+ */
+
+#include <types.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <errno.h>
+#include <utils/getchar.h>
+#include <utils/termcap.h>
+#include <utils/ansi.h>
+
+#define TIMEOUT_GETC	10
+#define MAX_COL_ROW	9999
+
+static int getnum(char end)
+{
+	int i = 0;
+	int c;
+
+	while ((c = getchar_timeout(TIMEOUT_GETC)) > -1) {
+		if (c == end)
+			return i;
+
+		if (c < 0)
+			return c;
+
+		if (!isdigit(c))
+			return -1;
+
+		i *= 10;
+		i += c - '0';
+	}
+
+	return -1;
+}
+
+int term_get_cursor_pos(int *row, int *col)
+{
+	int c;
+	int __row;
+
+	/* request cursos position */
+	printf("\e[6n");
+
+	/* reply \e[%d;%dR */
+	c = getchar_timeout(TIMEOUT_GETC);
+	if (c != '\e')
+		return -1;
+
+	c = getchar_timeout(TIMEOUT_GETC);
+	if (c != '[')
+		return -1;
+
+	__row = getnum(';');
+	if (__row < 0)
+		return __row;
+
+	c = getnum('R');
+	if (c < 0)
+		return c;
+
+	*row = __row;
+	*col = c;
+
+	return 0;
+}
+
+int term_get_size(int *row, int *col)
+{
+	ansi_save_cusror();
+
+	/* reset scroll */
+	printf("\e[r");
+
+	/* move the cursos to the bottom-right */
+	ansi_set_cursor(MAX_COL_ROW, MAX_COL_ROW);
+
+	term_get_cursor_pos(row, col);
+
+	/* restore cursor */
+	ansi_restore_cusror();
+
+	return 0;
+}
-- 
1.7.10.4


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH 07/20] app: Introduce example application
  2013-03-06  9:29 ` [PATCH 01/20] Makefile: x_flags prepare for apps support Jean-Christophe PLAGNIOL-VILLARD
                     ` (4 preceding siblings ...)
  2013-03-06  9:29   ` [PATCH 06/20] app: add some utils Jean-Christophe PLAGNIOL-VILLARD
@ 2013-03-06  9:29   ` Jean-Christophe PLAGNIOL-VILLARD
  2013-03-06  9:29   ` [PATCH 08/20] filetype: add barebox arm application Jean-Christophe PLAGNIOL-VILLARD
                     ` (12 subsequent siblings)
  18 siblings, 0 replies; 31+ messages in thread
From: Jean-Christophe PLAGNIOL-VILLARD @ 2013-03-06  9:29 UTC (permalink / raw)
  To: barebox

Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
---
 apps/Kconfig           |    3 +
 apps/Makefile          |    5 ++
 apps/example/Makefile  |   14 +++
 apps/example/example.h |    7 ++
 apps/example/list.c    |   98 ++++++++++++++++++++
 apps/example/ls.c      |  127 ++++++++++++++++++++++++++
 apps/example/main.c    |  231 ++++++++++++++++++++++++++++++++++++++++++++++++
 apps/example/setjmp.c  |   24 +++++
 8 files changed, 509 insertions(+)
 create mode 100644 apps/example/Makefile
 create mode 100644 apps/example/example.h
 create mode 100644 apps/example/list.c
 create mode 100644 apps/example/ls.c
 create mode 100644 apps/example/main.c
 create mode 100644 apps/example/setjmp.c

diff --git a/apps/Kconfig b/apps/Kconfig
index 4805c50..324e14d 100644
--- a/apps/Kconfig
+++ b/apps/Kconfig
@@ -37,4 +37,7 @@ config APP_FILE_MAX
 
 endmenu
 
+config APP_EXAMPLE
+	bool "example"
+
 endif
diff --git a/apps/Makefile b/apps/Makefile
index 28efb0d..7f609e7 100644
--- a/apps/Makefile
+++ b/apps/Makefile
@@ -5,6 +5,8 @@ export APP_CPPFLAGS
 
 apps-$(CONFIG_APP_EXAMPLE) += example
 
+apps-$(CONFIG_APP_EXAMPLE) += example
+
 $(obj)/application: $(apps-lds) $(apps-y)
 
 APP_CPPFLAGS		+= -fdata-sections -ffunction-sections
@@ -20,3 +22,6 @@ obj-y += utils/
 
 barebox-app-header += $(obj)/include/types.h
 barebox-app-header += $(obj)/include/barebox/syscalls.h
+
+$(apps-y): $(barebox-app-header) $(barebox-app-common)
+	$(Q)$(MAKE) $(build)=apps/$@ apps/$@/$@.app
diff --git a/apps/example/Makefile b/apps/example/Makefile
new file mode 100644
index 0000000..22f8d68
--- /dev/null
+++ b/apps/example/Makefile
@@ -0,0 +1,14 @@
+targets := example.map
+
+# Make sure files are removed during clean
+extra-y       += example.map
+
+app-y += main.o
+app-y += ls.o
+app-y += list.o
+app-y += setjmp.o
+app-final-y = example
+
+OBJCOPYFLAGS_example.app = -O binary
+LDFLAGS_apps	:= -Map $(obj)/example.map
+LDFLAGS_apps	+= -static --gc-sections
diff --git a/apps/example/example.h b/apps/example/example.h
new file mode 100644
index 0000000..34675b4
--- /dev/null
+++ b/apps/example/example.h
@@ -0,0 +1,7 @@
+
+#define LS_RECURSIVE	1
+#define LS_SHOWARG	2
+#define LS_COLUMN	4
+int ls(const char *path, ulong flags);
+void test_list(void);
+void test_setjmp(void);
diff --git a/apps/example/list.c b/apps/example/list.c
new file mode 100644
index 0000000..fd5662d
--- /dev/null
+++ b/apps/example/list.c
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2013 Jean-Christophe PLAGNIOL-VILLARD <plagnio@jcrosoft.com>
+ *
+ * Under GPLv2 only
+*/
+
+#include <stdio.h>
+#include <string.h>
+#include <appinfo.h>
+#include <utils/list.h>
+
+#define ARRAY_SIZE(arr)                (sizeof(arr) / sizeof((arr)[0]))
+
+static LIST_HEAD(test);
+
+struct data {
+	char *name;
+	struct list_entry list;
+};
+
+struct data data[] = {
+	[0] = { .name = "data0", },
+	[1] = { .name = "data1", },
+	[2] = { .name = "data2", },
+	[3] = { .name = "data3", },
+};
+
+static void dump_list(void)
+{
+	struct list_entry *pos;
+	struct data *d;
+	int i;
+
+	i = 0;
+	list_for_each(pos, test) {
+		printf("data[%d].list = %p\n", i, pos);
+		i++;
+	}
+
+	i = 0;
+	list_for_each_entry(d, &test, list) {
+		printf("data[%d].name = %s\n", i, d->name);
+		printf("data[%d].list = %p\n", i, &d->list);
+		i++;
+	}
+}
+
+static void empty_list(void)
+{
+	struct data *d, *tmp;
+	int i;
+
+	i = 0;
+	list_for_each_entry_safe(d, tmp, &test, list) {
+		printf("data[%d].name = %s\n", i, d->name);
+		printf("data[%d].list = %p\n", i, &d->list);
+		list_del(&d->list);
+		i++;
+	}
+}
+
+void test_list(void)
+{
+	int i;
+
+	puts("------ list test ------\n");
+
+	puts("fill list\n");
+
+	for (i = 0; i < ARRAY_SIZE(data); i++) {
+		printf("data[%d].name = %s\n", i, data[i].name);
+		printf("data[%d].list = %p\n", i, &data[i].list);
+		list_add(&data[i].list, &test);
+	}
+
+	puts("dump list\n");
+	dump_list();
+	puts("remove entry 2\n");
+	list_del(&data[2].list);
+	puts("dump list\n");
+	dump_list();
+	puts("empty list\n");
+	empty_list();
+	puts("dump list\n");
+	dump_list();
+	printf("list is %s\n", list_empty(&test) ? "empty" : "filled");
+
+	puts("fill list tail\n");
+	for (i = 0; i < ARRAY_SIZE(data); i++) {
+		printf("data[%d].name = %s\n", i, data[i].name);
+		printf("data[%d].list = %p\n", i, &data[i].list);
+		list_add_tail(&data[i].list, &test);
+	}
+	puts("dump list\n");
+	dump_list();
+
+	puts("------ end ------\n\n");
+}
diff --git a/apps/example/ls.c b/apps/example/ls.c
new file mode 100644
index 0000000..bad0ccb
--- /dev/null
+++ b/apps/example/ls.c
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2007 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ * Copyright (C) 2013 Jean-Christophe PLAGNIOL-VILLARD <plagnio@jcrosoft.com>
+ *
+ * Under GPLv2 only
+ */
+
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <errno.h>
+#include <limits.h>
+#include <malloc.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "example.h"
+
+static char *mkmodestr(unsigned long mode, char *str)
+{
+	static const char *l = "xwr";
+	int mask = 1, i;
+	char c;
+
+	switch (mode & S_IFMT) {
+		case S_IFDIR:    str[0] = 'd'; break;
+		case S_IFBLK:    str[0] = 'b'; break;
+		case S_IFCHR:    str[0] = 'c'; break;
+		case S_IFIFO:    str[0] = 'f'; break;
+		case S_IFLNK:    str[0] = 'l'; break;
+		case S_IFSOCK:   str[0] = 's'; break;
+		case S_IFREG:    str[0] = '-'; break;
+		default:         str[0] = '?';
+	}
+
+	for(i = 0; i < 9; i++) {
+		c = l[i%3];
+		str[9-i] = (mode & mask)?c:'-';
+		mask = mask<<1;
+	}
+
+	if(mode & S_ISUID) str[3] = (mode & S_IXUSR)?'s':'S';
+	if(mode & S_ISGID) str[6] = (mode & S_IXGRP)?'s':'S';
+	if(mode & S_ISVTX) str[9] = (mode & S_IXOTH)?'t':'T';
+	str[10] = '\0';
+	return str;
+}
+
+static void ls_one(const char *path, const char* fullname, struct stat *s)
+{
+	char modestr[11];
+	unsigned int namelen = strlen(path);
+
+	mkmodestr(s->st_mode, modestr);
+	printf("%s %10llu %*.*s", modestr, s->st_size, namelen, namelen, path);
+
+	if (S_ISLNK(s->st_mode)) {
+		char realname[PATH_MAX];
+
+		memset(realname, 0, PATH_MAX);
+
+		if (readlink(fullname, realname, PATH_MAX - 1) >= 0)
+			printf(" -> %s", realname);
+	}
+
+	puts("\n");
+}
+
+int ls(const char *path, ulong flags)
+{
+	DIR *dir;
+	struct dirent *d;
+	char tmp[PATH_MAX];
+	struct stat s;
+
+	if (lstat(path, &s))
+		return -1;
+
+	if (flags & LS_SHOWARG && s.st_mode & S_IFDIR)
+		printf("%s:\n", path);
+
+	if (!(s.st_mode & S_IFDIR)) {
+		ls_one(path, path, &s);
+		return 0;
+	}
+
+	dir = opendir(path);
+	if (!dir)
+		return -1;
+
+	while ((d = readdir(dir))) {
+		sprintf(tmp, "%s/%s", path, d->d_name);
+		if (!strlen(d->d_name))
+			break;
+		if (lstat(tmp, &s))
+			goto out;
+		ls_one(d->d_name, tmp, &s);
+	}
+
+	closedir(dir);
+
+	if (!(flags & LS_RECURSIVE))
+		return 0;
+
+	dir = opendir(path);
+	if (!dir) 
+		return -ENOENT;
+
+	while ((d = readdir(dir))) {
+
+		if (!strcmp(d->d_name, "."))
+			continue;
+		if (!strcmp(d->d_name, ".."))
+			continue;
+		sprintf(tmp, "%s/%s", path, d->d_name);
+
+		if (lstat(tmp, &s))
+			goto out;
+		if (s.st_mode & S_IFDIR)
+			ls(tmp, flags);
+	}
+out:
+	closedir(dir);
+
+	return 0;
+}
diff --git a/apps/example/main.c b/apps/example/main.c
new file mode 100644
index 0000000..12fb7f0
--- /dev/null
+++ b/apps/example/main.c
@@ -0,0 +1,231 @@
+/*
+ * Copyright (C) 2013 Jean-Christophe PLAGNIOL-VILLARD <plagnio@jcrosoft.com>
+ *
+ * Under GPLv2 only
+*/
+
+#include <stdio.h>
+#include <malloc.h>
+#include <appinfo.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sections.h>
+#include <sys/stat.h>
+
+#include "example.h"
+
+# define PUTHEX_LL(value)  ({ unsigned long v = (unsigned long) (value); \
+			     int i; unsigned char ch; \
+			     for (i = 8; i--; ) {\
+			     ch = ((v >> (i*4)) & 0xf);\
+			     ch += (ch >= 10) ? 'a' - 10 : '0';\
+			     putchar(ch); }})
+static void test_ls(void)
+{
+	puts(
+		"------ test 1 ------ \n"
+		"coverage:\n"
+		" - opendir/readdir/closedir\n"
+		" - lstat\n"
+		" - readlink\n"
+		"------ start ------ \n");
+
+	puts("ls -l /env/config\n");
+	ls("/env/config", 0);
+	puts("ls -l /dev\n");
+	ls("/dev", 0);
+	puts("ls -l /env\n");
+	ls("/env", 0);
+	puts("------ end ------\n\n");
+}
+
+static void print_ok_failed(int ret)
+{
+	if (ret)
+		printf("failed (%d)\n", ret);
+	else
+		puts(" => OK\n");
+}
+
+static void test_mkdir(void)
+{
+	int fd;
+	int ret;
+	char *test = "/test";
+	char *test_tmp = "/test/tmp";
+	char *readme_txt = "/test/readme.txt";
+	char *readme = "/test/readme";
+	char *txt = "test barebox app\n";
+
+	puts(
+		"------ test 2 ------ \n"
+		"coverage:\n"
+		" - mkdir/rmdir\n"
+		" - open/write\n"
+		" - symlink/unlink\n"
+		"------ start ------ \n");
+
+	printf("mkdir %s ", test);
+	ret = mkdir(test, 0666);
+	print_ok_failed(ret);
+	if (ret)
+		return;
+
+	printf("create %s ", readme_txt);
+	fd = open(readme_txt, O_CREAT | O_WRONLY);
+	if (fd >= 0) {
+		puts(" => OK\n");
+		ret = write(fd, txt, strlen(txt) + 1);
+		if (!ret)
+			printf("fprintf on fd=%d failer (%d)\n", fd, ret);
+		close(fd);
+	} else {
+		printf("failed (%d)\n", fd);
+	}
+
+	printf("ln -s %s %s ", readme_txt, readme);
+	ret = symlink(readme_txt, readme);
+	print_ok_failed(ret);
+
+	printf("mkdir %s ", test_tmp);
+	ret = mkdir(test_tmp, 0666);
+	print_ok_failed(ret);
+
+	printf("ls -l %s\n", test);
+	ls(test, 0);
+
+	if (!ret) {
+		printf("rmdir %s ", test_tmp);
+		ret = rmdir(test_tmp);
+		print_ok_failed(ret);
+	}
+
+	printf("unlink %s ", readme);
+	ret = unlink(readme);
+	print_ok_failed(ret);
+
+	printf("ls -l %s\n", test);
+	ls(test, 0);
+
+	puts("------ end ------\n\n");
+}
+
+static void test_printf(int argc, char **argv)
+{
+	int i;
+	char *test;
+
+	puts("hello world\n");
+	test = malloc(10);
+	puts("mallox of 10 => 0x");
+	PUTHEX_LL(test);
+	puts("\n");
+
+	puts("------ printf test ------\n");
+
+	for (i = 0; i < argc; i++)
+		printf("argv[%d] = %s\n", i, argv[i]);
+
+	printf("mallox of %d => %p\n", 10, test);
+	puts("------ end ------\n\n");
+}
+
+static void test_all(int argc, char **argv)
+{
+	test_printf(argc, argv);
+	test_ls();
+	test_mkdir();
+	test_list();
+	test_setjmp();
+}
+
+void usage(char *name)
+{
+	printf("%s: [-VplmLh]\n"
+	"-V             dump app info\n"
+	"-p             run printf test\n"
+	"-l             run ls test\n"
+	"-m             run mkdir test\n"
+	"-L             run list test\n"
+	"-j             run setjmp test\n"
+	"-h             print help\n", name);
+}
+
+int main(int argc, char** argv)
+{
+	int i;
+	int opt;
+	bool do_test_printf = false;
+	bool do_test_ls = false;
+	bool do_test_mkdir = false;
+	bool do_test_list = false;
+	bool do_test_setjmp = false;
+	bool do_test_all = true;
+
+	for (i = 0; i < argc; i++) {
+		puts("argv[0x");
+		PUTHEX_LL(i);
+		puts("] = ");
+		puts(argv[i]);
+		puts("\n");
+	}
+
+	while ((opt = getopt(argc, argv, "VplmLhj")) > 0) {
+		switch (opt) {
+		case 'V':
+			print_appinfo();
+			break;
+		case 'p':
+			do_test_all = false;
+			do_test_printf = true;
+			break;
+		case 'l':
+			do_test_all = false;
+			do_test_ls = true;
+			break;
+		case 'm':
+			do_test_all = false;
+			do_test_mkdir = true;
+			break;
+		case 'L':
+			do_test_all = false;
+			do_test_list = true;
+			break;
+		case 'j':
+			do_test_all = false;
+			do_test_setjmp = true;
+			break;
+		case 'h':
+			usage(argv[0]);
+			return 0;
+			break;
+		default:
+			break;
+		}
+	}
+
+	puts("------ start ------\n\n");
+	if (do_test_all) {
+		test_all(argc, argv);
+		return 0;
+	}
+
+	if (do_test_printf)
+		test_printf(argc, argv);
+	if (do_test_ls)
+		test_ls();
+	if (do_test_ls)
+		test_mkdir();
+	if (do_test_list)
+		test_list();
+	if (do_test_setjmp)
+		test_setjmp();
+	puts("------ end ------\n\n");
+
+	return 0;
+}
+
+APP_LICENSE("GPL");
+APP_DESCRIPTION("barebox Application example");
+APP_AUTHOR("Jean-Chrristophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>");
diff --git a/apps/example/setjmp.c b/apps/example/setjmp.c
new file mode 100644
index 0000000..4dee83c
--- /dev/null
+++ b/apps/example/setjmp.c
@@ -0,0 +1,24 @@
+#include <stdio.h>
+#include <setjmp.h>
+
+static jmp_buf buf;
+
+void second(void) {
+	printf("second\n");
+	longjmp(buf, 1);
+}
+
+void first(void) {
+	second();
+	printf("first not reach\n");
+}
+
+void test_setjmp(void)
+{
+	puts("------ setjmp/longjmp test ------\n");
+	if (!setjmp(buf))
+		first();
+	else
+		printf("main\n");
+	puts("------ end ------\n\n");
+}
-- 
1.7.10.4


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH 08/20] filetype: add barebox arm application
  2013-03-06  9:29 ` [PATCH 01/20] Makefile: x_flags prepare for apps support Jean-Christophe PLAGNIOL-VILLARD
                     ` (5 preceding siblings ...)
  2013-03-06  9:29   ` [PATCH 07/20] app: Introduce example application Jean-Christophe PLAGNIOL-VILLARD
@ 2013-03-06  9:29   ` Jean-Christophe PLAGNIOL-VILLARD
  2013-03-06  9:29   ` [PATCH 09/20] arm: add application support Jean-Christophe PLAGNIOL-VILLARD
                     ` (11 subsequent siblings)
  18 siblings, 0 replies; 31+ messages in thread
From: Jean-Christophe PLAGNIOL-VILLARD @ 2013-03-06  9:29 UTC (permalink / raw)
  To: barebox

Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
---
 common/filetype.c  |   35 +++++++++++++++++++++++++++++++++++
 include/filetype.h |    2 ++
 2 files changed, 37 insertions(+)

diff --git a/common/filetype.c b/common/filetype.c
index 8652f1d..16b217b 100644
--- a/common/filetype.c
+++ b/common/filetype.c
@@ -23,6 +23,7 @@
 #include <fs.h>
 #include <malloc.h>
 #include <errno.h>
+#include <linux/license.h>
 
 struct filetype_str {
 	const char *name;	/* human readable filetype */
@@ -49,6 +50,8 @@ static const struct filetype_str filetype_str[] = {
 	[filetype_png] = { "PNG image", "png" },
 	[filetype_ext] = { "ext filesystem", "ext" },
 	[filetype_gpt] = { "GUID Partition Table", "gpt" },
+	[filetype_arm_application] = { "arm barebox application", "arm-barebox-app"},
+	[filetype_arm_gpl_application] = { "arm barebox GPL compatible application", "arm-barebox-gpl-app"},
 };
 
 const char *file_type_to_string(enum filetype f)
@@ -151,6 +154,35 @@ enum filetype is_fat_or_mbr(const unsigned char *sector, unsigned long *bootsec)
 	return filetype_mbr;
 }
 
+bool is_barebox_app_gpl_compatible(const uint8_t *buf8, size_t bufsize)
+{
+	int i;
+
+	if (bufsize < 12)
+		return false;
+
+	bufsize -= 12;
+
+	for (i = 0; i < bufsize; i++, buf8++) {
+		if (!strncmp("license=", buf8, 8) &&
+		    license_is_gpl_compatible(buf8 + 8))
+				return true;
+	}
+
+	return false;
+}
+
+enum filetype is_barebox_arm_app(const uint8_t *buf8, size_t bufsize)
+{
+	if (strcmp(buf8 + 0x20, "barebox_arm_app"))
+		return filetype_unknown;
+	/* license=GPL */
+	if (is_barebox_app_gpl_compatible(buf8 + 0x80, bufsize))
+		return filetype_arm_gpl_application;
+
+	return filetype_arm_application;
+}
+
 enum filetype file_detect_type(const void *_buf, size_t bufsize)
 {
 	const u32 *buf = _buf;
@@ -201,6 +233,9 @@ enum filetype file_detect_type(const void *_buf, size_t bufsize)
 	if (buf[9] == 0x016f2818 || buf[9] == 0x18286f01)
 		return filetype_arm_zimage;
 
+	type = is_barebox_arm_app(buf8, bufsize);
+	if (type != filetype_unknown)
+		return type;
 	if (bufsize < 512)
 		return filetype_unknown;
 
diff --git a/include/filetype.h b/include/filetype.h
index 78ca5d2..09cdc99 100644
--- a/include/filetype.h
+++ b/include/filetype.h
@@ -24,6 +24,8 @@ enum filetype {
 	filetype_png,
 	filetype_ext,
 	filetype_gpt,
+	filetype_arm_application,
+	filetype_arm_gpl_application,
 	filetype_max,
 };
 
-- 
1.7.10.4


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH 09/20] arm: add application support
  2013-03-06  9:29 ` [PATCH 01/20] Makefile: x_flags prepare for apps support Jean-Christophe PLAGNIOL-VILLARD
                     ` (6 preceding siblings ...)
  2013-03-06  9:29   ` [PATCH 08/20] filetype: add barebox arm application Jean-Christophe PLAGNIOL-VILLARD
@ 2013-03-06  9:29   ` Jean-Christophe PLAGNIOL-VILLARD
  2013-03-06  9:59     ` Alexander Shiyan
  2013-03-06  9:29   ` [PATCH 10/20] app: printf: use HelenOS verison with wide char support Jean-Christophe PLAGNIOL-VILLARD
                     ` (10 subsequent siblings)
  18 siblings, 1 reply; 31+ messages in thread
From: Jean-Christophe PLAGNIOL-VILLARD @ 2013-03-06  9:29 UTC (permalink / raw)
  To: barebox

Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
---
 arch/arm/Kconfig                       |    1 +
 arch/arm/Makefile                      |    6 +-
 arch/arm/apps/Kconfig                  |   11 ++++
 arch/arm/apps/Makefile                 |    6 ++
 arch/arm/apps/apps.lds.S               |   64 ++++++++++++++++++
 arch/arm/apps/binfmt.c                 |  111 ++++++++++++++++++++++++++++++++
 arch/arm/apps/head.S                   |   59 +++++++++++++++++
 arch/arm/apps/include/arch/asm/macro.h |   46 +++++++++++++
 arch/arm/apps/include/arch/setjmp.h    |   26 ++++++++
 arch/arm/apps/raise.c                  |   27 ++++++++
 arch/arm/apps/setjmp.S                 |   60 +++++++++++++++++
 arch/arm/apps/start.c                  |   35 ++++++++++
 12 files changed, 451 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm/apps/Kconfig
 create mode 100644 arch/arm/apps/Makefile
 create mode 100644 arch/arm/apps/apps.lds.S
 create mode 100644 arch/arm/apps/binfmt.c
 create mode 100644 arch/arm/apps/head.S
 create mode 100644 arch/arm/apps/include/arch/asm/macro.h
 create mode 100644 arch/arm/apps/include/arch/setjmp.h
 create mode 100644 arch/arm/apps/raise.c
 create mode 100644 arch/arm/apps/setjmp.S
 create mode 100644 arch/arm/apps/start.c

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index f25dcf7..f30859b 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -2,6 +2,7 @@ config ARM
 	bool
 	select HAS_KALLSYMS
 	select HAS_MODULES
+	select HAS_APPLICATIONS
 	select HAVE_CONFIGURABLE_TEXT_BASE
 	select HAVE_PBL_IMAGE
 	select HAVE_IMAGE_COMPRESSION
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 100a3c4..731d92a 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -275,9 +275,13 @@ else
 MACH :=
 endif
 
+APP_LDFLAGS += -L $(shell dirname `$(CC) $(CPPFLAGS) -print-libgcc-file-name`) -lgcc
+
 common-y += $(BOARD) $(MACH)
 common-y += arch/arm/lib/ arch/arm/cpu/
+common-$(CONFIG_APPLICATIONS) += arch/arm/apps/
 
 lds-y	:= arch/arm/lib/barebox.lds
+apps-lds-y	:= arch/arm/apps/apps.lds
 
-CLEAN_FILES += include/generated/mach-types.h arch/arm/lib/barebox.lds barebox-flash-image
+CLEAN_FILES += include/generated/mach-types.h arch/arm/lib/barebox.lds arch/arm/apps/apps.lds barebox-flash-image
diff --git a/arch/arm/apps/Kconfig b/arch/arm/apps/Kconfig
new file mode 100644
index 0000000..8fcb79d
--- /dev/null
+++ b/arch/arm/apps/Kconfig
@@ -0,0 +1,11 @@
+
+config APP_TEXT_BASE_OFFSET
+	hex
+	default 0x800000
+	prompt "application text base offset"
+	help
+	  APP_TEXT_BASE = TEXT_BASE - APP_TEXT_BASE_OFFSET
+	  all the application will be link at this address
+	  the syscall table region of 0x2000 will be add
+	  APP_TEXT_BASE - 0x2000 and then the malloc region at
+	  APP_TEXT_BASE - 0x2000 - APP_MALLOC_SIZE
diff --git a/arch/arm/apps/Makefile b/arch/arm/apps/Makefile
new file mode 100644
index 0000000..c7e9a80
--- /dev/null
+++ b/arch/arm/apps/Makefile
@@ -0,0 +1,6 @@
+obj-y += binfmt.o
+app-y += head.o
+app-y += start.o
+app-y += raise.o
+app-y += setjmp.o
+extry-y += apps.lds
diff --git a/arch/arm/apps/apps.lds.S b/arch/arm/apps/apps.lds.S
new file mode 100644
index 0000000..b6e4ab9
--- /dev/null
+++ b/arch/arm/apps/apps.lds.S
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2013 Jean-Christophe PLAGNIOL-VILLARD <plagnio@jcrosoft.com>
+ *
+ * Under GPLv2 only
+ *
+ * As a special exception, if other files instantiate templates or use macros
+ * or inline functions from this file, or you compile this file and link it
+ * with other works to produce a work based on this file, this file does not
+ * by itself cause the resulting work to be covered by the GNU General Public
+ * License. However the source code for this file must still be made available
+ * in accordance with section (3) of the GNU General Public License.
+
+ * This exception does not invalidate any other reasons why a work based on
+ * this file might be covered by the GNU General Public License.
+ */
+
+#include <sizes.h>
+#include <asm-generic/barebox.lds.h>
+#include <asm-generic/memory_layout.h>
+
+#define HEAD_BASE (TEXT_BASE - CONFIG_APP_TEXT_BASE_OFFSET)
+
+OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
+OUTPUT_ARCH(arm)
+ENTRY(_start)
+SECTIONS
+{
+	. = HEAD_BASE;
+
+	. = ALIGN(4);
+	.text      :
+	{
+		_stext = .;
+		_text = .;
+		*(.text_head_entry*)
+		. = 0x80;
+		KEEP(*(.appinfo.start))
+		__appinfo_start = .;
+		KEEP(*(.appinfo))
+		__appinfo_end = .;
+		KEEP(*(.appinfo.end))
+		*(.text*)
+	}
+
+	/* Discard unwind if enable in barebox */
+	/DISCARD/ : { *(.ARM.ex*) }
+
+	. = ALIGN(4);
+	.rodata : { *(.rodata*) }
+
+	_etext = .;			/* End of text and rodata section */
+
+	. = ALIGN(4);
+	.data : { *(.data*) }
+
+	. = ALIGN(4);
+	__bss_start = .;
+	.bss : { *(.bss*) }
+	__bss_stop = .;
+	_end = .;
+
+	_barebox_app_image_size = __bss_start - HEAD_BASE;
+	_barebox_app_info_size = __appinfo_end - __appinfo_start;
+}
diff --git a/arch/arm/apps/binfmt.c b/arch/arm/apps/binfmt.c
new file mode 100644
index 0000000..f6bc450
--- /dev/null
+++ b/arch/arm/apps/binfmt.c
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2013 Jean-Christophe PLAGNIOL-VILLARD <plagnio@jcrosoft.com>
+ *
+ * Under GPLv2 only
+ */
+
+#include <common.h>
+#include <binfmt.h>
+#include <init.h>
+#include <fs.h>
+#include <sizes.h>
+#include <memory.h>
+#include <malloc.h>
+#include <apps/syscall_init.h>
+
+static int arm_application(char *file, int argc, char **argv, bool is_gpl)
+{
+	struct syscall_trace st;
+	u32 *buf32;
+	u32 load_addr, size;
+	int (*jump)(int argc, char** argv);
+	void *barebox_app;
+	int ret = 0;
+	struct resource *app_res, *syscall_res, *malloc_res;
+
+	barebox_app = read_file(file, NULL);
+	if (!barebox_app)
+		return -EINVAL;
+
+	buf32 = barebox_app + 0x30;
+	load_addr = buf32[0];
+	size = buf32[1];
+
+	app_res = request_sdram_region("application", load_addr, size);
+	if (!app_res) {
+		perror("application: request_sdram_region");
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	load_addr -= 0x2000;
+
+	syscall_res = request_sdram_region("bsyscall", load_addr, 0x2000);
+	if (!syscall_res) {
+		perror("application: bsyscall request_sdram_region");
+		ret = -ENOMEM;
+		goto err_app_res;
+	}
+
+	load_addr -= CONFIG_APP_MALLOC_SIZE;
+
+	malloc_res = request_sdram_region("application_malloc", load_addr, CONFIG_APP_MALLOC_SIZE);
+	if (!malloc_res) {
+		perror("application: bsyscall request_sdram_region");
+		ret = -ENOMEM;
+		goto err_malloc_res;
+	}
+
+	memset((void*)malloc_res->start, 0, resource_size(malloc_res));
+	memcpy((void*)app_res->start, barebox_app, size);
+
+	st.dest = (void*)syscall_res->start;
+	st.malloc_base = malloc_res->start;
+	st.malloc_size = resource_size(malloc_res);
+	syscalls_init(&st);
+
+	jump = (void*)app_res->start;
+	ret = jump(argc, argv);
+
+	syscalls_exit(&st);
+
+	release_sdram_region(malloc_res);
+err_malloc_res:
+	release_sdram_region(syscall_res);
+err_app_res:
+	release_sdram_region(app_res);
+err:
+	free(barebox_app);
+	return ret;
+}
+
+static int arm_gpl_application(struct binfmt_hook *b, char *file, int argc, char **argv)
+{
+	return arm_application(file, argc, argv, true);
+}
+
+static struct binfmt_hook binfmt_barebox_gpl_app_hook = {
+	.type = filetype_arm_gpl_application,
+	.hook = arm_gpl_application,
+};
+
+static int arm_non_gpl_application(struct binfmt_hook *b, char *file, int argc, char **argv)
+{
+	/* You are NOT allow to remove this warning */
+	pr_warn("non gpl compatible application\n");
+	return arm_application(file, argc, argv, false);
+}
+
+static struct binfmt_hook binfmt_barebox_app_hook = {
+	.type = filetype_arm_application,
+	.hook = arm_non_gpl_application,
+};
+
+static int arm_app_register_image_handler(void)
+{
+	binfmt_register(&binfmt_barebox_app_hook);
+	binfmt_register(&binfmt_barebox_gpl_app_hook);
+
+	return 0;
+}
+late_initcall(arm_app_register_image_handler);
diff --git a/arch/arm/apps/head.S b/arch/arm/apps/head.S
new file mode 100644
index 0000000..9cc714c
--- /dev/null
+++ b/arch/arm/apps/head.S
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2013 Jean-Christophe PLAGNIOL-VILLARD <plagnio@jcrosoft.com>
+ *
+ * Under GPLv2 only
+ *
+ * As a special exception, if other files instantiate templates or use macros
+ * or inline functions from this file, or you compile this file and link it
+ * with other works to produce a work based on this file, this file does not
+ * by itself cause the resulting work to be covered by the GNU General Public
+ * License. However the source code for this file must still be made available
+ * in accordance with section (3) of the GNU General Public License.
+
+ * This exception does not invalidate any other reasons why a work based on
+ * this file might be covered by the GNU General Public License.
+ */
+
+	.section ".text_head_entry.start"
+	.globl _start
+_start:
+	/* save register */
+	stmfd	sp!, {r2, r3, r4, r5, r6, r7, r8, r9, sl, lr}
+	/* save barebox stack */
+	mov	r2, sp
+	/* setup new stack */
+	ldr	sp, =_text
+	sub	sp, #CONFIG_STACK_SIZE
+	b _next
+	.org 0x20
+	.asciz "barebox_arm_app"
+	.word _text				/* text base. If copied there,
+						* barebox can skip relocation
+						*/
+	.word _barebox_app_image_size		/* image size to copy */
+
+_next:
+	stmfd	sp!, {r0-r2}
+1:	ldr	r0, =__bss_start
+	mov	r1, #0
+	ldr	r2, =__bss_stop
+	sub	r2, r2, r0
+	bl	memset			/* clear bss */
+	ldmfd	sp!, {r0-r2}
+
+	b arm_app_start
+
+	.section ".appinfo.start"
+	.asciz "#appinf"
+	.word _barebox_app_info_size
+
+	.section ".appinfo.end"
+	.asciz "appinf#"
+
+	.text
+	.globl barebox_return
+barebox_return:
+	/* restore barebox the stack */
+	mov	sp, r1
+	/* restore register */
+	ldmfd	sp!, {r2, r3, r4, r5, r6, r7, r8, r9, sl, pc}
diff --git a/arch/arm/apps/include/arch/asm/macro.h b/arch/arm/apps/include/arch/asm/macro.h
new file mode 100644
index 0000000..e451024
--- /dev/null
+++ b/arch/arm/apps/include/arch/asm/macro.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2013 Jean-Christophe PLAGNIOL-VILLARD <plagnio@jcrosoft.com>
+ *
+ * Under GPLv2 only
+ *
+ * As a special exception, if other files instantiate templates or use macros
+ * or inline functions from this file, or you compile this file and link it
+ * with other works to produce a work based on this file, this file does not
+ * by itself cause the resulting work to be covered by the GNU General Public
+ * License. However the source code for this file must still be made available
+ * in accordance with section (3) of the GNU General Public License.
+
+ * This exception does not invalidate any other reasons why a work based on
+ * this file might be covered by the GNU General Public License.
+ */
+
+#ifndef __ARCH_ASM_MACRO_H__
+#define __ARCH_ASM_MACRO_H__
+
+#if (!defined(__ARM_ARCH_2__) && !defined(__ARM_ARCH_3__) \
+	&& !defined(__ARM_ARCH_3M__) && !defined(__ARM_ARCH_4__))
+#define BX(x)	bx	x
+#else
+#define BX(x)	mov	pc, x
+#endif
+
+#define __FUNC(x)		\
+	.balign 4;		\
+	.globl x;		\
+
+#ifdef __thumb__
+#define FUNC(x)	\
+	__FUNC(x)	\
+	.thumb_func;	\
+x:
+#else
+#define FUNC(x)		\
+	__FUNC(x)	\
+x:
+#endif
+
+#define ENDFUNC(x)		\
+	.type x, #function;	\
+	.size x, .-x
+
+#endif /* __ARCH_ASM_MACRO_H__ */
diff --git a/arch/arm/apps/include/arch/setjmp.h b/arch/arm/apps/include/arch/setjmp.h
new file mode 100644
index 0000000..82058a9
--- /dev/null
+++ b/arch/arm/apps/include/arch/setjmp.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2013 Jean-Christophe PLAGNIOL-VILLARD <plagnio@jcrosoft.com>
+ *
+ * Under GPLv2 only
+ *
+ * As a special exception, if other files instantiate templates or use macros
+ * or inline functions from this file, or you compile this file and link it
+ * with other works to produce a work based on this file, this file does not
+ * by itself cause the resulting work to be covered by the GNU General Public
+ * License. However the source code for this file must still be made available
+ * in accordance with section (3) of the GNU General Public License.
+
+ * This exception does not invalidate any other reasons why a work based on
+ * this file might be covered by the GNU General Public License.
+ */
+
+#ifndef __ARCH_SETJMP_H__
+#define __ARCH_SETJMP_H__
+
+struct __jmp_buf {
+		unsigned int regs[10];
+};
+
+typedef struct __jmp_buf jmp_buf[1];
+
+#endif /* __ARCH_SETJMP_H__ */
diff --git a/arch/arm/apps/raise.c b/arch/arm/apps/raise.c
new file mode 100644
index 0000000..18cc0d8
--- /dev/null
+++ b/arch/arm/apps/raise.c
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2013 Jean-Christophe PLAGNIOL-VILLARD <plagnio@jcrosoft.com>
+ *
+ * Under GPLv2 only
+ *
+ * As a special exception, if other files instantiate templates or use macros
+ * or inline functions from this file, or you compile this file and link it
+ * with other works to produce a work based on this file, this file does not
+ * by itself cause the resulting work to be covered by the GNU General Public
+ * License. However the source code for this file must still be made available
+ * in accordance with section (3) of the GNU General Public License.
+
+ * This exception does not invalidate any other reasons why a work based on
+ * this file might be covered by the GNU General Public License.
+ */
+
+#include <stdio.h>
+
+int raise(int signum)
+{
+	/* use puts as printf may not be availlable */
+	puts("raise: ");
+	puts(itoa(signum));
+	puts(" caught\n");
+
+	return 0;
+}
diff --git a/arch/arm/apps/setjmp.S b/arch/arm/apps/setjmp.S
new file mode 100644
index 0000000..1607ce3
--- /dev/null
+++ b/arch/arm/apps/setjmp.S
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2013 Jean-Christophe PLAGNIOL-VILLARD <plagnio@jcrosoft.com>
+ *
+ * Under GPLv2 only
+ *
+ * As a special exception, if other files instantiate templates or use macros
+ * or inline functions from this file, or you compile this file and link it
+ * with other works to produce a work based on this file, this file does not
+ * by itself cause the resulting work to be covered by the GNU General Public
+ * License. However the source code for this file must still be made available
+ * in accordance with section (3) of the GNU General Public License.
+
+ * This exception does not invalidate any other reasons why a work based on
+ * this file might be covered by the GNU General Public License.
+ */
+
+#include <arch/asm/macro.h>
+
+	.text
+FUNC(setjmp)
+#ifndef	__thumb__
+	stmia	r0, {r4, r5, r6, r7, r8, r9, r10, fp, sp, lr}
+#else
+	/* we need to do it in 2 steps in thumb */
+	mov	r3, lr
+	stmia	r0!, {r3, r4, r5, r6, r7}
+	mov	r3, r8
+	mov	r4, r9
+	mov	r5, r10
+	mov	r6, fp
+	mov	r7, sp
+	stmia	r0!, {r3, r4, r5, r6, r7}
+#endif /* __thumb__ */
+	mov	r0, #0
+	BX(lr)
+ENDFUNC(setjmp)
+
+	.text
+FUNC(longjmp)
+#ifndef	__thumb__
+	ldmia	r0, {r4, r5, r6, r7, r8, r9, r10, fp, sp, lr}
+	mov	r0, r1
+	BX(lr)
+#else
+	/* we need to do it in 2 steps in thumb */
+	mov	r2, r0
+	add	r0, #20
+	ldmia	r0!, {r3, r4, r5, r6, r7}
+	mov	r8, r3
+	mov	r9, r4
+	mov	r10, r5
+	mov	fp, r6
+	mov	sp, r7
+	ldmia	r2!, {r3, r4, r5, r6, r7}
+	mov	r0, r1
+	bne	1f
+	mov	r0, #1
+1:	BX(r3)
+#endif /* __thumb__ */
+ENDFUNC(longjmp)
diff --git a/arch/arm/apps/start.c b/arch/arm/apps/start.c
new file mode 100644
index 0000000..af072a1
--- /dev/null
+++ b/arch/arm/apps/start.c
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2013 Jean-Christophe PLAGNIOL-VILLARD <plagnio@jcrosoft.com>
+ *
+ * Under GPLv2 only
+ *
+ * As a special exception, if other files instantiate templates or use macros
+ * or inline functions from this file, or you compile this file and link it
+ * with other works to produce a work based on this file, this file does not
+ * by itself cause the resulting work to be covered by the GNU General Public
+ * License. However the source code for this file must still be made available
+ * in accordance with section (3) of the GNU General Public License.
+
+ * This exception does not invalidate any other reasons why a work based on
+ * this file might be covered by the GNU General Public License.
+ */
+
+#include <sys/types.h>
+
+static void *barebox_sp;
+void barebox_return(int, void*);
+int app_start(int argc, char **argv);
+
+void exit(int c)
+{
+	barebox_return(c, barebox_sp);
+}
+
+void arm_app_start(int argc, char** argv, void *sp)
+{
+	int ret;
+	barebox_sp = sp;
+
+	ret = app_start(argc, argv);
+	exit(ret);
+}
-- 
1.7.10.4


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH 10/20] app: printf: use HelenOS verison with wide char support
  2013-03-06  9:29 ` [PATCH 01/20] Makefile: x_flags prepare for apps support Jean-Christophe PLAGNIOL-VILLARD
                     ` (7 preceding siblings ...)
  2013-03-06  9:29   ` [PATCH 09/20] arm: add application support Jean-Christophe PLAGNIOL-VILLARD
@ 2013-03-06  9:29   ` Jean-Christophe PLAGNIOL-VILLARD
  2013-03-06  9:29   ` [PATCH 11/20] app: printf: add version from contiki Jean-Christophe PLAGNIOL-VILLARD
                     ` (9 subsequent siblings)
  18 siblings, 0 replies; 31+ messages in thread
From: Jean-Christophe PLAGNIOL-VILLARD @ 2013-03-06  9:29 UTC (permalink / raw)
  To: barebox

Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
---
 apps/include/stdio.h               |   21 +-
 apps/include/stdlib.h              |    3 +
 apps/include/{stdlib.h => wchar.h} |   24 +-
 apps/libc/Kconfig                  |   10 +
 apps/libc/Makefile                 |    1 +
 apps/libc/helenos/Makefile         |    4 +
 apps/libc/helenos/align.h          |   63 ++
 apps/libc/helenos/assert.h         |    2 +
 apps/libc/helenos/ctype.c          |   52 ++
 apps/libc/helenos/printf_core.c    |  905 +++++++++++++++++++
 apps/libc/helenos/printf_core.h    |   59 ++
 apps/libc/helenos/stdio.c          |  153 ++++
 apps/libc/helenos/str.c            | 1755 ++++++++++++++++++++++++++++++++++++
 apps/libc/helenos/str.h            |  135 +++
 apps/libc/helenos/vsnprintf.c      |  187 ++++
 15 files changed, 3353 insertions(+), 21 deletions(-)
 copy apps/include/{stdlib.h => wchar.h} (70%)
 create mode 100644 apps/libc/helenos/Makefile
 create mode 100644 apps/libc/helenos/align.h
 create mode 100644 apps/libc/helenos/assert.h
 create mode 100644 apps/libc/helenos/ctype.c
 create mode 100644 apps/libc/helenos/printf_core.c
 create mode 100644 apps/libc/helenos/printf_core.h
 create mode 100644 apps/libc/helenos/stdio.c
 create mode 100644 apps/libc/helenos/str.c
 create mode 100644 apps/libc/helenos/str.h
 create mode 100644 apps/libc/helenos/vsnprintf.c

diff --git a/apps/include/stdio.h b/apps/include/stdio.h
index 32a7d25..9c9720e 100644
--- a/apps/include/stdio.h
+++ b/apps/include/stdio.h
@@ -49,6 +49,16 @@ size_t fread(void *buf, size_t size, size_t nb, FILE *f);
 size_t fwrite(const void *buf, size_t size, size_t nb, FILE *f);
 int fseek(FILE *stream, long offset, int whence);
 
+int printf(const char *fmt, ...) __attribute__ ((format(__printf__, 1, 2)));
+int vprintf(const char *fmt, va_list args);
+int sprintf(char *buf, const char *fmt, ...) __attribute__ ((format(__printf__, 2, 3)));
+int snprintf(char *buf, size_t size, const char *fmt, ...) __attribute__ ((format(__printf__, 3, 4)));
+int vsprintf(char *buf, const char *fmt, va_list args);
+char *asprintf(const char *fmt, ...) __attribute__ ((format(__printf__, 1, 2)));
+char *vasprintf(const char *fmt, va_list ap);
+int vsnprintf(char *buf, size_t size, const char *fmt, va_list args);
+int vscnprintf(char *buf, size_t size, const char *fmt, va_list args);
+
 /* barebox API */
 void eputc(char c);
 int eputs(const char *str);
@@ -56,15 +66,4 @@ int tstc(void);
 int flush(int fd);
 char* itoa(int i);
 
-static int printf(const char *fmt, ...) __attribute__ ((format(__printf__, 1, 2)));
-static inline int printf(const char *fmt, ...)
-{
-	return 0;
-}
-
-static inline int vprintf(const char *fmt, va_list args)
-{
-	return 0;
-}
-
 #endif /* __STDIO_H__ */
diff --git a/apps/include/stdlib.h b/apps/include/stdlib.h
index 7ae78ad..e08775f 100644
--- a/apps/include/stdlib.h
+++ b/apps/include/stdlib.h
@@ -26,4 +26,7 @@ int atoi(const char *s);
 long atol(const char *s);
 long long atoll(const char *s);
 
+#define min(x, y) ((x) < (y) ? (x) : (y))
+#define max(x, y) ((x) > (y) ? (x) : (y))
+
 #endif /* __STDLIB_H__ */
diff --git a/apps/include/stdlib.h b/apps/include/wchar.h
similarity index 70%
copy from apps/include/stdlib.h
copy to apps/include/wchar.h
index 7ae78ad..8610569 100644
--- a/apps/include/stdlib.h
+++ b/apps/include/wchar.h
@@ -14,16 +14,20 @@
  * this file might be covered by the GNU General Public License.
  */
 
-#ifndef __STDLIB_H__
-#define __STDLIB_H__
+#ifndef __WCHAR_H__
+#define __WCHAR_H__
 
-#define EXIT_FAILURE 1
-#define EXIT_SUCCESS 0
+#include <stdio.h>
 
-char *getenv(const char *name);
-void exit(int num);
-int atoi(const char *s);
-long atol(const char *s);
-long long atoll(const char *s);
+typedef unsigned long wchar_t;
+typedef long wint_t;
 
-#endif /* __STDLIB_H__ */
+
+#define wprintf printf
+#define fwprintf fprintf
+#define swprintf sprintf
+#define vwprintf vprintf
+#define vfwprintf vfwprintf
+#define vswprintf vswprintf
+
+#endif /* __WCHAR_H__ */
diff --git a/apps/libc/Kconfig b/apps/libc/Kconfig
index b9478b5..25b35ee 100644
--- a/apps/libc/Kconfig
+++ b/apps/libc/Kconfig
@@ -22,4 +22,14 @@ config APP_PRINTF_STACK_SIZE
 	hex "printf stack size"
 	default 0x1000
 
+choice
+	prompt "printf implementation"
+
+config APPS_PRINTF_HELENOS
+	bool "helen os"
+	help
+	  support wide char
+
+endchoice
+
 endmenu
diff --git a/apps/libc/Makefile b/apps/libc/Makefile
index 844ea9b..c84f00e 100644
--- a/apps/libc/Makefile
+++ b/apps/libc/Makefile
@@ -15,6 +15,7 @@ app-y += unistd.o
 app-$(CONFIG_APPS_MALLOC_DUMMY) += dummy_malloc.o
 app-$(CONFIG_APPS_MALLOC_TLSF) += tlsf_malloc.o tlsf.o
 app-y += string.o
+obj-$(CONFIG_APPS_PRINTF_HELENOS) += helenos/
 obj-y += sys/
 app-y += time.o
 
diff --git a/apps/libc/helenos/Makefile b/apps/libc/helenos/Makefile
new file mode 100644
index 0000000..1c34aff
--- /dev/null
+++ b/apps/libc/helenos/Makefile
@@ -0,0 +1,4 @@
+app-y += printf_core.o
+app-y += vsnprintf.o
+app-y += str.o
+app-y += stdio.o
diff --git a/apps/libc/helenos/align.h b/apps/libc/helenos/align.h
new file mode 100644
index 0000000..8ca4270
--- /dev/null
+++ b/apps/libc/helenos/align.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2005 Jakub Jermar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup libc
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBC_ALIGN_H_
+#define LIBC_ALIGN_H_
+
+/** Align to the nearest lower address which is a power of two.
+ *
+ * @param s		Address or size to be aligned.
+ * @param a		Size of alignment, must be power of 2.
+ */
+#define ALIGN_DOWN(s, a)	((s) & ~((a) - 1))
+
+
+/** Align to the nearest higher address which is a power of two.
+ *
+ * @param s		Address or size to be aligned.
+ * @param a		Size of alignment, must be power of 2.
+ */
+#define ALIGN_UP(s, a)		((long)((s) + ((a) - 1)) & ~((long) (a) - 1))
+
+/** Round up to the nearest higher boundary.
+ *
+ * @param n		Number to be aligned.
+ * @param b		Boundary, arbitrary unsigned number.
+ */
+#define ROUND_UP(n, b)		(((n) / (b) + ((n) % (b) != 0)) * (b))
+
+#endif
+
+/** @}
+ */
diff --git a/apps/libc/helenos/assert.h b/apps/libc/helenos/assert.h
new file mode 100644
index 0000000..16fedb4
--- /dev/null
+++ b/apps/libc/helenos/assert.h
@@ -0,0 +1,2 @@
+
+#define assert(x)
diff --git a/apps/libc/helenos/ctype.c b/apps/libc/helenos/ctype.c
new file mode 100644
index 0000000..6d20da5
--- /dev/null
+++ b/apps/libc/helenos/ctype.c
@@ -0,0 +1,52 @@
+/*
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+/*
+ *  linux/lib/ctype.c
+ *
+ *  Copyright (C) 1991, 1992  Linus Torvalds
+ */
+
+#include <linux/ctype.h>
+
+unsigned char _ctype[] = {
+_C,_C,_C,_C,_C,_C,_C,_C,			/* 0-7 */
+_C,_C|_S,_C|_S,_C|_S,_C|_S,_C|_S,_C,_C,		/* 8-15 */
+_C,_C,_C,_C,_C,_C,_C,_C,			/* 16-23 */
+_C,_C,_C,_C,_C,_C,_C,_C,			/* 24-31 */
+_S|_SP,_P,_P,_P,_P,_P,_P,_P,			/* 32-39 */
+_P,_P,_P,_P,_P,_P,_P,_P,			/* 40-47 */
+_D,_D,_D,_D,_D,_D,_D,_D,			/* 48-55 */
+_D,_D,_P,_P,_P,_P,_P,_P,			/* 56-63 */
+_P,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U,	/* 64-71 */
+_U,_U,_U,_U,_U,_U,_U,_U,			/* 72-79 */
+_U,_U,_U,_U,_U,_U,_U,_U,			/* 80-87 */
+_U,_U,_U,_P,_P,_P,_P,_P,			/* 88-95 */
+_P,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L,	/* 96-103 */
+_L,_L,_L,_L,_L,_L,_L,_L,			/* 104-111 */
+_L,_L,_L,_L,_L,_L,_L,_L,			/* 112-119 */
+_L,_L,_L,_P,_P,_P,_P,_C,			/* 120-127 */
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,		/* 128-143 */
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,		/* 144-159 */
+_S|_SP,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,   /* 160-175 */
+_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,       /* 176-191 */
+_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,       /* 192-207 */
+_U,_U,_U,_U,_U,_U,_U,_P,_U,_U,_U,_U,_U,_U,_U,_L,       /* 208-223 */
+_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,       /* 224-239 */
+_L,_L,_L,_L,_L,_L,_L,_P,_L,_L,_L,_L,_L,_L,_L,_L};      /* 240-255 */
diff --git a/apps/libc/helenos/printf_core.c b/apps/libc/helenos/printf_core.c
new file mode 100644
index 0000000..ccfaaa9
--- /dev/null
+++ b/apps/libc/helenos/printf_core.c
@@ -0,0 +1,905 @@
+/*
+ * Copyright (c) 2001-2004 Jakub Jermar
+ * Copyright (c) 2006 Josef Cejka
+ * Copyright (c) 2009 Martin Decky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdlib.h>
+#include <stdarg.h>
+#include <ctype.h>
+
+#include "printf_core.h"
+#include "str.h"
+
+/** show prefixes 0x or 0 */
+#define __PRINTF_FLAG_PREFIX       0x00000001
+
+/** show the decimal point even if no fractional digits present */
+#define __PRINTF_FLAG_DECIMALPT    0x00000001
+
+/** signed / unsigned number */
+#define __PRINTF_FLAG_SIGNED       0x00000002
+
+/** print leading zeroes */
+#define __PRINTF_FLAG_ZEROPADDED   0x00000004
+
+/** align to left */
+#define __PRINTF_FLAG_LEFTALIGNED  0x00000010
+
+/** always show + sign */
+#define __PRINTF_FLAG_SHOWPLUS     0x00000020
+
+/** print space instead of plus */
+#define __PRINTF_FLAG_SPACESIGN    0x00000040
+
+/** show big characters */
+#define __PRINTF_FLAG_BIGCHARS     0x00000080
+
+/** number has - sign */
+#define __PRINTF_FLAG_NEGATIVE     0x00000100
+
+/** don't print trailing zeros in the fractional part */
+#define __PRINTF_FLAG_NOFRACZEROS  0x00000200
+
+
+/**
+ * Buffer big enough for 64-bit number printed in base 2, sign, prefix and 0
+ * to terminate string... (last one is only for better testing end of buffer by
+ * zero-filling subroutine)
+ */
+#define PRINT_NUMBER_BUFFER_SIZE  (64 + 5)
+
+/** Enumeration of possible arguments types.
+ */
+typedef enum {
+	PrintfQualifierByte = 0,
+	PrintfQualifierShort,
+	PrintfQualifierInt,
+	PrintfQualifierLong,
+	PrintfQualifierLongLong,
+	PrintfQualifierPointer,
+	PrintfQualifierSize
+} qualifier_t;
+
+static const char *nullstr = "(NULL)";
+static const char digits_small[] = "0123456789abcdef";
+static const char digits_big[] = "0123456789ABCDEF";
+static const char invalch = U_SPECIAL;
+
+/** Print one or more characters without adding newline.
+ *
+ * @param buf  Buffer holding characters with size of
+ *             at least size bytes. NULL is not allowed!
+ * @param size Size of the buffer in bytes.
+ * @param ps   Output method and its data.
+ *
+ * @return Number of characters printed.
+ *
+ */
+static int printf_putnchars(const char *buf, size_t size,
+    printf_spec_t *ps)
+{
+	return ps->str_write((void *) buf, size, ps->data);
+}
+
+/** Print one or more wide characters without adding newline.
+ *
+ * @param buf  Buffer holding wide characters with size of
+ *             at least size bytes. NULL is not allowed!
+ * @param size Size of the buffer in bytes.
+ * @param ps   Output method and its data.
+ *
+ * @return Number of wide characters printed.
+ *
+ */
+static int printf_wputnchars(const wchar_t *buf, size_t size,
+    printf_spec_t *ps)
+{
+	return ps->wstr_write((void *) buf, size, ps->data);
+}
+
+/** Print string without adding a newline.
+ *
+ * @param str String to print.
+ * @param ps  Write function specification and support data.
+ *
+ * @return Number of characters printed.
+ *
+ */
+static int printf_putstr(const char *str, printf_spec_t *ps)
+{
+	if (str == NULL)
+		return printf_putnchars(nullstr, str_size(nullstr), ps);
+	
+	return ps->str_write((void *) str, str_size(str), ps->data);
+}
+
+/** Print one ASCII character.
+ *
+ * @param c  ASCII character to be printed.
+ * @param ps Output method.
+ *
+ * @return Number of characters printed.
+ *
+ */
+static int printf_putchar(const char ch, printf_spec_t *ps)
+{
+	if (!ascii_check(ch))
+		return ps->str_write((void *) &invalch, 1, ps->data);
+	
+	return ps->str_write(&ch, 1, ps->data);
+}
+
+/** Print one wide character.
+ *
+ * @param c  Wide character to be printed.
+ * @param ps Output method.
+ *
+ * @return Number of characters printed.
+ *
+ */
+static int printf_putwchar(const wchar_t ch, printf_spec_t *ps)
+{
+	if (!chr_check(ch))
+		return ps->str_write((void *) &invalch, 1, ps->data);
+	
+	return ps->wstr_write(&ch, sizeof(wchar_t), ps->data);
+}
+
+/** Print one formatted ASCII character.
+ *
+ * @param ch    Character to print.
+ * @param width Width modifier.
+ * @param flags Flags that change the way the character is printed.
+ *
+ * @return Number of characters printed, negative value on failure.
+ *
+ */
+static int print_char(const char ch, int width, uint32_t flags, printf_spec_t *ps)
+{
+	size_t counter = 0;
+	if (!(flags & __PRINTF_FLAG_LEFTALIGNED)) {
+		while (--width > 0) {
+			/*
+			 * One space is consumed by the character itself, hence
+			 * the predecrement.
+			 */
+			if (printf_putchar(' ', ps) > 0)
+				counter++;
+		}
+	}
+	
+	if (printf_putchar(ch, ps) > 0)
+		counter++;
+	
+	while (--width > 0) {
+		/*
+		 * One space is consumed by the character itself, hence
+		 * the predecrement.
+		 */
+		if (printf_putchar(' ', ps) > 0)
+			counter++;
+	}
+	
+	return (int) (counter);
+}
+
+/** Print one formatted wide character.
+ *
+ * @param ch    Character to print.
+ * @param width Width modifier.
+ * @param flags Flags that change the way the character is printed.
+ *
+ * @return Number of characters printed, negative value on failure.
+ *
+ */
+static int print_wchar(const wchar_t ch, int width, uint32_t flags, printf_spec_t *ps)
+{
+	size_t counter = 0;
+	if (!(flags & __PRINTF_FLAG_LEFTALIGNED)) {
+		while (--width > 0) {
+			/*
+			 * One space is consumed by the character itself, hence
+			 * the predecrement.
+			 */
+			if (printf_putchar(' ', ps) > 0)
+				counter++;
+		}
+	}
+	
+	if (printf_putwchar(ch, ps) > 0)
+		counter++;
+	
+	while (--width > 0) {
+		/*
+		 * One space is consumed by the character itself, hence
+		 * the predecrement.
+		 */
+		if (printf_putchar(' ', ps) > 0)
+			counter++;
+	}
+	
+	return (int) (counter);
+}
+
+/** Print string.
+ *
+ * @param str       String to be printed.
+ * @param width     Width modifier.
+ * @param precision Precision modifier.
+ * @param flags     Flags that modify the way the string is printed.
+ *
+ * @return Number of characters printed, negative value on failure.
+ */
+static int print_str(char *str, int width, unsigned int precision,
+    uint32_t flags, printf_spec_t *ps)
+{
+	size_t strw;
+	size_t counter = 0;
+	size_t size;
+	int retval;
+
+	if (str == NULL)
+		return printf_putstr(nullstr, ps);
+	
+	strw = str_length(str);
+
+	/* Precision unspecified - print everything. */
+	if ((precision == 0) || (precision > strw))
+		precision = strw;
+	
+	/* Left padding */
+	width -= precision;
+	if (!(flags & __PRINTF_FLAG_LEFTALIGNED)) {
+		while (width-- > 0) {
+			if (printf_putchar(' ', ps) == 1)
+				counter++;
+		}
+	}
+	
+	/* Part of @a str fitting into the alloted space. */
+	size = str_lsize(str, precision);
+	if ((retval = printf_putnchars(str, size, ps)) < 0)
+		return -counter;
+
+	counter += retval;
+
+	/* Right padding */
+	while (width-- > 0) {
+		if (printf_putchar(' ', ps) == 1)
+			counter++;
+	}
+
+	return ((int) counter);
+
+}
+
+/** Print wide string.
+ *
+ * @param str       Wide string to be printed.
+ * @param width     Width modifier.
+ * @param precision Precision modifier.
+ * @param flags     Flags that modify the way the string is printed.
+ *
+ * @return Number of wide characters printed, negative value on failure.
+ */
+static int print_wstr(wchar_t *str, int width, unsigned int precision,
+    uint32_t flags, printf_spec_t *ps)
+{
+	size_t counter = 0;
+	size_t strw;
+	int retval;
+	size_t size;
+
+	if (str == NULL)
+		return printf_putstr(nullstr, ps);
+	
+	strw = wstr_length(str);
+
+	/* Precision not specified - print everything. */
+	if ((precision == 0) || (precision > strw))
+		precision = strw;
+	
+	/* Left padding */
+	width -= precision;
+	if (!(flags & __PRINTF_FLAG_LEFTALIGNED)) {
+		while (width-- > 0) {
+			if (printf_putchar(' ', ps) == 1)
+				counter++;
+		}
+	}
+	
+	/* Part of @a wstr fitting into the alloted space. */
+	size = wstr_lsize(str, precision);
+	if ((retval = printf_wputnchars(str, size, ps)) < 0)
+		return -counter;
+	
+	counter += retval;
+	
+	/* Right padding */
+	while (width-- > 0) {
+		if (printf_putchar(' ', ps) == 1)
+			counter++;
+	}
+
+	return ((int) counter);
+}
+
+/** Print a number in a given base.
+ *
+ * Print significant digits of a number in given base.
+ *
+ * @param num       Number to print.
+ * @param width     Width modifier.
+ * @param precision Precision modifier.
+ * @param base      Base to print the number in (must be between 2 and 16).
+ * @param flags     Flags that modify the way the number is printed.
+ *
+ * @return Number of characters printed.
+ *
+ */
+static int print_number(uint64_t num, int width, int precision, int base,
+			uint64_t flags, printf_spec_t *ps)
+{
+	const char *digits;
+	char d[PRINT_NUMBER_BUFFER_SIZE];
+	char *ptr = &d[PRINT_NUMBER_BUFFER_SIZE - 1];
+	int size = 0;		/* Size of number with all prefixes and signs. */
+	int number_size;	/* Size of plain number. */
+	char sgn;
+	int retval;
+	int counter = 0;
+
+	if (flags & __PRINTF_FLAG_BIGCHARS)
+		digits = digits_big;
+	else
+		digits = digits_small;
+	
+	/* Put zero at end of string */
+	*ptr-- = 0;
+	
+	if (num == 0) {
+		*ptr-- = '0';
+		size++;
+	} else {
+		do {
+			*ptr-- = digits[num % base];
+			size++;
+		} while (num /= base);
+	}
+	
+	/* Size of plain number */
+	number_size = size;
+	
+	/*
+	 * Collect the sum of all prefixes/signs/etc. to calculate padding and
+	 * leading zeroes.
+	 */
+	if (flags & __PRINTF_FLAG_PREFIX) {
+		switch (base) {
+		case 2:
+			/* Binary formating is not standard, but usefull */
+			size += 2;
+			break;
+		case 8:
+			size++;
+			break;
+		case 16:
+			size += 2;
+			break;
+		}
+	}
+	
+	sgn = 0;
+	if (flags & __PRINTF_FLAG_SIGNED) {
+		if (flags & __PRINTF_FLAG_NEGATIVE) {
+			sgn = '-';
+			size++;
+		} else if (flags & __PRINTF_FLAG_SHOWPLUS) {
+			sgn = '+';
+			size++;
+		} else if (flags & __PRINTF_FLAG_SPACESIGN) {
+			sgn = ' ';
+			size++;
+		}
+	}
+	
+	if (flags & __PRINTF_FLAG_LEFTALIGNED)
+		flags &= ~__PRINTF_FLAG_ZEROPADDED;
+	
+	/*
+	 * If the number is left-aligned or precision is specified then
+	 * padding with zeros is ignored.
+	 */
+	if (flags & __PRINTF_FLAG_ZEROPADDED) {
+		if ((precision == 0) && (width > size))
+			precision = width - size + number_size;
+	}
+	
+	/* Print leading spaces */
+	if (number_size > precision) {
+		/* Print the whole number, not only a part */
+		precision = number_size;
+	}
+	
+	width -= precision + size - number_size;
+	
+	if (!(flags & __PRINTF_FLAG_LEFTALIGNED)) {
+		while (width-- > 0) {
+			if (printf_putchar(' ', ps) == 1)
+				counter++;
+		}
+	}
+	
+	/* Print sign */
+	if (sgn) {
+		if (printf_putchar(sgn, ps) == 1)
+			counter++;
+	}
+	
+	/* Print prefix */
+	if (flags & __PRINTF_FLAG_PREFIX) {
+		switch (base) {
+		case 2:
+			/* Binary formating is not standard, but usefull */
+			if (printf_putchar('0', ps) == 1)
+				counter++;
+			if (flags & __PRINTF_FLAG_BIGCHARS) {
+				if (printf_putchar('B', ps) == 1)
+					counter++;
+			} else {
+				if (printf_putchar('b', ps) == 1)
+					counter++;
+			}
+			break;
+		case 8:
+			if (printf_putchar('o', ps) == 1)
+				counter++;
+			break;
+		case 16:
+			if (printf_putchar('0', ps) == 1)
+				counter++;
+			if (flags & __PRINTF_FLAG_BIGCHARS) {
+				if (printf_putchar('X', ps) == 1)
+					counter++;
+			} else {
+				if (printf_putchar('x', ps) == 1)
+					counter++;
+			}
+			break;
+		}
+	}
+	
+	/* Print leading zeroes */
+	precision -= number_size;
+	while (precision-- > 0) {
+		if (printf_putchar('0', ps) == 1)
+			counter++;
+	}
+	
+	/* Print the number itself */
+	if ((retval = printf_putstr(++ptr, ps)) > 0)
+		counter += retval;
+	
+	/* Print trailing spaces */
+	
+	while (width-- > 0) {
+		if (printf_putchar(' ', ps) == 1)
+			counter++;
+	}
+	
+	return ((int) counter);
+}
+
+/** Print formatted string.
+ *
+ * Print string formatted according to the fmt parameter and variadic arguments.
+ * Each formatting directive must have the following form:
+ *
+ *  \% [ FLAGS ] [ WIDTH ] [ .PRECISION ] [ TYPE ] CONVERSION
+ *
+ * FLAGS:@n
+ *  - "#" Force to print prefix. For \%o conversion, the prefix is 0, for
+ *        \%x and \%X prefixes are 0x and 0X and for conversion \%b the
+ *        prefix is 0b.
+ *
+ *  - "-" Align to left.
+ *
+ *  - "+" Print positive sign just as negative.
+ *
+ *  - " " If the printed number is positive and "+" flag is not set,
+ *        print space in place of sign.
+ *
+ *  - "0" Print 0 as padding instead of spaces. Zeroes are placed between
+ *        sign and the rest of the number. This flag is ignored if "-"
+ *        flag is specified.
+ *
+ * WIDTH:@n
+ *  - Specify the minimal width of a printed argument. If it is bigger,
+ *    width is ignored. If width is specified with a "*" character instead of
+ *    number, width is taken from parameter list. And integer parameter is
+ *    expected before parameter for processed conversion specification. If
+ *    this value is negative its absolute value is taken and the "-" flag is
+ *    set.
+ *
+ * PRECISION:@n
+ *  - Value precision. For numbers it specifies minimum valid numbers.
+ *    Smaller numbers are printed with leading zeroes. Bigger numbers are not
+ *    affected. Strings with more than precision characters are cut off. Just
+ *    as with width, an "*" can be used used instead of a number. An integer
+ *    value is then expected in parameters. When both width and precision are
+ *    specified using "*", the first parameter is used for width and the
+ *    second one for precision.
+ *
+ * TYPE:@n
+ *  - "hh" Signed or unsigned char.@n
+ *  - "h"  Signed or unsigned short.@n
+ *  - ""   Signed or unsigned int (default value).@n
+ *  - "l"  Signed or unsigned long int.@n
+ *         If conversion is "c", the character is wint_t (wide character).@n
+ *         If conversion is "s", the string is wchar_t * (wide string).@n
+ *  - "ll" Signed or unsigned long long int.@n
+ *  - "z"  Signed or unsigned ssize_t or site_t.@n
+ *
+ * CONVERSION:@n
+ *  - % Print percentile character itself.
+ *
+ *  - c Print single character. The character is expected to be plain
+ *      ASCII (e.g. only values 0 .. 127 are valid).@n
+ *      If type is "l", then the character is expected to be wide character
+ *      (e.g. values 0 .. 0x10ffff are valid).
+ *
+ *  - s Print zero terminated string. If a NULL value is passed as
+ *      value, "(NULL)" is printed instead.@n
+ *      If type is "l", then the string is expected to be wide string.
+ *
+ *  - P, p Print value of a pointer. Void * value is expected and it is
+ *         printed in hexadecimal notation with prefix (as with
+ *         \%#0.8X / \%#0.8x for 32-bit or \%#0.16lX / \%#0.16lx for 64-bit
+ *         long pointers).
+ *
+ *  - b Print value as unsigned binary number. Prefix is not printed by
+ *      default. (Nonstandard extension.)
+ *
+ *  - o Print value as unsigned octal number. Prefix is not printed by
+ *      default.
+ *
+ *  - d, i Print signed decimal number. There is no difference between d
+ *         and i conversion.
+ *
+ *  - u Print unsigned decimal number.
+ *
+ *  - X, x Print hexadecimal number with upper- or lower-case. Prefix is
+ *         not printed by default.
+ *
+ * All other characters from fmt except the formatting directives are printed
+ * verbatim.
+ *
+ * @param fmt Format NULL-terminated string.
+ *
+ * @return Number of characters printed, negative value on failure.
+ *
+ */
+int printf_core(const char *fmt, printf_spec_t *ps, va_list ap)
+{
+	size_t i;        /* Index of the currently processed character from fmt */
+	size_t nxt = 0;  /* Index of the next character from fmt */
+	size_t j = 0;    /* Index to the first not printed nonformating character */
+	
+	size_t counter = 0;   /* Number of characters printed */
+	int retval;           /* Return values from nested functions */
+	
+	while (true) {
+		wchar_t uc;
+
+		i = nxt;
+		uc = str_decode(fmt, &nxt, STR_NO_LIMIT);
+		
+		if (uc == 0)
+			break;
+		
+		/* Control character */
+		if (uc == '%') {
+			uint32_t flags = 0;
+			bool end = false;
+			int width = 0;
+			int precision = -1;
+			qualifier_t qualifier;
+			unsigned int base = 10;
+			size_t size;
+			uint64_t number;
+
+			/* Print common characters if any processed */
+			if (i > j) {
+				if ((retval = printf_putnchars(&fmt[j], i - j, ps)) < 0) {
+					/* Error */
+					counter = -counter;
+					goto out;
+				}
+				counter += retval;
+			}
+			
+			j = i;
+			
+			/* Parse modifiers */
+			do {
+				i = nxt;
+				uc = str_decode(fmt, &nxt, STR_NO_LIMIT);
+				switch (uc) {
+				case '#':
+					flags |= __PRINTF_FLAG_PREFIX;
+					flags |= __PRINTF_FLAG_DECIMALPT;
+					break;
+				case '-':
+					flags |= __PRINTF_FLAG_LEFTALIGNED;
+					break;
+				case '+':
+					flags |= __PRINTF_FLAG_SHOWPLUS;
+					break;
+				case ' ':
+					flags |= __PRINTF_FLAG_SPACESIGN;
+					break;
+				case '0':
+					flags |= __PRINTF_FLAG_ZEROPADDED;
+					break;
+				default:
+					end = true;
+				};
+			} while (!end);
+			
+			/* Width & '*' operator */
+			if (isdigit(uc)) {
+				while (true) {
+					width *= 10;
+					width += uc - '0';
+					
+					i = nxt;
+					uc = str_decode(fmt, &nxt, STR_NO_LIMIT);
+					if (uc == 0)
+						break;
+					if (!isdigit(uc))
+						break;
+				}
+			} else if (uc == '*') {
+				/* Get width value from argument list */
+				i = nxt;
+				uc = str_decode(fmt, &nxt, STR_NO_LIMIT);
+				width = (int) va_arg(ap, int);
+				if (width < 0) {
+					/* Negative width sets '-' flag */
+					width *= -1;
+					flags |= __PRINTF_FLAG_LEFTALIGNED;
+				}
+			}
+			
+			/* Precision and '*' operator */
+			if (uc == '.') {
+				i = nxt;
+				uc = str_decode(fmt, &nxt, STR_NO_LIMIT);
+				if (isdigit(uc)) {
+					precision = 0;
+					while (true) {
+						precision *= 10;
+						precision += uc - '0';
+						
+						i = nxt;
+						uc = str_decode(fmt, &nxt, STR_NO_LIMIT);
+						if (uc == 0)
+							break;
+						if (!isdigit(uc))
+							break;
+					}
+				} else if (uc == '*') {
+					/* Get precision value from the argument list */
+					i = nxt;
+					uc = str_decode(fmt, &nxt, STR_NO_LIMIT);
+					precision = (int) va_arg(ap, int);
+					if (precision < 0) {
+						/* Ignore negative precision - use default instead */
+						precision = -1;
+					}
+				}
+			}
+			
+			switch (uc) {
+			/** @todo Unimplemented qualifiers:
+			 *        t ptrdiff_t - ISO C 99
+			 */
+			case 'h':
+				/* Char or short */
+				qualifier = PrintfQualifierShort;
+				i = nxt;
+				uc = str_decode(fmt, &nxt, STR_NO_LIMIT);
+				if (uc == 'h') {
+					i = nxt;
+					uc = str_decode(fmt, &nxt, STR_NO_LIMIT);
+					qualifier = PrintfQualifierByte;
+				}
+				break;
+			case 'l':
+				/* Long or long long */
+				qualifier = PrintfQualifierLong;
+				i = nxt;
+				uc = str_decode(fmt, &nxt, STR_NO_LIMIT);
+				if (uc == 'l') {
+					i = nxt;
+					uc = str_decode(fmt, &nxt, STR_NO_LIMIT);
+					qualifier = PrintfQualifierLongLong;
+				}
+				break;
+			case 'z':
+				qualifier = PrintfQualifierSize;
+				i = nxt;
+				uc = str_decode(fmt, &nxt, STR_NO_LIMIT);
+				break;
+			default:
+				/* Default type */
+				qualifier = PrintfQualifierInt;
+			}
+			
+			switch (uc) {
+			/*
+			 * String and character conversions.
+			 */
+			case 's':
+				precision = max(0,  precision);
+				
+				if (qualifier == PrintfQualifierLong)
+					retval = print_wstr(va_arg(ap, wchar_t *), width, precision, flags, ps);
+				else
+					retval = print_str(va_arg(ap, char *), width, precision, flags, ps);
+				
+				if (retval < 0) {
+					counter = -counter;
+					goto out;
+				}
+				
+				counter += retval;
+				j = nxt;
+				goto next_char;
+			case 'c':
+				if (qualifier == PrintfQualifierLong)
+					retval = print_wchar(va_arg(ap, wint_t), width, flags, ps);
+				else
+					retval = print_char(va_arg(ap, unsigned int), width, flags, ps);
+				
+				if (retval < 0) {
+					counter = -counter;
+					goto out;
+				};
+				
+				counter += retval;
+				j = nxt;
+				goto next_char;
+				
+			/*
+			 * Integer values
+			 */
+			case 'P':
+				/* Pointer */
+				flags |= __PRINTF_FLAG_BIGCHARS;
+			case 'p':
+				flags |= __PRINTF_FLAG_PREFIX;
+				flags |= __PRINTF_FLAG_ZEROPADDED;
+				base = 16;
+				qualifier = PrintfQualifierPointer;
+				break;
+			case 'b':
+				base = 2;
+				break;
+			case 'o':
+				base = 8;
+				break;
+			case 'd':
+			case 'i':
+				flags |= __PRINTF_FLAG_SIGNED;
+			case 'u':
+				break;
+			case 'X':
+				flags |= __PRINTF_FLAG_BIGCHARS;
+			case 'x':
+				base = 16;
+				break;
+			
+			/* Percentile itself */
+			case '%':
+				j = i;
+				goto next_char;
+			
+			/*
+			 * Bad formatting.
+			 */
+			default:
+				/*
+				 * Unknown format. Now, j is the index of '%'
+				 * so we will print whole bad format sequence.
+				 */
+				goto next_char;
+			}
+			
+			/* Print integers */
+			switch (qualifier) {
+			case PrintfQualifierByte:
+				size = sizeof(unsigned char);
+				number = (uint64_t) va_arg(ap, unsigned int);
+				break;
+			case PrintfQualifierShort:
+				size = sizeof(unsigned short);
+				number = (uint64_t) va_arg(ap, unsigned int);
+				break;
+			case PrintfQualifierInt:
+				size = sizeof(unsigned int);
+				number = (uint64_t) va_arg(ap, unsigned int);
+				break;
+			case PrintfQualifierLong:
+				size = sizeof(unsigned long);
+				number = (uint64_t) va_arg(ap, unsigned long);
+				break;
+			case PrintfQualifierLongLong:
+				size = sizeof(unsigned long long);
+				number = (uint64_t) va_arg(ap, unsigned long long);
+				break;
+			case PrintfQualifierPointer:
+				size = sizeof(void *);
+				precision = size << 1;
+				number = (uint64_t) (unsigned long)va_arg(ap, void *);
+				break;
+			case PrintfQualifierSize:
+				size = sizeof(size_t);
+				number = (uint64_t) va_arg(ap, size_t);
+				break;
+			default:
+				/* Unknown qualifier */
+				counter = -counter;
+				goto out;
+			}
+			
+			if ((retval = print_number(number, width, precision,
+			    base, flags, ps)) < 0) {
+				counter = -counter;
+				goto out;
+			}
+			
+			counter += retval;
+			j = nxt;
+		}
+next_char:
+		;
+	}
+	
+	if (i > j) {
+		if ((retval = printf_putnchars(&fmt[j], i - j, ps)) < 0) {
+			/* Error */
+			counter = -counter;
+			goto out;
+		}
+		counter += retval;
+	}
+	
+out:
+	return ((int) counter);
+}
diff --git a/apps/libc/helenos/printf_core.h b/apps/libc/helenos/printf_core.h
new file mode 100644
index 0000000..71c725a
--- /dev/null
+++ b/apps/libc/helenos/printf_core.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2006 Josef Cejka
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup libc
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBC_PRINTF_CORE_H_
+#define LIBC_PRINTF_CORE_H_
+
+#include <sys/types.h>
+#include <stdarg.h>
+#include <wchar.h>
+
+/** Structure for specifying output methods for different printf clones. */
+typedef struct {
+	/* String output function, returns number of printed characters or EOF */
+	int (*str_write)(const char *, size_t, void *);
+	
+	/* Wide string output function, returns number of printed characters or EOF */
+	int (*wstr_write)(const wchar_t *, size_t, void *);
+	
+	/* User data - output stream specification, state, locks, etc. */
+	void *data;
+} printf_spec_t;
+
+extern int printf_core(const char *, printf_spec_t *, va_list);
+
+#endif
+
+/** @}
+ */
diff --git a/apps/libc/helenos/stdio.c b/apps/libc/helenos/stdio.c
new file mode 100644
index 0000000..e4bf3c6
--- /dev/null
+++ b/apps/libc/helenos/stdio.c
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 2011 Jiri Zarevucky
+ * Copyright (c) 2011 Petr Koupy
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup libposix
+ * @{
+ */
+/** @file Standard buffered input/output.
+ */
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <malloc.h>
+
+#include "printf_core.h"
+#include "str.h"
+
+
+/**
+ * Write ordinary string to the opened file.
+ *
+ * @param str String to be written.
+ * @param size Size of the string (in bytes)..
+ * @param fd File descriptor of the opened file.
+ * @return The number of written characters.
+ */
+static int _dprintf_str_write(const char *str, size_t size, void *fd)
+{
+	ssize_t wr = write(*(int *) fd, str, size);
+	return str_nlength(str, wr);
+}
+
+/**
+ * Write wide string to the opened file.
+ * 
+ * @param str String to be written.
+ * @param size Size of the string (in bytes).
+ * @param fd File descriptor of the opened file.
+ * @return The number of written characters.
+ */
+static int _dprintf_wstr_write(const wchar_t *str, size_t size, void *fd)
+{
+	size_t offset = 0;
+	size_t chars = 0;
+	size_t sz;
+	char buf[4];
+	
+	while (offset < size) {
+		sz = 0;
+		if (chr_encode(str[chars], buf, &sz, sizeof(buf)) != 0) {
+			break;
+		}
+		
+		if (write(*(int *) fd, buf, sz) != (ssize_t) sz) {
+			break;
+		}
+		
+		chars++;
+		offset += sizeof(wchar_t);
+	}
+	
+	return chars;
+}
+
+/**
+ * Print formatted output to the opened file.
+ * 
+ * @param fildes File descriptor of the opened file.
+ * @param format Format description.
+ * @param ap Print arguments.
+ * @return Either the number of printed characters or negative value on error.
+ */
+int vdprintf(int fildes, const char * format, va_list ap)
+{
+	printf_spec_t spec = {
+		.str_write = _dprintf_str_write,
+		.wstr_write = _dprintf_wstr_write,
+		.data = &fildes
+	};
+	
+	return printf_core(format, &spec, ap);
+}
+
+/**
+ * Print formatted output to the string.
+ * 
+ * @param s Output string.
+ * @param format Format description.
+ * @return Either the number of printed characters (excluding null byte) or
+ *     negative value on error.
+ */
+int sprintf(char *s, const char * format, ...)
+{
+	va_list list;
+	int result;
+
+	va_start(list, format);
+	result = vsprintf(s, format, list);
+	va_end(list);
+	return result;
+}
+
+/**
+ * Print formatted output to the string.
+ * 
+ * @param s Output string.
+ * @param format Format description.
+ * @param ap Print arguments.
+ * @return Either the number of printed characters (excluding null byte) or
+ *     negative value on error.
+ */
+int vsprintf(char *s, const char * format, va_list ap)
+{
+	return vsnprintf(s, STR_NO_LIMIT, format, ap);
+}
+
+int snprintf(char *str, size_t size, const char *fmt, ...)
+{
+	int ret;
+	va_list args;
+
+	va_start(args, fmt);
+	ret = vsnprintf(str, size, fmt, args);
+	va_end(args);
+
+	return ret;
+}
diff --git a/apps/libc/helenos/str.c b/apps/libc/helenos/str.c
new file mode 100644
index 0000000..cb350e9
--- /dev/null
+++ b/apps/libc/helenos/str.c
@@ -0,0 +1,1755 @@
+/*
+ * Copyright (c) 2005 Martin Decky
+ * Copyright (c) 2008 Jiri Svoboda
+ * Copyright (c) 2011 Martin Sucha
+ * Copyright (c) 2011 Oleg Romanenko
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup libc
+ * @{
+ */
+/** @file
+ */
+
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <ctype.h>
+#include <malloc.h>
+#include <errno.h>
+#include <limits.h>
+#include <wchar.h>
+#include "align.h"
+#include "assert.h"
+#include "str.h"
+
+/** Check the condition if wchar_t is signed */
+#ifdef WCHAR_IS_UNSIGNED
+	#define WCHAR_SIGNED_CHECK(cond)  (true)
+#else
+	#define WCHAR_SIGNED_CHECK(cond)  (cond)
+#endif
+
+/** Byte mask consisting of lowest @n bits (out of 8) */
+#define LO_MASK_8(n)  ((uint8_t) ((1 << (n)) - 1))
+
+/** Byte mask consisting of lowest @n bits (out of 32) */
+#define LO_MASK_32(n)  ((uint32_t) ((1 << (n)) - 1))
+
+/** Byte mask consisting of highest @n bits (out of 8) */
+#define HI_MASK_8(n)  (~LO_MASK_8(8 - (n)))
+
+/** Number of data bits in a UTF-8 continuation byte */
+#define CONT_BITS  6
+
+/** Decode a single character from a string.
+ *
+ * Decode a single character from a string of size @a size. Decoding starts
+ * at @a offset and this offset is moved to the beginning of the next
+ * character. In case of decoding error, offset generally advances at least
+ * by one. However, offset is never moved beyond size.
+ *
+ * @param str    String (not necessarily NULL-terminated).
+ * @param offset Byte offset in string where to start decoding.
+ * @param size   Size of the string (in bytes).
+ *
+ * @return Value of decoded character, U_SPECIAL on decoding error or
+ *         NULL if attempt to decode beyond @a size.
+ *
+ */
+wchar_t str_decode(const char *str, size_t *offset, size_t size)
+{
+	uint8_t b0;
+	unsigned int b0_bits;  /* Data bits in first byte */
+	unsigned int cbytes;   /* Number of continuation bytes */
+	wchar_t ch;
+
+	if (*offset + 1 > size)
+		return 0;
+	
+	/* First byte read from string */
+	b0 = (uint8_t) str[(*offset)++];
+	
+	/* Determine code length */
+	
+	if ((b0 & 0x80) == 0) {
+		/* 0xxxxxxx (Plain ASCII) */
+		b0_bits = 7;
+		cbytes = 0;
+	} else if ((b0 & 0xe0) == 0xc0) {
+		/* 110xxxxx 10xxxxxx */
+		b0_bits = 5;
+		cbytes = 1;
+	} else if ((b0 & 0xf0) == 0xe0) {
+		/* 1110xxxx 10xxxxxx 10xxxxxx */
+		b0_bits = 4;
+		cbytes = 2;
+	} else if ((b0 & 0xf8) == 0xf0) {
+		/* 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */
+		b0_bits = 3;
+		cbytes = 3;
+	} else {
+		/* 10xxxxxx -- unexpected continuation byte */
+		return U_SPECIAL;
+	}
+	
+	if (*offset + cbytes > size)
+		return U_SPECIAL;
+	
+	ch = b0 & LO_MASK_8(b0_bits);
+	
+	/* Decode continuation bytes */
+	while (cbytes > 0) {
+		uint8_t b = (uint8_t) str[(*offset)++];
+		
+		/* Must be 10xxxxxx */
+		if ((b & 0xc0) != 0x80)
+			return U_SPECIAL;
+		
+		/* Shift data bits to ch */
+		ch = (ch << CONT_BITS) | (wchar_t) (b & LO_MASK_8(CONT_BITS));
+		cbytes--;
+	}
+	
+	return ch;
+}
+
+/** Decode a single character from a string to the left.
+ *
+ * Decode a single character from a string of size @a size. Decoding starts
+ * at @a offset and this offset is moved to the beginning of the previous
+ * character. In case of decoding error, offset generally decreases at least
+ * by one. However, offset is never moved before 0.
+ *
+ * @param str    String (not necessarily NULL-terminated).
+ * @param offset Byte offset in string where to start decoding.
+ * @param size   Size of the string (in bytes).
+ *
+ * @return Value of decoded character, U_SPECIAL on decoding error or
+ *         NULL if attempt to decode beyond @a start of str.
+ *
+ */
+wchar_t str_decode_reverse(const char *str, size_t *offset, size_t size)
+{
+	size_t processed = 0;
+
+	if (*offset == 0)
+		return 0;
+	
+	/* Continue while continuation bytes found */
+	while (*offset > 0 && processed < 4) {
+		uint8_t b = (uint8_t) str[--(*offset)];
+		
+		if (processed == 0 && (b & 0x80) == 0) {
+			/* 0xxxxxxx (Plain ASCII) */
+			return b & 0x7f;
+		}
+		else if ((b & 0xe0) == 0xc0 || (b & 0xf0) == 0xe0 ||
+		    (b & 0xf8) == 0xf0) {
+			/* Start byte */
+			size_t start_offset = *offset;
+			return str_decode(str, &start_offset, size);
+		}
+		else if ((b & 0xc0) != 0x80) {
+			/* Not a continuation byte */
+			return U_SPECIAL;
+		}
+		processed++;
+	}
+	/* Too many continuation bytes */
+	return U_SPECIAL;
+}
+
+/** Encode a single character to string representation.
+ *
+ * Encode a single character to string representation (i.e. UTF-8) and store
+ * it into a buffer at @a offset. Encoding starts at @a offset and this offset
+ * is moved to the position where the next character can be written to.
+ *
+ * @param ch     Input character.
+ * @param str    Output buffer.
+ * @param offset Byte offset where to start writing.
+ * @param size   Size of the output buffer (in bytes).
+ *
+ * @return 0 if the character was encoded successfully, EOVERFLOW if there
+ *         was not enough space in the output buffer or EINVAL if the character
+ *         code was invalid.
+ */
+int chr_encode(const wchar_t ch, char *str, size_t *offset, size_t size)
+{
+	unsigned int i;
+	uint32_t cc = (uint32_t) ch;
+	unsigned int b0_bits;  /* Data bits in first byte */
+	unsigned int cbytes;   /* Number of continuation bytes */
+
+	if (*offset >= size)
+		return EOVERFLOW;
+	
+	if (!chr_check(ch))
+		return EINVAL;
+	
+	/* Unsigned version of ch (bit operations should only be done
+	   on unsigned types). */
+	
+	/* Determine how many continuation bytes are needed */
+	
+	if ((cc & ~LO_MASK_32(7)) == 0) {
+		b0_bits = 7;
+		cbytes = 0;
+	} else if ((cc & ~LO_MASK_32(11)) == 0) {
+		b0_bits = 5;
+		cbytes = 1;
+	} else if ((cc & ~LO_MASK_32(16)) == 0) {
+		b0_bits = 4;
+		cbytes = 2;
+	} else if ((cc & ~LO_MASK_32(21)) == 0) {
+		b0_bits = 3;
+		cbytes = 3;
+	} else {
+		/* Codes longer than 21 bits are not supported */
+		return EINVAL;
+	}
+	
+	/* Check for available space in buffer */
+	if (*offset + cbytes >= size)
+		return EOVERFLOW;
+	
+	/* Encode continuation bytes */
+	for (i = cbytes; i > 0; i--) {
+		str[*offset + i] = 0x80 | (cc & LO_MASK_32(CONT_BITS));
+		cc = cc >> CONT_BITS;
+	}
+	
+	/* Encode first byte */
+	str[*offset] = (cc & LO_MASK_32(b0_bits)) | HI_MASK_8(8 - b0_bits - 1);
+	
+	/* Advance offset */
+	*offset += cbytes + 1;
+	
+	return 0;
+}
+
+/** Get size of string.
+ *
+ * Get the number of bytes which are used by the string @a str (excluding the
+ * NULL-terminator).
+ *
+ * @param str String to consider.
+ *
+ * @return Number of bytes used by the string
+ *
+ */
+size_t str_size(const char *str)
+{
+	size_t size = 0;
+	
+	while (*str++ != 0)
+		size++;
+	
+	return size;
+}
+
+/** Get size of wide string.
+ *
+ * Get the number of bytes which are used by the wide string @a str (excluding the
+ * NULL-terminator).
+ *
+ * @param str Wide string to consider.
+ *
+ * @return Number of bytes used by the wide string
+ *
+ */
+size_t wstr_size(const wchar_t *str)
+{
+	return (wstr_length(str) * sizeof(wchar_t));
+}
+
+/** Get size of string with length limit.
+ *
+ * Get the number of bytes which are used by up to @a max_len first
+ * characters in the string @a str. If @a max_len is greater than
+ * the length of @a str, the entire string is measured (excluding the
+ * NULL-terminator).
+ *
+ * @param str     String to consider.
+ * @param max_len Maximum number of characters to measure.
+ *
+ * @return Number of bytes used by the characters.
+ *
+ */
+size_t str_lsize(const char *str, size_t max_len)
+{
+	size_t len = 0;
+	size_t offset = 0;
+	
+	while (len < max_len) {
+		if (str_decode(str, &offset, STR_NO_LIMIT) == 0)
+			break;
+		
+		len++;
+	}
+	
+	return offset;
+}
+
+/** Get size of string with size limit.
+ *
+ * Get the number of bytes which are used by the string @a str
+ * (excluding the NULL-terminator), but no more than @max_size bytes.
+ *
+ * @param str      String to consider.
+ * @param max_size Maximum number of bytes to measure.
+ *
+ * @return Number of bytes used by the string
+ *
+ */
+size_t str_nsize(const char *str, size_t max_size)
+{
+	size_t size = 0;
+	
+	while ((*str++ != 0) && (size < max_size))
+		size++;
+	
+	return size;
+}
+
+/** Get size of wide string with size limit.
+ *
+ * Get the number of bytes which are used by the wide string @a str
+ * (excluding the NULL-terminator), but no more than @max_size bytes.
+ *
+ * @param str      Wide string to consider.
+ * @param max_size Maximum number of bytes to measure.
+ *
+ * @return Number of bytes used by the wide string
+ *
+ */
+size_t wstr_nsize(const wchar_t *str, size_t max_size)
+{
+	return (wstr_nlength(str, max_size) * sizeof(wchar_t));
+}
+
+/** Get size of wide string with length limit.
+ *
+ * Get the number of bytes which are used by up to @a max_len first
+ * wide characters in the wide string @a str. If @a max_len is greater than
+ * the length of @a str, the entire wide string is measured (excluding the
+ * NULL-terminator).
+ *
+ * @param str     Wide string to consider.
+ * @param max_len Maximum number of wide characters to measure.
+ *
+ * @return Number of bytes used by the wide characters.
+ *
+ */
+size_t wstr_lsize(const wchar_t *str, size_t max_len)
+{
+	return (wstr_nlength(str, max_len * sizeof(wchar_t)) * sizeof(wchar_t));
+}
+
+/** Get number of characters in a string.
+ *
+ * @param str NULL-terminated string.
+ *
+ * @return Number of characters in string.
+ *
+ */
+size_t str_length(const char *str)
+{
+	size_t len = 0;
+	size_t offset = 0;
+	
+	while (str_decode(str, &offset, STR_NO_LIMIT) != 0)
+		len++;
+	
+	return len;
+}
+
+/** Get number of characters in a wide string.
+ *
+ * @param str NULL-terminated wide string.
+ *
+ * @return Number of characters in @a str.
+ *
+ */
+size_t wstr_length(const wchar_t *wstr)
+{
+	size_t len = 0;
+	
+	while (*wstr++ != 0)
+		len++;
+	
+	return len;
+}
+
+/** Get number of characters in a string with size limit.
+ *
+ * @param str  NULL-terminated string.
+ * @param size Maximum number of bytes to consider.
+ *
+ * @return Number of characters in string.
+ *
+ */
+size_t str_nlength(const char *str, size_t size)
+{
+	size_t len = 0;
+	size_t offset = 0;
+	
+	while (str_decode(str, &offset, size) != 0)
+		len++;
+	
+	return len;
+}
+
+/** Get number of characters in a string with size limit.
+ *
+ * @param str  NULL-terminated string.
+ * @param size Maximum number of bytes to consider.
+ *
+ * @return Number of characters in string.
+ *
+ */
+size_t wstr_nlength(const wchar_t *str, size_t size)
+{
+	size_t len = 0;
+	size_t limit = ALIGN_DOWN(size, sizeof(wchar_t));
+	size_t offset = 0;
+	
+	while ((offset < limit) && (*str++ != 0)) {
+		len++;
+		offset += sizeof(wchar_t);
+	}
+	
+	return len;
+}
+
+/** Get character display width on a character cell display.
+ *
+ * @param ch	Character
+ * @return	Width of character in cells.
+ */
+size_t chr_width(wchar_t ch)
+{
+	return 1;
+}
+
+/** Get string display width on a character cell display.
+ *
+ * @param str	String
+ * @return	Width of string in cells.
+ */
+size_t str_width(const char *str)
+{
+	size_t width = 0;
+	size_t offset = 0;
+	wchar_t ch;
+	
+	while ((ch = str_decode(str, &offset, STR_NO_LIMIT)) != 0)
+		width += chr_width(ch);
+	
+	return width;
+}
+
+/** Check whether character is plain ASCII.
+ *
+ * @return True if character is plain ASCII.
+ *
+ */
+bool ascii_check(wchar_t ch)
+{
+	if (WCHAR_SIGNED_CHECK(ch >= 0) && (ch <= 127))
+		return true;
+	
+	return false;
+}
+
+/** Check whether character is valid
+ *
+ * @return True if character is a valid Unicode code point.
+ *
+ */
+bool chr_check(wchar_t ch)
+{
+	if (WCHAR_SIGNED_CHECK(ch >= 0) && (ch <= 1114111))
+		return true;
+	
+	return false;
+}
+
+/** Compare two NULL terminated strings.
+ *
+ * Do a char-by-char comparison of two NULL-terminated strings.
+ * The strings are considered equal iff their length is equal
+ * and both strings consist of the same sequence of characters.
+ *
+ * A string S1 is less than another string S2 if it has a character with
+ * lower value at the first character position where the strings differ.
+ * If the strings differ in length, the shorter one is treated as if
+ * padded by characters with a value of zero.
+ *
+ * @param s1 First string to compare.
+ * @param s2 Second string to compare.
+ *
+ * @return 0 if the strings are equal, -1 if the first is less than the second,
+ *         1 if the second is less than the first.
+ *
+ */
+int str_cmp(const char *s1, const char *s2)
+{
+	wchar_t c1 = 0;
+	wchar_t c2 = 0;
+	
+	size_t off1 = 0;
+	size_t off2 = 0;
+
+	while (true) {
+		c1 = str_decode(s1, &off1, STR_NO_LIMIT);
+		c2 = str_decode(s2, &off2, STR_NO_LIMIT);
+
+		if (c1 < c2)
+			return -1;
+		
+		if (c1 > c2)
+			return 1;
+
+		if (c1 == 0 || c2 == 0)
+			break;		
+	}
+
+	return 0;
+}
+
+/** Compare two NULL terminated strings with length limit.
+ *
+ * Do a char-by-char comparison of two NULL-terminated strings.
+ * The strings are considered equal iff
+ * min(str_length(s1), max_len) == min(str_length(s2), max_len)
+ * and both strings consist of the same sequence of characters,
+ * up to max_len characters.
+ *
+ * A string S1 is less than another string S2 if it has a character with
+ * lower value at the first character position where the strings differ.
+ * If the strings differ in length, the shorter one is treated as if
+ * padded by characters with a value of zero. Only the first max_len
+ * characters are considered.
+ *
+ * @param s1      First string to compare.
+ * @param s2      Second string to compare.
+ * @param max_len Maximum number of characters to consider.
+ *
+ * @return 0 if the strings are equal, -1 if the first is less than the second,
+ *         1 if the second is less than the first.
+ *
+ */
+int str_lcmp(const char *s1, const char *s2, size_t max_len)
+{
+	wchar_t c1 = 0;
+	wchar_t c2 = 0;
+	
+	size_t off1 = 0;
+	size_t off2 = 0;
+	
+	size_t len = 0;
+
+	while (true) {
+		if (len >= max_len)
+			break;
+
+		c1 = str_decode(s1, &off1, STR_NO_LIMIT);
+		c2 = str_decode(s2, &off2, STR_NO_LIMIT);
+
+		if (c1 < c2)
+			return -1;
+
+		if (c1 > c2)
+			return 1;
+
+		if (c1 == 0 || c2 == 0)
+			break;
+
+		++len;	
+	}
+
+	return 0;
+
+}
+
+/** Test whether p is a prefix of s.
+ *
+ * Do a char-by-char comparison of two NULL-terminated strings
+ * and determine if p is a prefix of s.
+ *
+ * @param s The string in which to look
+ * @param p The string to check if it is a prefix of s
+ *
+ * @return true iff p is prefix of s else false
+ *
+ */
+bool str_test_prefix(const char *s, const char *p)
+{
+	wchar_t c1 = 0;
+	wchar_t c2 = 0;
+	
+	size_t off1 = 0;
+	size_t off2 = 0;
+
+	while (true) {
+		c1 = str_decode(s, &off1, STR_NO_LIMIT);
+		c2 = str_decode(p, &off2, STR_NO_LIMIT);
+		
+		if (c2 == 0)
+			return true;
+
+		if (c1 != c2)
+			return false;
+		
+		if (c1 == 0)
+			break;
+	}
+
+	return false;
+}
+
+/** Copy string.
+ *
+ * Copy source string @a src to destination buffer @a dest.
+ * No more than @a size bytes are written. If the size of the output buffer
+ * is at least one byte, the output string will always be well-formed, i.e.
+ * null-terminated and containing only complete characters.
+ *
+ * @param dest  Destination buffer.
+ * @param count Size of the destination buffer (must be > 0).
+ * @param src   Source string.
+ *
+ */
+void str_cpy(char *dest, size_t size, const char *src)
+{
+	/* There must be space for a null terminator in the buffer. */
+	size_t src_off = 0;
+	size_t dest_off = 0;
+	wchar_t ch;
+
+	assert(size > 0);
+
+	while ((ch = str_decode(src, &src_off, STR_NO_LIMIT)) != 0) {
+		if (chr_encode(ch, dest, &dest_off, size - 1) != 0)
+			break;
+	}
+	
+	dest[dest_off] = '\0';
+}
+
+/** Copy size-limited substring.
+ *
+ * Copy prefix of string @a src of max. size @a size to destination buffer
+ * @a dest. No more than @a size bytes are written. The output string will
+ * always be well-formed, i.e. null-terminated and containing only complete
+ * characters.
+ *
+ * No more than @a n bytes are read from the input string, so it does not
+ * have to be null-terminated.
+ *
+ * @param dest  Destination buffer.
+ * @param count Size of the destination buffer (must be > 0).
+ * @param src   Source string.
+ * @param n     Maximum number of bytes to read from @a src.
+ *
+ */
+void str_ncpy(char *dest, size_t size, const char *src, size_t n)
+{
+	/* There must be space for a null terminator in the buffer. */
+	size_t src_off = 0;
+	size_t dest_off = 0;
+	wchar_t ch;
+
+	assert(size > 0);
+
+	while ((ch = str_decode(src, &src_off, n)) != 0) {
+		if (chr_encode(ch, dest, &dest_off, size - 1) != 0)
+			break;
+	}
+	
+	dest[dest_off] = '\0';
+}
+
+/** Append one string to another.
+ *
+ * Append source string @a src to string in destination buffer @a dest.
+ * Size of the destination buffer is @a dest. If the size of the output buffer
+ * is at least one byte, the output string will always be well-formed, i.e.
+ * null-terminated and containing only complete characters.
+ *
+ * @param dest   Destination buffer.
+ * @param count Size of the destination buffer.
+ * @param src   Source string.
+ */
+void str_append(char *dest, size_t size, const char *src)
+{
+	size_t dstr_size;
+
+	dstr_size = str_size(dest);
+	if (dstr_size >= size)
+		return;
+	
+	str_cpy(dest + dstr_size, size - dstr_size, src);
+}
+
+/** Convert space-padded ASCII to string.
+ *
+ * Common legacy text encoding in hardware is 7-bit ASCII fitted into
+ * a fixed-width byte buffer (bit 7 always zero), right-padded with spaces
+ * (ASCII 0x20). Convert space-padded ascii to string representation.
+ *
+ * If the text does not fit into the destination buffer, the function converts
+ * as many characters as possible and returns EOVERFLOW.
+ *
+ * If the text contains non-ASCII bytes (with bit 7 set), the whole string is
+ * converted anyway and invalid characters are replaced with question marks
+ * (U_SPECIAL) and the function returns EIO.
+ *
+ * Regardless of return value upon return @a dest will always be well-formed.
+ *
+ * @param dest		Destination buffer
+ * @param size		Size of destination buffer
+ * @param src		Space-padded ASCII.
+ * @param n		Size of the source buffer in bytes.
+ *
+ * @return		0 on success, EOVERFLOW if the text does not fit
+ *			destination buffer, EIO if the text contains
+ *			non-ASCII bytes.
+ */
+int spascii_to_str(char *dest, size_t size, const uint8_t *src, size_t n)
+{
+	size_t sidx;
+	size_t didx;
+	size_t dlast;
+	uint8_t byte;
+	int rc;
+	int result;
+
+	/* There must be space for a null terminator in the buffer. */
+	assert(size > 0);
+	result = 0;
+
+	didx = 0;
+	dlast = 0;
+	for (sidx = 0; sidx < n; ++sidx) {
+		byte = src[sidx];
+		if (!ascii_check(byte)) {
+			byte = U_SPECIAL;
+			result = EIO;
+		}
+
+		rc = chr_encode(byte, dest, &didx, size - 1);
+		if (rc != 0) {
+			assert(rc == EOVERFLOW);
+			dest[didx] = '\0';
+			return rc;
+		}
+
+		/* Remember dest index after last non-empty character */
+		if (byte != 0x20)
+			dlast = didx;
+	}
+
+	/* Terminate string after last non-empty character */
+	dest[dlast] = '\0';
+	return result;
+}
+
+/** Convert wide string to string.
+ *
+ * Convert wide string @a src to string. The output is written to the buffer
+ * specified by @a dest and @a size. @a size must be non-zero and the string
+ * written will always be well-formed.
+ *
+ * @param dest	Destination buffer.
+ * @param size	Size of the destination buffer.
+ * @param src	Source wide string.
+ */
+void wstr_to_str(char *dest, size_t size, const wchar_t *src)
+{
+	wchar_t ch;
+	size_t src_idx;
+	size_t dest_off;
+
+	/* There must be space for a null terminator in the buffer. */
+	assert(size > 0);
+	
+	src_idx = 0;
+	dest_off = 0;
+
+	while ((ch = src[src_idx++]) != 0) {
+		if (chr_encode(ch, dest, &dest_off, size - 1) != 0)
+			break;
+	}
+
+	dest[dest_off] = '\0';
+}
+
+/** Convert UTF16 string to string.
+ *
+ * Convert utf16 string @a src to string. The output is written to the buffer
+ * specified by @a dest and @a size. @a size must be non-zero and the string
+ * written will always be well-formed. Surrogate pairs also supported.
+ *
+ * @param dest	Destination buffer.
+ * @param size	Size of the destination buffer.
+ * @param src	Source utf16 string.
+ *
+ * @return 0, if success, negative otherwise.
+ */
+int utf16_to_str(char *dest, size_t size, const uint16_t *src)
+{
+	size_t idx = 0, dest_off = 0;
+	wchar_t ch;
+	int rc = 0;
+
+	/* There must be space for a null terminator in the buffer. */
+	assert(size > 0);
+
+	while (src[idx]) {
+		if ((src[idx] & 0xfc00) == 0xd800) {
+			if (src[idx + 1] && (src[idx + 1] & 0xfc00) == 0xdc00) {
+				ch = 0x10000;
+				ch += (src[idx] & 0x03FF) << 10;
+				ch += (src[idx + 1] & 0x03FF);
+				idx += 2;
+			}
+			else
+				break;
+		} else {
+			ch = src[idx];
+			idx++;
+		}
+		rc = chr_encode(ch, dest, &dest_off, size - 1);
+		if (rc != 0)
+			break;
+	}
+	dest[dest_off] = '\0';
+	return rc;
+}
+
+int str_to_utf16(uint16_t *dest, size_t size, const char *src)
+{
+	int rc = 0;
+	size_t offset = 0;
+	size_t idx = 0;
+	wchar_t c;
+
+	assert(size > 0);
+	
+	while ((c = str_decode(src, &offset, STR_NO_LIMIT)) != 0) {
+		if (c > 0x10000) {
+			if (idx + 2 >= size - 1) {
+				rc = EOVERFLOW;
+				break;
+			}
+			c = (c - 0x10000);
+			dest[idx] = 0xD800 | (c >> 10);
+			dest[idx + 1] = 0xDC00 | (c & 0x3FF);
+			idx++;
+		} else {
+			 dest[idx] = c;
+		}
+
+		idx++;
+		if (idx >= size - 1) {
+			rc = EOVERFLOW;
+			break;
+		}
+	}
+
+	dest[idx] = '\0';
+	return rc;
+}
+
+
+/** Convert wide string to new string.
+ *
+ * Convert wide string @a src to string. Space for the new string is allocated
+ * on the heap.
+ *
+ * @param src	Source wide string.
+ * @return	New string.
+ */
+char *wstr_to_astr(const wchar_t *src)
+{
+	char dbuf[STR_BOUNDS(1)];
+	char *str;
+	wchar_t ch;
+
+	size_t src_idx;
+	size_t dest_off;
+	size_t dest_size;
+
+	/* Compute size of encoded string. */
+
+	src_idx = 0;
+	dest_size = 0;
+
+	while ((ch = src[src_idx++]) != 0) {
+		dest_off = 0;
+		if (chr_encode(ch, dbuf, &dest_off, STR_BOUNDS(1)) != 0)
+			break;
+		dest_size += dest_off;
+	}
+
+	str = malloc(dest_size + 1);
+	if (str == NULL)
+		return NULL;
+
+	/* Encode string. */
+
+	src_idx = 0;
+	dest_off = 0;
+
+	while ((ch = src[src_idx++]) != 0) {
+		if (chr_encode(ch, str, &dest_off, dest_size) != 0)
+			break;
+	}
+
+	str[dest_size] = '\0';
+	return str;
+}
+
+
+/** Convert string to wide string.
+ *
+ * Convert string @a src to wide string. The output is written to the
+ * buffer specified by @a dest and @a dlen. @a dlen must be non-zero
+ * and the wide string written will always be null-terminated.
+ *
+ * @param dest	Destination buffer.
+ * @param dlen	Length of destination buffer (number of wchars).
+ * @param src	Source string.
+ */
+void str_to_wstr(wchar_t *dest, size_t dlen, const char *src)
+{
+	size_t offset;
+	size_t di;
+	wchar_t c;
+
+	assert(dlen > 0);
+
+	offset = 0;
+	di = 0;
+
+	do {
+		if (di >= dlen - 1)
+			break;
+
+		c = str_decode(src, &offset, STR_NO_LIMIT);
+		dest[di++] = c;
+	} while (c != '\0');
+
+	dest[dlen - 1] = '\0';
+}
+
+/** Convert string to wide string.
+ *
+ * Convert string @a src to wide string. A new wide NULL-terminated
+ * string will be allocated on the heap.
+ *
+ * @param src	Source string.
+ */
+wchar_t *str_to_awstr(const char *str)
+{
+	size_t len = str_length(str);
+	
+	wchar_t *wstr = calloc(len+1, sizeof(wchar_t));
+	if (wstr == NULL)
+		return NULL;
+	
+	str_to_wstr(wstr, len + 1, str);
+	return wstr;
+}
+
+/** Find first occurence of character in string.
+ *
+ * @param str String to search.
+ * @param ch  Character to look for.
+ *
+ * @return Pointer to character in @a str or NULL if not found.
+ */
+char *str_chr(const char *str, wchar_t ch)
+{
+	wchar_t acc;
+	size_t off = 0;
+	size_t last = 0;
+	
+	while ((acc = str_decode(str, &off, STR_NO_LIMIT)) != 0) {
+		if (acc == ch)
+			return (char *) (str + last);
+		last = off;
+	}
+	
+	return NULL;
+}
+
+/** Removes specified trailing characters from a string.
+ *
+ * @param str String to remove from.
+ * @param ch  Character to remove.
+ */
+void str_rtrim(char *str, wchar_t ch)
+{
+	size_t off = 0;
+	size_t pos = 0;
+	wchar_t c;
+	bool update_last_chunk = true;
+	char *last_chunk = NULL;
+
+	while ((c = str_decode(str, &off, STR_NO_LIMIT))) {
+		if (c != ch) {
+			update_last_chunk = true;
+			last_chunk = NULL;
+		} else if (update_last_chunk) {
+			update_last_chunk = false;
+			last_chunk = (str + pos);
+		}
+		pos = off;
+	}
+
+	if (last_chunk)
+		*last_chunk = '\0';
+}
+
+/** Removes specified leading characters from a string.
+ *
+ * @param str String to remove from.
+ * @param ch  Character to remove.
+ */
+void str_ltrim(char *str, wchar_t ch)
+{
+	wchar_t acc;
+	size_t off = 0;
+	size_t pos = 0;
+	size_t str_sz = str_size(str);
+
+	while ((acc = str_decode(str, &off, STR_NO_LIMIT)) != 0) {
+		if (acc != ch)
+			break;
+		else
+			pos = off;
+	}
+
+	if (pos > 0) {
+		memmove(str, &str[pos], str_sz - pos);
+		pos = str_sz - pos;
+		str[str_sz - pos] = '\0';
+	}
+}
+
+/** Find last occurence of character in string.
+ *
+ * @param str String to search.
+ * @param ch  Character to look for.
+ *
+ * @return Pointer to character in @a str or NULL if not found.
+ */
+char *str_rchr(const char *str, wchar_t ch)
+{
+	wchar_t acc;
+	size_t off = 0;
+	size_t last = 0;
+	const char *res = NULL;
+	
+	while ((acc = str_decode(str, &off, STR_NO_LIMIT)) != 0) {
+		if (acc == ch)
+			res = (str + last);
+		last = off;
+	}
+	
+	return (char *) res;
+}
+
+/** Insert a wide character into a wide string.
+ *
+ * Insert a wide character into a wide string at position
+ * @a pos. The characters after the position are shifted.
+ *
+ * @param str     String to insert to.
+ * @param ch      Character to insert to.
+ * @param pos     Character index where to insert.
+ @ @param max_pos Characters in the buffer.
+ *
+ * @return True if the insertion was sucessful, false if the position
+ *         is out of bounds.
+ *
+ */
+bool wstr_linsert(wchar_t *str, wchar_t ch, size_t pos, size_t max_pos)
+{
+	size_t len = wstr_length(str);
+	size_t i;
+	
+	if ((pos > len) || (pos + 1 > max_pos))
+		return false;
+	
+	for (i = len; i + 1 > pos; i--)
+		str[i + 1] = str[i];
+	
+	str[pos] = ch;
+	
+	return true;
+}
+
+/** Remove a wide character from a wide string.
+ *
+ * Remove a wide character from a wide string at position
+ * @a pos. The characters after the position are shifted.
+ *
+ * @param str String to remove from.
+ * @param pos Character index to remove.
+ *
+ * @return True if the removal was sucessful, false if the position
+ *         is out of bounds.
+ *
+ */
+bool wstr_remove(wchar_t *str, size_t pos)
+{
+	size_t len = wstr_length(str);
+	size_t i;
+	
+	if (pos >= len)
+		return false;
+	
+	for (i = pos + 1; i <= len; i++)
+		str[i - 1] = str[i];
+	
+	return true;
+}
+
+int stricmp(const char *a, const char *b)
+{
+	int c = 0;
+	
+	while (a[c] && b[c] && (!(tolower(a[c]) - tolower(b[c]))))
+		c++;
+	
+	return (tolower(a[c]) - tolower(b[c]));
+}
+
+/** Convert string to a number. 
+ * Core of strtol and strtoul functions.
+ *
+ * @param nptr		Pointer to string.
+ * @param endptr	If not NULL, function stores here pointer to the first
+ * 			invalid character.
+ * @param base		Zero or number between 2 and 36 inclusive.
+ * @param sgn		It's set to 1 if minus found.
+ * @return		Result of conversion.
+ */
+static unsigned long
+_strtoul(const char *nptr, char **endptr, int base, char *sgn)
+{
+	unsigned char c;
+	unsigned long result = 0;
+	unsigned long a, b;
+	const char *str = nptr;
+	const char *tmpptr;
+	
+	while (isspace(*str))
+		str++;
+	
+	if (*str == '-') {
+		*sgn = 1;
+		++str;
+	} else if (*str == '+')
+		++str;
+	
+	if (base) {
+		if ((base == 1) || (base > 36)) {
+			/* FIXME: set errno to EINVAL */
+			return 0;
+		}
+		if ((base == 16) && (*str == '0') && ((str[1] == 'x') ||
+		    (str[1] == 'X'))) {
+			str += 2;
+		}
+	} else {
+		base = 10;
+		
+		if (*str == '0') {
+			base = 8;
+			if ((str[1] == 'X') || (str[1] == 'x'))  {
+				base = 16;
+				str += 2;
+			}
+		} 
+	}
+	
+	tmpptr = str;
+
+	while (*str) {
+		c = *str;
+		c = (c >= 'a' ? c - 'a' + 10 : (c >= 'A' ? c - 'A' + 10 :
+		    (c <= '9' ? c - '0' : 0xff)));
+		if (c >= base) {
+			break;
+		}
+		
+		a = (result & 0xff) * base + c;
+		b = (result >> 8) * base + (a >> 8);
+		
+		if (b > (ULONG_MAX >> 8)) {
+			/* overflow */
+			/* FIXME: errno = ERANGE*/
+			return ULONG_MAX;
+		}
+	
+		result = (b << 8) + (a & 0xff);
+		++str;
+	}
+	
+	if (str == tmpptr) {
+		/*
+		 * No number was found => first invalid character is the first
+		 * character of the string.
+		 */
+		/* FIXME: set errno to EINVAL */
+		str = nptr;
+		result = 0;
+	}
+	
+	if (endptr)
+		*endptr = (char *) str;
+
+	if (nptr == str) { 
+		/*FIXME: errno = EINVAL*/
+		return 0;
+	}
+
+	return result;
+}
+
+/** Convert initial part of string to long int according to given base.
+ * The number may begin with an arbitrary number of whitespaces followed by
+ * optional sign (`+' or `-'). If the base is 0 or 16, the prefix `0x' may be
+ * inserted and the number will be taken as hexadecimal one. If the base is 0
+ * and the number begin with a zero, number will be taken as octal one (as with
+ * base 8). Otherwise the base 0 is taken as decimal.
+ *
+ * @param nptr		Pointer to string.
+ * @param endptr	If not NULL, function stores here pointer to the first
+ * 			invalid character.
+ * @param base		Zero or number between 2 and 36 inclusive.
+ * @return		Result of conversion.
+ */
+long int strtol(const char *nptr, char **endptr, int base)
+{
+	char sgn = 0;
+	unsigned long number = 0;
+	
+	number = _strtoul(nptr, endptr, base, &sgn);
+
+	if (number > LONG_MAX) {
+		if ((sgn) && (number == (unsigned long) (LONG_MAX) + 1)) {
+			/* FIXME: set 0 to errno */
+			return number;		
+		}
+		/* FIXME: set ERANGE to errno */
+		return (sgn ? LONG_MIN : LONG_MAX);	
+	}
+	
+	return (sgn ? -number : number);
+}
+
+/** Convert initial part of string to unsigned long according to given base.
+ * The number may begin with an arbitrary number of whitespaces followed by
+ * optional sign (`+' or `-'). If the base is 0 or 16, the prefix `0x' may be
+ * inserted and the number will be taken as hexadecimal one. If the base is 0
+ * and the number begin with a zero, number will be taken as octal one (as with
+ * base 8). Otherwise the base 0 is taken as decimal.
+ *
+ * @param nptr		Pointer to string.
+ * @param endptr	If not NULL, function stores here pointer to the first
+ * 			invalid character
+ * @param base		Zero or number between 2 and 36 inclusive.
+ * @return		Result of conversion.
+ */
+unsigned long strtoul(const char *nptr, char **endptr, int base)
+{
+	char sgn = 0;
+	unsigned long number = 0;
+	
+	number = _strtoul(nptr, endptr, base, &sgn);
+
+	return (sgn ? -number : number);
+}
+
+char *strtok(char *s, const char *delim)
+{
+	static char *next;
+
+	return strtok_r(s, delim, &next);
+}
+
+char *strtok_r(char *s, const char *delim, char **next)
+{
+	char *start, *end;
+
+	if (s == NULL)
+		s = *next;
+
+	/* Skip over leading delimiters. */
+	while (*s && (str_chr(delim, *s) != NULL)) ++s;
+	start = s;
+
+	/* Skip over token characters. */
+	while (*s && (str_chr(delim, *s) == NULL)) ++s;
+	end = s;
+	*next = (*s ? s + 1 : s);
+
+	if (start == end) {
+		return NULL;	/* No more tokens. */
+	}
+
+	/* Overwrite delimiter with NULL terminator. */
+	*end = '\0';
+	return start;
+}
+
+/** Convert string to uint64_t (internal variant).
+ *
+ * @param nptr   Pointer to string.
+ * @param endptr Pointer to the first invalid character is stored here.
+ * @param base   Zero or number between 2 and 36 inclusive.
+ * @param neg    Indication of unary minus is stored here.
+ * @apram result Result of the conversion.
+ *
+ * @return 0 if conversion was successful.
+ *
+ */
+static int str_uint(const char *nptr, char **endptr, unsigned int base,
+    bool *neg, uint64_t *result)
+{
+	const char *str = nptr;
+	const char *startstr;
+
+	assert(endptr != NULL);
+	assert(neg != NULL);
+	assert(result != NULL);
+	
+	*neg = false;
+	
+	/* Ignore leading whitespace */
+	while (isspace(*str))
+		str++;
+	
+	if (*str == '-') {
+		*neg = true;
+		str++;
+	} else if (*str == '+')
+		str++;
+	
+	if (base == 0) {
+		/* Decode base if not specified */
+		base = 10;
+		
+		if (*str == '0') {
+			base = 8;
+			str++;
+			
+			switch (*str) {
+			case 'b':
+			case 'B':
+				base = 2;
+				str++;
+				break;
+			case 'o':
+			case 'O':
+				base = 8;
+				str++;
+				break;
+			case 'd':
+			case 'D':
+			case 't':
+			case 'T':
+				base = 10;
+				str++;
+				break;
+			case 'x':
+			case 'X':
+				base = 16;
+				str++;
+				break;
+			default:
+				str--;
+			}
+		}
+	} else {
+		/* Check base range */
+		if ((base < 2) || (base > 36)) {
+			*endptr = (char *) str;
+			return EINVAL;
+		}
+	}
+	
+	*result = 0;
+	startstr = str;
+	
+	while (*str != 0) {
+		unsigned int digit;
+		uint64_t prev;
+		
+		if ((*str >= 'a') && (*str <= 'z'))
+			digit = *str - 'a' + 10;
+		else if ((*str >= 'A') && (*str <= 'Z'))
+			digit = *str - 'A' + 10;
+		else if ((*str >= '0') && (*str <= '9'))
+			digit = *str - '0';
+		else
+			break;
+		
+		if (digit >= base)
+			break;
+		
+		prev = *result;
+		*result = (*result) * base + digit;
+		
+		if (*result < prev) {
+			/* Overflow */
+			*endptr = (char *) str;
+			return EOVERFLOW;
+		}
+		
+		str++;
+	}
+	
+	if (str == startstr) {
+		/*
+		 * No digits were decoded => first invalid character is
+		 * the first character of the string.
+		 */
+		str = nptr;
+	}
+	
+	*endptr = (char *) str;
+	
+	if (str == nptr)
+		return EINVAL;
+	
+	return 0;
+}
+
+/** Convert string to uint8_t.
+ *
+ * @param nptr   Pointer to string.
+ * @param endptr If not NULL, pointer to the first invalid character
+ *               is stored here.
+ * @param base   Zero or number between 2 and 36 inclusive.
+ * @param strict Do not allow any trailing characters.
+ * @param result Result of the conversion.
+ *
+ * @return 0 if conversion was successful.
+ *
+ */
+int str_uint8_t(const char *nptr, char **endptr, unsigned int base,
+    bool strict, uint8_t *result)
+{
+	bool neg;
+	char *lendptr;
+	uint64_t res;
+	int ret;
+	uint8_t _res;
+
+	assert(result != NULL);
+
+	ret = str_uint(nptr, &lendptr, base, &neg, &res);
+	
+	if (endptr != NULL)
+		*endptr = (char *) lendptr;
+	
+	if (ret != 0)
+		return ret;
+	
+	/* Do not allow negative values */
+	if (neg)
+		return EINVAL;
+	
+	/* Check whether we are at the end of
+	   the string in strict mode */
+	if ((strict) && (*lendptr != 0))
+		return EINVAL;
+	
+	/* Check for overflow */
+	_res = (uint8_t) res;
+	if (_res != res)
+		return EOVERFLOW;
+	
+	*result = _res;
+	
+	return 0;
+}
+
+/** Convert string to uint16_t.
+ *
+ * @param nptr   Pointer to string.
+ * @param endptr If not NULL, pointer to the first invalid character
+ *               is stored here.
+ * @param base   Zero or number between 2 and 36 inclusive.
+ * @param strict Do not allow any trailing characters.
+ * @param result Result of the conversion.
+ *
+ * @return 0 if conversion was successful.
+ *
+ */
+int str_uint16_t(const char *nptr, char **endptr, unsigned int base,
+    bool strict, uint16_t *result)
+{
+	bool neg;
+	char *lendptr;
+	uint64_t res;
+	int ret;
+	uint16_t _res;
+
+	assert(result != NULL);
+
+	ret = str_uint(nptr, &lendptr, base, &neg, &res);
+	
+	if (endptr != NULL)
+		*endptr = (char *) lendptr;
+	
+	if (ret != 0)
+		return ret;
+	
+	/* Do not allow negative values */
+	if (neg)
+		return EINVAL;
+	
+	/* Check whether we are at the end of
+	   the string in strict mode */
+	if ((strict) && (*lendptr != 0))
+		return EINVAL;
+	
+	/* Check for overflow */
+	_res = (uint16_t) res;
+	if (_res != res)
+		return EOVERFLOW;
+	
+	*result = _res;
+	
+	return 0;
+}
+
+/** Convert string to uint32_t.
+ *
+ * @param nptr   Pointer to string.
+ * @param endptr If not NULL, pointer to the first invalid character
+ *               is stored here.
+ * @param base   Zero or number between 2 and 36 inclusive.
+ * @param strict Do not allow any trailing characters.
+ * @param result Result of the conversion.
+ *
+ * @return 0 if conversion was successful.
+ *
+ */
+int str_uint32_t(const char *nptr, char **endptr, unsigned int base,
+    bool strict, uint32_t *result)
+{
+	bool neg;
+	char *lendptr;
+	uint64_t res;
+	int ret;
+	uint32_t _res;
+
+	assert(result != NULL);
+
+	ret = str_uint(nptr, &lendptr, base, &neg, &res);
+	
+	if (endptr != NULL)
+		*endptr = (char *) lendptr;
+	
+	if (ret != 0)
+		return ret;
+	
+	/* Do not allow negative values */
+	if (neg)
+		return EINVAL;
+	
+	/* Check whether we are at the end of
+	   the string in strict mode */
+	if ((strict) && (*lendptr != 0))
+		return EINVAL;
+	
+	/* Check for overflow */
+	_res = (uint32_t) res;
+	if (_res != res)
+		return EOVERFLOW;
+	
+	*result = _res;
+	
+	return 0;
+}
+
+/** Convert string to uint64_t.
+ *
+ * @param nptr   Pointer to string.
+ * @param endptr If not NULL, pointer to the first invalid character
+ *               is stored here.
+ * @param base   Zero or number between 2 and 36 inclusive.
+ * @param strict Do not allow any trailing characters.
+ * @param result Result of the conversion.
+ *
+ * @return 0 if conversion was successful.
+ *
+ */
+int str_uint64_t(const char *nptr, char **endptr, unsigned int base,
+    bool strict, uint64_t *result)
+{
+	bool neg;
+	char *lendptr;
+	int ret;
+
+	assert(result != NULL);
+	
+	ret = str_uint(nptr, &lendptr, base, &neg, result);
+	
+	if (endptr != NULL)
+		*endptr = (char *) lendptr;
+	
+	if (ret != 0)
+		return ret;
+	
+	/* Do not allow negative values */
+	if (neg)
+		return EINVAL;
+	
+	/* Check whether we are at the end of
+	   the string in strict mode */
+	if ((strict) && (*lendptr != 0))
+		return EINVAL;
+	
+	return 0;
+}
+
+/** Convert string to size_t.
+ *
+ * @param nptr   Pointer to string.
+ * @param endptr If not NULL, pointer to the first invalid character
+ *               is stored here.
+ * @param base   Zero or number between 2 and 36 inclusive.
+ * @param strict Do not allow any trailing characters.
+ * @param result Result of the conversion.
+ *
+ * @return 0 if conversion was successful.
+ *
+ */
+int str_size_t(const char *nptr, char **endptr, unsigned int base,
+    bool strict, size_t *result)
+{
+	bool neg;
+	char *lendptr;
+	uint64_t res;
+	int ret;
+	size_t _res;
+
+	assert(result != NULL);
+	
+	ret = str_uint(nptr, &lendptr, base, &neg, &res);
+	
+	if (endptr != NULL)
+		*endptr = (char *) lendptr;
+	
+	if (ret != 0)
+		return ret;
+	
+	/* Do not allow negative values */
+	if (neg)
+		return EINVAL;
+	
+	/* Check whether we are at the end of
+	   the string in strict mode */
+	if ((strict) && (*lendptr != 0))
+		return EINVAL;
+	
+	/* Check for overflow */
+	_res = (size_t) res;
+	if (_res != res)
+		return EOVERFLOW;
+	
+	*result = _res;
+	
+	return 0;
+}
+
+void order_suffix(const uint64_t val, uint64_t *rv, char *suffix)
+{
+	if (val > UINT64_C(10000000000000000000)) {
+		*rv = val / UINT64_C(1000000000000000000);
+		*suffix = 'Z';
+	} else if (val > UINT64_C(1000000000000000000)) {
+		*rv = val / UINT64_C(1000000000000000);
+		*suffix = 'E';
+	} else if (val > UINT64_C(1000000000000000)) {
+		*rv = val / UINT64_C(1000000000000);
+		*suffix = 'T';
+	} else if (val > UINT64_C(1000000000000)) {
+		*rv = val / UINT64_C(1000000000);
+		*suffix = 'G';
+	} else if (val > UINT64_C(1000000000)) {
+		*rv = val / UINT64_C(1000000);
+		*suffix = 'M';
+	} else if (val > UINT64_C(1000000)) {
+		*rv = val / UINT64_C(1000);
+		*suffix = 'k';
+	} else {
+		*rv = val;
+		*suffix = ' ';
+	}
+}
+
+void bin_order_suffix(const uint64_t val, uint64_t *rv, const char **suffix,
+    bool fixed)
+{
+	if (val > UINT64_C(1152921504606846976)) {
+		*rv = val / UINT64_C(1125899906842624);
+		*suffix = "EiB";
+	} else if (val > UINT64_C(1125899906842624)) {
+		*rv = val / UINT64_C(1099511627776);
+		*suffix = "TiB";
+	} else if (val > UINT64_C(1099511627776)) {
+		*rv = val / UINT64_C(1073741824);
+		*suffix = "GiB";
+	} else if (val > UINT64_C(1073741824)) {
+		*rv = val / UINT64_C(1048576);
+		*suffix = "MiB";
+	} else if (val > UINT64_C(1048576)) {
+		*rv = val / UINT64_C(1024);
+		*suffix = "KiB";
+	} else {
+		*rv = val;
+		if (fixed)
+			*suffix = "B  ";
+		else
+			*suffix = "B";
+	}
+}
+
+/** @}
+ */
diff --git a/apps/libc/helenos/str.h b/apps/libc/helenos/str.h
new file mode 100644
index 0000000..f114543
--- /dev/null
+++ b/apps/libc/helenos/str.h
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2005 Martin Decky
+ * Copyright (c) 2011 Oleg Romanenko
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup libc
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBC_STR_H_
+#define LIBC_STR_H_
+
+#include <sys/types.h>
+#include <stdbool.h>
+#include <wchar.h>
+
+#define U_SPECIAL  '?'
+
+/** No size limit constant */
+#define STR_NO_LIMIT  ((size_t) -1)
+
+/** Maximum size of a string containing @c length characters */
+#define STR_BOUNDS(length)  ((length) << 2)
+
+/**
+ * Maximum size of a buffer needed to a string converted from space-padded
+ * ASCII of size @a spa_size using spascii_to_str().
+ */
+#define SPASCII_STR_BUFSIZE(spa_size) ((spa_size) + 1)
+
+extern wchar_t str_decode(const char *str, size_t *offset, size_t sz);
+extern wchar_t str_decode_reverse(const char *str, size_t *offset, size_t sz);
+extern int chr_encode(const wchar_t ch, char *str, size_t *offset, size_t sz);
+
+extern size_t str_size(const char *str);
+extern size_t wstr_size(const wchar_t *str);
+
+extern size_t str_nsize(const char *str, size_t max_size);
+extern size_t wstr_nsize(const wchar_t *str, size_t max_size);
+
+extern size_t str_lsize(const char *str, size_t max_len);
+extern size_t wstr_lsize(const wchar_t *str, size_t max_len);
+
+extern size_t str_length(const char *str);
+extern size_t wstr_length(const wchar_t *wstr);
+
+extern size_t str_nlength(const char *str, size_t size);
+extern size_t wstr_nlength(const wchar_t *str, size_t size);
+
+extern size_t chr_width(wchar_t ch);
+extern size_t str_width(const char *str);
+
+extern bool ascii_check(wchar_t ch);
+extern bool chr_check(wchar_t ch);
+
+extern int str_cmp(const char *s1, const char *s2);
+extern int str_lcmp(const char *s1, const char *s2, size_t max_len);
+
+extern bool str_test_prefix(const char *s, const char *p);
+
+extern void str_cpy(char *dest, size_t size, const char *src);
+extern void str_ncpy(char *dest, size_t size, const char *src, size_t n);
+extern void str_append(char *dest, size_t size, const char *src);
+
+extern int spascii_to_str(char *dest, size_t size, const uint8_t *src, size_t n);
+extern void wstr_to_str(char *dest, size_t size, const wchar_t *src);
+extern char *wstr_to_astr(const wchar_t *src);
+extern void str_to_wstr(wchar_t *dest, size_t dlen, const char *src);
+extern wchar_t *str_to_awstr(const char *src);
+extern int utf16_to_str(char *dest, size_t size, const uint16_t *src);
+extern int str_to_utf16(uint16_t *dest, size_t size, const char *src);
+
+extern char *str_chr(const char *str, wchar_t ch);
+extern char *str_rchr(const char *str, wchar_t ch);
+
+extern void str_rtrim(char *str, wchar_t ch);
+extern void str_ltrim(char *str, wchar_t ch);
+
+extern bool wstr_linsert(wchar_t *str, wchar_t ch, size_t pos, size_t max_pos);
+extern bool wstr_remove(wchar_t *str, size_t pos);
+
+extern char *str_dup(const char *);
+extern char *str_ndup(const char *, size_t max_size);
+
+extern int str_uint8_t(const char *, char **, unsigned int, bool, uint8_t *);
+extern int str_uint16_t(const char *, char **, unsigned int, bool, uint16_t *);
+extern int str_uint32_t(const char *, char **, unsigned int, bool, uint32_t *);
+extern int str_uint64_t(const char *, char **, unsigned int, bool, uint64_t *);
+extern int str_size_t(const char *, char **, unsigned int, bool, size_t *);
+
+extern void order_suffix(const uint64_t, uint64_t *, char *);
+extern void bin_order_suffix(const uint64_t, uint64_t *, const char **, bool);
+
+/*
+ * TODO: Get rid of this.
+ */
+
+extern int stricmp(const char *, const char *);
+
+extern long int strtol(const char *, char **, int);
+extern unsigned long strtoul(const char *, char **, int);
+
+extern char * strtok_r(char *, const char *, char **);
+extern char * strtok(char *, const char *);
+
+#endif
+
+/** @}
+ */
diff --git a/apps/libc/helenos/vsnprintf.c b/apps/libc/helenos/vsnprintf.c
new file mode 100644
index 0000000..7b54719
--- /dev/null
+++ b/apps/libc/helenos/vsnprintf.c
@@ -0,0 +1,187 @@
+/*
+ * Copyright (c) 2006 Josef Cejka
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup libc
+ * @{
+ */
+/** @file
+ */
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+#include "str.h"
+#include "printf_core.h"
+#include <errno.h>
+
+typedef struct {
+	size_t size;    /* Total size of the buffer (in bytes) */
+	size_t len;     /* Number of already used bytes */
+	char *dst;      /* Destination */
+} vsnprintf_data_t;
+
+/** Write string to given buffer.
+ *
+ * Write at most data->size plain characters including trailing zero.
+ * According to C99, snprintf() has to return number of characters that
+ * would have been written if enough space had been available. Hence
+ * the return value is not the number of actually printed characters
+ * but size of the input string.
+ *
+ * @param str  Source string to print.
+ * @param size Number of plain characters in str.
+ * @param data Structure describing destination string, counter
+ *             of used space and total string size.
+ *
+ * @return Number of characters to print (not characters actually
+ *         printed).
+ *
+ */
+static int vsnprintf_str_write(const char *str, size_t size, vsnprintf_data_t *data)
+{
+	size_t left = data->size - data->len;
+	
+	if (left == 0)
+		return ((int) size);
+	
+	if (left == 1) {
+		/* We have only one free byte left in buffer
+		 * -> store trailing zero
+		 */
+		data->dst[data->size - 1] = 0;
+		data->len = data->size;
+		return ((int) size);
+	}
+	
+	if (left <= size) {
+		/* We do not have enough space for the whole string
+		 * with the trailing zero => print only a part
+		 * of string
+		 */
+		size_t index = 0;
+		
+		while (index < size) {
+			wchar_t uc = str_decode(str, &index, size);
+			
+			if (chr_encode(uc, data->dst, &data->len, data->size - 1) != 0)
+				break;
+		}
+		
+		/* Put trailing zero at end, but not count it
+		 * into data->len so it could be rewritten next time
+		 */
+		data->dst[data->len] = 0;
+		
+		return ((int) size);
+	}
+	
+	/* Buffer is big enough to print the whole string */
+	memcpy((void *)(data->dst + data->len), (void *) str, size);
+	data->len += size;
+	
+	/* Put trailing zero at end, but not count it
+	 * into data->len so it could be rewritten next time
+	 */
+	data->dst[data->len] = 0;
+	
+	return ((int) size);
+}
+
+/** Write wide string to given buffer.
+ *
+ * Write at most data->size plain characters including trailing zero.
+ * According to C99, snprintf() has to return number of characters that
+ * would have been written if enough space had been available. Hence
+ * the return value is not the number of actually printed characters
+ * but size of the input string.
+ *
+ * @param str  Source wide string to print.
+ * @param size Number of bytes in str.
+ * @param data Structure describing destination string, counter
+ *             of used space and total string size.
+ *
+ * @return Number of wide characters to print (not characters actually
+ *         printed).
+ *
+ */
+static int vsnprintf_wstr_write(const wchar_t *str, size_t size, vsnprintf_data_t *data)
+{
+	size_t index = 0;
+	
+	while (index < (size / sizeof(wchar_t))) {
+		size_t left = data->size - data->len;
+		
+		if (left == 0)
+			return ((int) size);
+		
+		if (left == 1) {
+			/* We have only one free byte left in buffer
+			 * -> store trailing zero
+			 */
+			data->dst[data->size - 1] = 0;
+			data->len = data->size;
+			return ((int) size);
+		}
+		
+		if (chr_encode(str[index], data->dst, &data->len, data->size - 1) != 0)
+			break;
+		
+		index++;
+	}
+	
+	/* Put trailing zero at end, but not count it
+	 * into data->len so it could be rewritten next time
+	 */
+	data->dst[data->len] = 0;
+	
+	return ((int) size);
+}
+
+int vsnprintf(char *str, size_t size, const char *fmt, va_list ap)
+{
+	vsnprintf_data_t data = {
+		size,
+		0,
+		str
+	};
+	printf_spec_t ps = {
+		(int(*) (const char *, size_t, void *)) vsnprintf_str_write,
+		(int(*) (const wchar_t *, size_t, void *)) vsnprintf_wstr_write,
+		&data
+	};
+	
+	/* Print 0 at end of string - fix the case that nothing will be printed */
+	if (size > 0)
+		str[0] = 0;
+	
+	/* vsnprintf_write ensures that str will be terminated by zero. */
+	return printf_core(fmt, &ps, ap);
+}
+
+/** @}
+ */
-- 
1.7.10.4


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH 11/20] app: printf: add version from contiki
  2013-03-06  9:29 ` [PATCH 01/20] Makefile: x_flags prepare for apps support Jean-Christophe PLAGNIOL-VILLARD
                     ` (8 preceding siblings ...)
  2013-03-06  9:29   ` [PATCH 10/20] app: printf: use HelenOS verison with wide char support Jean-Christophe PLAGNIOL-VILLARD
@ 2013-03-06  9:29   ` Jean-Christophe PLAGNIOL-VILLARD
  2013-03-06  9:29   ` [PATCH 12/20] app: add tinycurses support Jean-Christophe PLAGNIOL-VILLARD
                     ` (8 subsequent siblings)
  18 siblings, 0 replies; 31+ messages in thread
From: Jean-Christophe PLAGNIOL-VILLARD @ 2013-03-06  9:29 UTC (permalink / raw)
  To: barebox

the strformat is taken from contiki OS which is under 3-clause BSD license
no wide char support

Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
---
 apps/libc/Kconfig             |    9 +
 apps/libc/Makefile            |    1 +
 apps/libc/contiki/Makefile    |    1 +
 apps/libc/contiki/strformat.c |  621 +++++++++++++++++++++++++++++++++++++++++
 apps/libc/contiki/strformat.h |   25 ++
 apps/libc/contiki/vsprintf.c  |  116 ++++++++
 6 files changed, 773 insertions(+)
 create mode 100644 apps/libc/contiki/Makefile
 create mode 100644 apps/libc/contiki/strformat.c
 create mode 100644 apps/libc/contiki/strformat.h
 create mode 100644 apps/libc/contiki/vsprintf.c

diff --git a/apps/libc/Kconfig b/apps/libc/Kconfig
index 25b35ee..8d4fbd6 100644
--- a/apps/libc/Kconfig
+++ b/apps/libc/Kconfig
@@ -24,6 +24,10 @@ config APP_PRINTF_STACK_SIZE
 
 choice
 	prompt "printf implementation"
+	default APPS_PRINTF_HELENOS
+
+config APPS_PRINTF_CONTIKI
+	bool "contiki"
 
 config APPS_PRINTF_HELENOS
 	bool "helen os"
@@ -32,4 +36,9 @@ config APPS_PRINTF_HELENOS
 
 endchoice
 
+config APP_PRINTF_STACK_SIZE
+	hex "printf stack size"
+	default 0x1000
+	depends on APPS_PRINTF_CONTIKI
+
 endmenu
diff --git a/apps/libc/Makefile b/apps/libc/Makefile
index c84f00e..832833c 100644
--- a/apps/libc/Makefile
+++ b/apps/libc/Makefile
@@ -15,6 +15,7 @@ app-y += unistd.o
 app-$(CONFIG_APPS_MALLOC_DUMMY) += dummy_malloc.o
 app-$(CONFIG_APPS_MALLOC_TLSF) += tlsf_malloc.o tlsf.o
 app-y += string.o
+obj-$(CONFIG_APPS_PRINTF_CONTIKI) += contiki/
 obj-$(CONFIG_APPS_PRINTF_HELENOS) += helenos/
 obj-y += sys/
 app-y += time.o
diff --git a/apps/libc/contiki/Makefile b/apps/libc/contiki/Makefile
new file mode 100644
index 0000000..e77ee5c
--- /dev/null
+++ b/apps/libc/contiki/Makefile
@@ -0,0 +1 @@
+app-y += vsprintf.o strformat.o
diff --git a/apps/libc/contiki/strformat.c b/apps/libc/contiki/strformat.c
new file mode 100644
index 0000000..82f0535
--- /dev/null
+++ b/apps/libc/contiki/strformat.c
@@ -0,0 +1,621 @@
+/*
+ * from contiki 3-clause BSD license
+ */
+#include <strformat.h>
+
+#ifdef __APP__
+#define HAVE_DOUBLE
+#endif
+
+#define HAVE_LONGLONG
+#ifndef LARGEST_SIGNED
+#ifdef HAVE_LONGLONG
+#define LARGEST_SIGNED long long int
+#else
+#define LARGEST_SIGNED long int
+#endif
+#endif
+
+#ifndef LARGEST_UNSIGNED
+#ifdef HAVE_LONGLONG
+#define LARGEST_UNSIGNED unsigned long long int
+#else
+#define LARGEST_UNSIGNED unsigned long int
+#endif
+#endif
+
+#ifndef POINTER_INT
+#define POINTER_INT unsigned long
+#endif
+
+typedef unsigned int FormatFlags;
+
+#define MAKE_MASK(shift,size) (((1 << size) - 1) << (shift))
+
+#define JUSTIFY_SHIFT	0
+#define JUSTIFY_SIZE	1
+#define JUSTIFY_RIGHT	0x0000
+#define JUSTIFY_LEFT	0x0001
+#define JUSTIFY_MASK	MAKE_MASK(JUSTIFY_SHIFT,JUSTIFY_SIZE)
+
+
+/* How a positive number is prefixed */
+#define POSITIVE_SHIFT	(JUSTIFY_SHIFT + JUSTIFY_SIZE)
+#define POSITIVE_NONE	(0x0000 << POSITIVE_SHIFT)
+#define POSITIVE_SPACE	(0x0001 << POSITIVE_SHIFT)
+#define POSITIVE_PLUS	(0x0003 << POSITIVE_SHIFT)
+#define POSITIVE_MASK	MAKE_MASK(POSITIVE_SHIFT, POSITIVE_SIZE)
+
+#define POSITIVE_SIZE	2
+
+#define ALTERNATE_FORM_SHIFT (POSITIVE_SHIFT + POSITIVE_SIZE)
+#define ALTERNATE_FORM_SIZE 1
+#define ALTERNATE_FORM  (0x0001 << ALTERNATE_FORM_SHIFT)
+
+
+#define PAD_SHIFT	(ALTERNATE_FORM_SHIFT + ALTERNATE_FORM_SIZE)
+#define PAD_SIZE	1
+#define PAD_SPACE	(0x0000 << PAD_SHIFT)
+#define PAD_ZERO	(0x0001 << PAD_SHIFT)
+
+#define SIZE_SHIFT	(PAD_SHIFT + PAD_SIZE)
+#define SIZE_SIZE	3
+#define SIZE_CHAR	(0x0001 << SIZE_SHIFT)
+#define SIZE_SHORT	(0x0002 << SIZE_SHIFT)
+#define SIZE_INT	(0x0000 << SIZE_SHIFT)
+#define SIZE_LONG	(0x0003 << SIZE_SHIFT)
+#define SIZE_LONGLONG	(0x0004 << SIZE_SHIFT)
+#define SIZE_MASK	MAKE_MASK(SIZE_SHIFT,SIZE_SIZE)
+
+#define CONV_SHIFT	(SIZE_SHIFT + SIZE_SIZE)
+#define CONV_SIZE	3
+#define CONV_INTEGER	(0x0001 << CONV_SHIFT)
+#define CONV_FLOAT	(0x0002 << CONV_SHIFT)
+#define CONV_POINTER	(0x0003 << CONV_SHIFT)
+#define CONV_STRING	(0x0004 << CONV_SHIFT)
+#define CONV_CHAR	(0x0005 << CONV_SHIFT)
+#define CONV_PERCENT	(0x0006 << CONV_SHIFT)
+#define CONV_WRITTEN	(0x0007 << CONV_SHIFT)
+#define CONV_MASK	MAKE_MASK(CONV_SHIFT, CONV_SIZE)
+
+#define RADIX_SHIFT	(CONV_SHIFT + CONV_SIZE)
+#define RADIX_SIZE	2
+#define RADIX_DECIMAL	(0x0001 << RADIX_SHIFT)
+#define RADIX_OCTAL	(0x0002 << RADIX_SHIFT)
+#define RADIX_HEX	(0x0003 << RADIX_SHIFT)
+#define RADIX_MASK	MAKE_MASK(RADIX_SHIFT,RADIX_SIZE)
+
+#define SIGNED_SHIFT	(RADIX_SHIFT + RADIX_SIZE)
+#define SIGNED_SIZE	1
+#define SIGNED_NO	(0x0000 << SIGNED_SHIFT)
+#define SIGNED_YES	(0x0001 << SIGNED_SHIFT)
+#define SIGNED_MASK	MAKE_MASK(SIGNED_SHIFT,SIGNED_SIZE)
+
+#define CAPS_SHIFT	(SIGNED_SHIFT + SIGNED_SIZE)
+#define CAPS_SIZE	1
+#define CAPS_NO		(0x0000 << CAPS_SHIFT)
+#define CAPS_YES	(0x0001 << CAPS_SHIFT)
+#define CAPS_MASK	MAKE_MASK(CAPS_SHIFT,CAPS_SIZE)
+
+#define FLOAT_SHIFT	(CAPS_SHIFT + CAPS_SIZE)
+#define FLOAT_SIZE	2
+#define FLOAT_NORMAL	(0x0000 << FLOAT_SHIFT)
+#define FLOAT_EXPONENT	(0x0001 << FLOAT_SHIFT)
+#define FLOAT_DEPENDANT	(0x0002 << FLOAT_SHIFT)
+#define FLOAT_HEX	(0x0003 << FLOAT_SHIFT)
+#define FLOAT_MASK	MAKE_MASK(FLOAT_SHIFT, FLOAT_SIZE)
+
+static FormatFlags
+parse_flags(const char **posp)
+{
+  FormatFlags flags = 0;
+  const char *pos = *posp;
+  while (1) {
+    switch(*pos) {
+    case '-':
+      flags |= JUSTIFY_LEFT;
+      break;
+    case '+':
+      flags |= POSITIVE_PLUS;
+      break;
+    case ' ':
+      flags |= POSITIVE_SPACE;
+      break;
+    case '#':
+      flags |= ALTERNATE_FORM;
+      break;
+    case '0':
+      flags |= PAD_ZERO;
+      break;
+    default:
+      *posp = pos;
+      return flags;
+    }
+    pos++;
+  }
+      
+}
+
+static unsigned int
+parse_uint(const char **posp)
+{
+  unsigned v = 0;
+  const char *pos = *posp;
+  char ch;
+  while((ch = *pos) >= '0' && ch <= '9') {
+    v = v * 10 + (ch - '0');
+    pos++;
+  }
+  *posp = pos;
+  return v;
+}
+
+#define MAXCHARS_HEX ((sizeof(LARGEST_UNSIGNED) * 8) / 4 )
+
+/* Largest number of characters needed for converting an unsigned integer.
+ */
+#define MAXCHARS ((sizeof(LARGEST_UNSIGNED) * 8  + 2) / 3 )
+
+static unsigned int
+output_uint_decimal(char **posp, LARGEST_UNSIGNED v)
+{
+  unsigned int len;
+  char *pos = *posp;
+  while (v > 0) {
+    *--pos = (v % 10) + '0';
+    v /= 10;
+  }
+  len = *posp - pos;
+  *posp = pos;
+  return len;
+}
+
+static unsigned int
+output_uint_hex(char **posp, LARGEST_UNSIGNED v, unsigned int flags)
+{
+  unsigned int len;
+  const char *hex = (flags & CAPS_YES) ?"0123456789ABCDEF":"0123456789abcdef";
+  char *pos = *posp;
+  while (v > 0) {
+    *--pos = hex[(v % 16)];
+    v /= 16;
+  }
+  len = *posp - pos;
+  *posp = pos;
+  return len;
+}
+
+static unsigned int
+output_uint_octal(char **posp, LARGEST_UNSIGNED v)
+{
+  unsigned int len;
+  char *pos = *posp;
+  while (v > 0) {
+    *--pos = (v % 8) + '0';
+    v /= 8;
+  }
+  len = *posp - pos;
+  *posp = pos;
+  return len;
+}
+
+static StrFormatResult
+fill_space(const StrFormatContext *ctxt, unsigned int len)
+{
+  StrFormatResult res;
+  static const char buffer[16] = "                ";
+  while(len > 16) {
+    res = ctxt->write_str(ctxt->user_data, buffer, 16);
+    if (res != STRFORMAT_OK) return res;
+    len -= 16;
+  }
+  if (len == 0) return STRFORMAT_OK;
+  return ctxt->write_str(ctxt->user_data, buffer, len);
+}
+
+static StrFormatResult
+fill_zero(const StrFormatContext *ctxt, unsigned int len)
+{
+  StrFormatResult res;
+  static const char buffer[16] = "0000000000000000";
+  while(len > 16) {
+    res = ctxt->write_str(ctxt->user_data, buffer, 16);
+    if (res != STRFORMAT_OK) return res;
+    len -= 16;
+  }
+  if (len == 0) return STRFORMAT_OK;
+  return ctxt->write_str(ctxt->user_data, buffer, len);
+}
+
+#define CHECKCB(res) {if ((res) != STRFORMAT_OK) {va_end(ap); return -1;}}
+
+int
+format_str(const StrFormatContext *ctxt, const char *format, ...)
+{
+  int ret;
+  va_list ap;
+  va_start(ap, format);
+  ret = format_str_v(ctxt, format, ap);
+  va_end(ap);
+  return ret;
+}
+
+int
+format_str_v(const StrFormatContext *ctxt, const char *format, va_list ap)
+{
+  unsigned int written = 0;
+  const char *pos = format;
+  while(*pos != '\0') {
+    FormatFlags flags;
+    unsigned int minwidth = 0;
+    int precision = -1; /* Negative means no precision */
+    char ch;
+    const char *start = pos;
+    while( (ch = *pos) != '\0' && ch != '%') pos++;
+    if (pos != start) {
+      CHECKCB(ctxt->write_str(ctxt->user_data, start, pos - start));
+      written += pos - start;
+    }
+    if (*pos == '\0') {
+      va_end(ap);
+      return written;
+    }
+    pos++;
+    if (*pos == '\0') {
+      va_end(ap);
+      return written;
+    }
+    flags = parse_flags(&pos);
+
+    /* parse width */
+    if (*pos >= '1' && *pos <= '9') {
+      minwidth = parse_uint(&pos);
+    } else if (*pos == '*') {
+      int w = va_arg(ap,int);
+      if (w < 0) {
+	flags |= JUSTIFY_LEFT;
+	minwidth = w;
+      } else {
+	minwidth = w;
+      }
+      pos ++;
+    }
+
+    /* parse precision */
+    if (*pos == '.') {
+      pos++;
+      if (*pos >= '0' && *pos <= '9') {
+	precision = parse_uint(&pos);
+      } else if (*pos == '*') {
+	pos++;
+	precision = va_arg(ap,int);
+      }
+    }
+    if (*pos == 'l') {
+      pos++;
+      if (*pos == 'l') {
+	flags |= SIZE_LONGLONG;
+	pos++;
+      } else {
+	flags |= SIZE_LONG;
+      }
+    } else if (*pos == 'h') {
+      pos++;
+      if (*pos == 'h') {
+	flags |= SIZE_CHAR;
+	pos++;
+      } else {
+	flags |= SIZE_SHORT;
+      }
+    }
+
+    /* parse conversion specifier */
+    switch(*pos) {
+    case 'd':
+    case 'i':
+      flags |= CONV_INTEGER | RADIX_DECIMAL | SIGNED_YES;
+      break;
+    case 'u':
+      flags |= CONV_INTEGER | RADIX_DECIMAL | SIGNED_NO;
+      break;
+    case 'o':
+      flags |= CONV_INTEGER | RADIX_OCTAL | SIGNED_NO;
+      break;
+    case 'x':
+      flags |= CONV_INTEGER | RADIX_HEX | SIGNED_NO;
+      break;
+    case 'X':
+      flags |= CONV_INTEGER | RADIX_HEX | SIGNED_NO | CAPS_YES;
+      break;
+#ifdef HAVE_DOUBLE
+    case 'f':
+      flags |= CONV_FLOAT | FLOAT_NORMAL;
+      break;
+    case 'F':
+      flags |= CONV_FLOAT | FLOAT_NORMAL | CAPS_YES;
+      break;
+    case 'e':
+      flags |= CONV_FLOAT | FLOAT_EXPONENT;
+      break;
+    case 'E':
+      flags |= CONV_FLOAT | FLOAT_EXPONENT | CAPS_YES;
+      break;
+    case 'g':
+      flags |= CONV_FLOAT | FLOAT_DEPENDANT;
+      break;
+    case 'G':
+      flags |= CONV_FLOAT | FLOAT_DEPENDANT | CAPS_YES;
+      break;
+    case 'a':
+      flags |= CONV_FLOAT | FLOAT_HEX;
+      break;
+    case 'A':
+      flags |= CONV_FLOAT | FLOAT_HEX | CAPS_YES;
+      break;
+#endif
+    case 'c':
+      flags |= CONV_CHAR;
+      break;
+    case 's':
+      flags |= CONV_STRING;
+      break;
+    case 'p':
+      flags |= CONV_POINTER;
+      break;
+    case 'n':
+      flags |= CONV_WRITTEN;
+      break;
+    case '%':
+      flags |= CONV_PERCENT;
+      break;
+    case '\0':
+      va_end(ap);
+      return written;
+    }
+    pos++;
+    switch(flags & CONV_MASK) {
+    case CONV_PERCENT:
+      CHECKCB(ctxt->write_str(ctxt->user_data, "%", 1));
+      written++;
+      break;
+    case CONV_INTEGER:
+      {
+	/* unsigned integers */
+	char *prefix = 0; /* sign, "0x" or "0X" */
+	unsigned int prefix_len = 0;
+	char buffer[MAXCHARS];
+	char *conv_pos = buffer + MAXCHARS;
+	unsigned int conv_len = 0;
+	unsigned int width = 0;
+	unsigned int precision_fill;
+	unsigned int field_fill;
+	LARGEST_UNSIGNED uvalue = 0;
+	int negative = 0;
+      
+	if (precision < 0) precision = 1;
+	else flags &= ~PAD_ZERO;
+      
+	if (flags & SIGNED_YES) {
+	  /* signed integers */
+	  LARGEST_SIGNED value = 0;
+	  switch(flags & SIZE_MASK) {
+	  case SIZE_CHAR:
+	    value = (signed char)va_arg(ap, int);
+	    break;
+	  case SIZE_SHORT:
+	    value = (short)va_arg(ap, int);
+	    break;
+	  case SIZE_INT:
+	    value = va_arg(ap, int);
+	    break;
+#ifndef HAVE_LONGLONG
+	  case SIZE_LONGLONG:	/* Treat long long the same as long */
+#endif
+	  case SIZE_LONG:
+	    value = va_arg(ap, long);
+	    break;
+#ifdef HAVE_LONGLONG
+	  case SIZE_LONGLONG:
+	    value = va_arg(ap, long long);
+	    break;
+#endif
+	  }
+	  if (value < 0) {
+	    uvalue = -value;
+	    negative = 1;
+	  } else {
+	    uvalue = value;
+	  }
+	} else {
+	
+	  switch(flags & SIZE_MASK) {
+	  case SIZE_CHAR:
+	    uvalue = (unsigned char)va_arg(ap,unsigned int);
+	    break;
+	  case SIZE_SHORT:
+	    uvalue = (unsigned short)va_arg(ap,unsigned int);
+	    break;
+	  case SIZE_INT:
+	    uvalue = va_arg(ap,unsigned int);
+	    break;
+#ifndef HAVE_LONGLONG
+	  case SIZE_LONGLONG:	/* Treat long long the same as long */
+#endif
+	  case SIZE_LONG:
+	    uvalue = va_arg(ap,unsigned long);
+	    break;
+#ifdef HAVE_LONGLONG
+	  case SIZE_LONGLONG:
+	    uvalue = va_arg(ap,unsigned long long);
+	    break;
+#endif
+	  }
+	}
+	
+	switch(flags & (RADIX_MASK)) {
+	case RADIX_DECIMAL:
+	  conv_len = output_uint_decimal(&conv_pos,uvalue);
+	  break;
+	case RADIX_OCTAL:
+	  conv_len = output_uint_octal(&conv_pos,uvalue);
+	  break;
+	case RADIX_HEX:
+	  conv_len = output_uint_hex(&conv_pos,uvalue, flags);
+	  break;
+	}
+
+	width += conv_len;
+	precision_fill = (precision > conv_len) ? precision - conv_len : 0;
+	if ((flags & (RADIX_MASK | ALTERNATE_FORM))
+	    == (RADIX_OCTAL | ALTERNATE_FORM)) {
+	  if (precision_fill < 1) precision_fill = 1;
+	}
+
+	width += precision_fill;
+	
+	if ((flags & (RADIX_MASK | ALTERNATE_FORM))
+	    == (RADIX_HEX | ALTERNATE_FORM) && uvalue != 0) {
+	  prefix_len = 2;
+	  if (flags & CAPS_YES) {
+	    prefix = "0X";
+	  } else {
+	    prefix = "0x";
+	  }
+	}
+
+	if (flags & SIGNED_YES) {
+	  if (negative) {
+	    prefix = "-";
+	    prefix_len = 1;
+	  } else {
+	    switch(flags & POSITIVE_MASK) {
+	    case POSITIVE_SPACE:
+	      prefix = " ";
+	      prefix_len = 1;
+	      break;
+	    case POSITIVE_PLUS:
+	      prefix = "+";
+	      prefix_len = 1;
+	      break;
+	    }
+	  }
+	}
+
+	width += prefix_len;
+
+	field_fill = (minwidth > width) ? minwidth - width : 0;
+
+	if ((flags & JUSTIFY_MASK) == JUSTIFY_RIGHT) {
+	  if (flags & PAD_ZERO) {
+	    precision_fill += field_fill;
+        field_fill = 0;  /* Do not double count padding */
+	  } else {
+	    CHECKCB(fill_space(ctxt,field_fill));
+	  }
+	}
+
+	if (prefix_len > 0)
+	  CHECKCB(ctxt->write_str(ctxt->user_data, prefix, prefix_len));
+	written += prefix_len;
+	
+	CHECKCB(fill_zero(ctxt,precision_fill));
+	written += precision_fill;
+	
+	CHECKCB(ctxt->write_str(ctxt->user_data, conv_pos,conv_len));
+	written += conv_len;
+	
+	if ((flags & JUSTIFY_MASK) == JUSTIFY_LEFT) {
+	  CHECKCB(fill_space(ctxt,field_fill));
+	}
+	written += field_fill;
+      }
+      break;
+    case CONV_STRING:
+      {
+	unsigned int field_fill;
+	unsigned int len;
+	char *str = va_arg(ap,char *);
+	if (str) {
+	  char *pos = str;
+	  while(*pos != '\0') pos++;
+	  len = pos - str;
+	} else {
+	  str = "(null)";
+	  len = 6;
+	}
+	if (precision >= 0 && precision < len) len = precision;
+	field_fill = (minwidth > len) ? minwidth - len : 0;
+	if ((flags & JUSTIFY_MASK) == JUSTIFY_RIGHT) {
+	  CHECKCB(fill_space(ctxt,field_fill));
+	}
+	CHECKCB(ctxt->write_str(ctxt->user_data, str,len));
+	written += len;
+	if ((flags & JUSTIFY_MASK) == JUSTIFY_LEFT) {
+	  CHECKCB(fill_space(ctxt,field_fill));
+	}
+	written += field_fill;
+      }
+      break;
+    case CONV_POINTER:
+      {
+	LARGEST_UNSIGNED uvalue =
+	  (LARGEST_UNSIGNED)(POINTER_INT)va_arg(ap,void *);
+	char buffer[MAXCHARS_HEX + 2];
+	char *conv_pos = buffer + MAXCHARS_HEX + 2;
+	unsigned int conv_len;
+	unsigned int field_fill;
+	
+	conv_len = output_uint_hex(&conv_pos,uvalue,flags);
+	if (conv_len == 0) {
+	  *--conv_pos = '0';
+	  conv_len++;
+	}
+	*--conv_pos = 'x';
+	*--conv_pos = '0';
+	conv_len += 2;
+
+	field_fill = (minwidth > conv_len) ? minwidth - conv_len : 0;
+	
+	if ((flags & JUSTIFY_MASK) == JUSTIFY_RIGHT) {
+	  CHECKCB(fill_space(ctxt,field_fill));
+	}
+	
+	CHECKCB(ctxt->write_str(ctxt->user_data, conv_pos,conv_len));
+	written += conv_len;
+	
+	if ((flags & JUSTIFY_MASK) == JUSTIFY_LEFT) {
+	  CHECKCB(fill_space(ctxt,field_fill));
+	}
+	written += field_fill;
+      }
+      break;
+    case CONV_CHAR:
+      {
+	char ch = va_arg(ap,int);
+	unsigned int field_fill = (minwidth > 1) ? minwidth - 1 : 0;
+	if ((flags & JUSTIFY_MASK) == JUSTIFY_RIGHT) {
+	  CHECKCB(fill_space(ctxt,field_fill));
+	  written += field_fill;
+	}
+	
+	CHECKCB(ctxt->write_str(ctxt->user_data, &ch, 1));
+	written++;
+	
+	if ((flags & JUSTIFY_MASK) == JUSTIFY_LEFT) {
+	  CHECKCB(fill_space(ctxt,field_fill));
+	}
+	written+= field_fill;
+      }
+      break;
+    case CONV_WRITTEN:
+      {
+	int *p = va_arg(ap,int*);
+	*p = written;
+      }
+      break;
+
+    }
+  }
+  
+  return written;
+}
diff --git a/apps/libc/contiki/strformat.h b/apps/libc/contiki/strformat.h
new file mode 100644
index 0000000..d953c3e
--- /dev/null
+++ b/apps/libc/contiki/strformat.h
@@ -0,0 +1,25 @@
+#ifndef __STRFORMAT_H__
+#define __STRFORMAT_H__
+
+#include <stdarg.h>
+
+#define STRFORMAT_OK 0
+#define STRFORMAT_FAILED 1
+typedef unsigned int StrFormatResult;
+
+/* The data argument may only be considered valid during the function call */
+typedef StrFormatResult (*StrFormatWrite)(void *user_data, const char *data, unsigned int len);
+
+typedef struct _StrFormatContext
+{
+  StrFormatWrite write_str;
+  void *user_data;
+} StrFormatContext;
+
+int format_str(const StrFormatContext *ctxt, const char *format, ...)
+     __attribute__ ((__format__ (__printf__, 2,3)));
+     
+int
+format_str_v(const StrFormatContext *ctxt, const char *format, va_list ap);
+
+#endif /* __STRFORMAT_H__ */
diff --git a/apps/libc/contiki/vsprintf.c b/apps/libc/contiki/vsprintf.c
new file mode 100644
index 0000000..1df7a4d
--- /dev/null
+++ b/apps/libc/contiki/vsprintf.c
@@ -0,0 +1,116 @@
+/*
+ * Coypyright Jean-Chritophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+ */
+
+#include <sys/types.h>
+#include <stdarg.h>
+#include <limits.h>
+#include <string.h>
+#include <malloc.h>
+
+#include "strformat.h"
+
+struct FmtBuffer {
+	char *pos;
+	size_t left;
+};
+
+static StrFormatResult buffer_str(void *user_data, const char *data, unsigned int len)
+{
+	struct FmtBuffer *buffer = (struct FmtBuffer*)user_data;
+
+	if (len >= buffer->left) {
+		len = buffer->left;
+		len--;
+	}
+
+	memcpy(buffer->pos, data, len);
+	buffer->pos += len;
+	buffer->left -= len;
+
+	return STRFORMAT_OK;
+}
+
+int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
+{
+	struct FmtBuffer buffer;
+	StrFormatContext ctxt;
+	int res;
+
+	ctxt.write_str = buffer_str;
+	ctxt.user_data = &buffer;
+	buffer.pos = buf;
+	buffer.left = size;
+	res = format_str_v(&ctxt, fmt, args);
+	*buffer.pos = '\0';
+
+	return res;
+}
+
+int vscnprintf(char *buf, size_t size, const char *fmt, va_list args)
+{
+	int i;
+
+	i = vsnprintf(buf, size, fmt, args);
+	return (i >= size) ? (size - 1) : i;
+}
+
+int vsprintf(char *buf, const char *fmt, va_list args)
+{
+	return vsnprintf(buf, INT_MAX, fmt, args);
+}
+
+int sprintf(char * buf, const char *fmt, ...)
+{
+	va_list args;
+	int i;
+
+	va_start(args, fmt);
+	i = vsprintf(buf, fmt, args);
+	va_end(args);
+
+	return i;
+}
+
+int snprintf(char * buf, size_t size, const char *fmt, ...)
+{
+	va_list args;
+	int i;
+
+	va_start(args, fmt);
+	i = vsnprintf(buf, size, fmt, args);
+	va_end(args);
+
+	return i;
+}
+
+char *vasprintf(const char *fmt, va_list ap)
+{
+	unsigned int len;
+	char *p;
+	va_list aq;
+
+	va_copy(aq, ap);
+	len = vsnprintf(NULL, 0, fmt, aq);
+	va_end(aq);
+
+	p = malloc(len + 1);
+	if (!p)
+		return NULL;
+
+	vsnprintf(p, len + 1, fmt, ap);
+
+	return p;
+}
+
+char *asprintf(const char *fmt, ...)
+{
+	va_list ap;
+	char *p;
+
+	va_start(ap, fmt);
+	p = vasprintf(fmt, ap);
+	va_end(ap);
+
+	return p;
+}
-- 
1.7.10.4


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH 12/20] app: add tinycurses support
  2013-03-06  9:29 ` [PATCH 01/20] Makefile: x_flags prepare for apps support Jean-Christophe PLAGNIOL-VILLARD
                     ` (9 preceding siblings ...)
  2013-03-06  9:29   ` [PATCH 11/20] app: printf: add version from contiki Jean-Christophe PLAGNIOL-VILLARD
@ 2013-03-06  9:29   ` Jean-Christophe PLAGNIOL-VILLARD
  2013-03-06 11:31     ` Sascha Hauer
  2013-03-06  9:29   ` [PATCH 13/20] app: curses: add pdcurses Jean-Christophe PLAGNIOL-VILLARD
                     ` (7 subsequent siblings)
  18 siblings, 1 reply; 31+ messages in thread
From: Jean-Christophe PLAGNIOL-VILLARD @ 2013-03-06  9:29 UTC (permalink / raw)
  To: barebox

take from corboot and upated to use ansi

Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
---
 apps/Kconfig                                |    1 +
 apps/Makefile                               |    3 +
 apps/lib/Kconfig                            |    1 +
 apps/lib/Makefile                           |    1 +
 apps/lib/Makefile.include                   |    1 +
 apps/lib/curses/Kconfig                     |   14 +
 apps/lib/curses/Makefile                    |    1 +
 apps/lib/curses/Makefile.include            |    3 +
 apps/lib/curses/tinycurses/Makefile         |    3 +
 apps/lib/curses/tinycurses/Makefile.include |    1 +
 apps/lib/curses/tinycurses/colors.c         |   62 +
 apps/lib/curses/tinycurses/curses.h         | 1680 +++++++++++++++++++++++++++
 apps/lib/curses/tinycurses/curses.priv.h    | 1317 +++++++++++++++++++++
 apps/lib/curses/tinycurses/keyboard.c       |  247 ++++
 apps/lib/curses/tinycurses/local.h          |   89 ++
 apps/lib/curses/tinycurses/tinycurses.c     | 1016 ++++++++++++++++
 16 files changed, 4440 insertions(+)
 create mode 100644 apps/lib/Kconfig
 create mode 100644 apps/lib/Makefile
 create mode 100644 apps/lib/Makefile.include
 create mode 100644 apps/lib/curses/Kconfig
 create mode 100644 apps/lib/curses/Makefile
 create mode 100644 apps/lib/curses/Makefile.include
 create mode 100644 apps/lib/curses/tinycurses/Makefile
 create mode 100644 apps/lib/curses/tinycurses/Makefile.include
 create mode 100644 apps/lib/curses/tinycurses/colors.c
 create mode 100644 apps/lib/curses/tinycurses/curses.h
 create mode 100644 apps/lib/curses/tinycurses/curses.priv.h
 create mode 100644 apps/lib/curses/tinycurses/keyboard.c
 create mode 100644 apps/lib/curses/tinycurses/local.h
 create mode 100644 apps/lib/curses/tinycurses/tinycurses.c

diff --git a/apps/Kconfig b/apps/Kconfig
index 324e14d..a025955 100644
--- a/apps/Kconfig
+++ b/apps/Kconfig
@@ -8,6 +8,7 @@ menuconfig APPLICATIONS
 if APPLICATIONS
 
 source "apps/libc/Kconfig"
+source "apps/lib/Kconfig"
 
 menu "memory layout"
 
diff --git a/apps/Makefile b/apps/Makefile
index 7f609e7..cce547e 100644
--- a/apps/Makefile
+++ b/apps/Makefile
@@ -1,6 +1,8 @@
 
 APP_CPPFLAGS += -include $(srctree)/apps/include/libc_config.h
 APP_CPPFLAGS += -I$(srctree)/apps/include
+include $(srctree)/apps/lib/Makefile.include
+APP_CPPFLAGS += $(APP_CPPFLAGS-y)
 export APP_CPPFLAGS
 
 apps-$(CONFIG_APP_EXAMPLE) += example
@@ -19,6 +21,7 @@ $(obj)/include/barebox/syscalls.h: $(srctree)/include/apps/syscalls.h
 
 obj-y += libc/
 obj-y += utils/
+obj-y += lib/
 
 barebox-app-header += $(obj)/include/types.h
 barebox-app-header += $(obj)/include/barebox/syscalls.h
diff --git a/apps/lib/Kconfig b/apps/lib/Kconfig
new file mode 100644
index 0000000..6725322
--- /dev/null
+++ b/apps/lib/Kconfig
@@ -0,0 +1 @@
+source apps/lib/curses/Kconfig
diff --git a/apps/lib/Makefile b/apps/lib/Makefile
new file mode 100644
index 0000000..3d3653e
--- /dev/null
+++ b/apps/lib/Makefile
@@ -0,0 +1 @@
+obj-y += curses/
diff --git a/apps/lib/Makefile.include b/apps/lib/Makefile.include
new file mode 100644
index 0000000..c0563cb
--- /dev/null
+++ b/apps/lib/Makefile.include
@@ -0,0 +1 @@
+include $(srctree)/apps/lib/curses/Makefile.include
diff --git a/apps/lib/curses/Kconfig b/apps/lib/curses/Kconfig
new file mode 100644
index 0000000..c6bc573
--- /dev/null
+++ b/apps/lib/curses/Kconfig
@@ -0,0 +1,14 @@
+menuconfig APP_LIB_CURSES
+	bool "curses"
+
+if APP_LIB_CURSES
+
+choice
+	prompt "curses implementation"
+
+config APP_LIB_TINYCURSES
+	bool "tiny"
+
+endchoice
+
+endif
diff --git a/apps/lib/curses/Makefile b/apps/lib/curses/Makefile
new file mode 100644
index 0000000..aeebdd5
--- /dev/null
+++ b/apps/lib/curses/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_APP_LIB_TINYCURSES) += tinycurses/
diff --git a/apps/lib/curses/Makefile.include b/apps/lib/curses/Makefile.include
new file mode 100644
index 0000000..8cf9d52
--- /dev/null
+++ b/apps/lib/curses/Makefile.include
@@ -0,0 +1,3 @@
+inc-$(CONFIG_APP_LIB_TINYCURSES) += $(srctree)/apps/lib/curses/tinycurses/Makefile.include
+
+include $(inc-y)
diff --git a/apps/lib/curses/tinycurses/Makefile b/apps/lib/curses/tinycurses/Makefile
new file mode 100644
index 0000000..05ff063
--- /dev/null
+++ b/apps/lib/curses/tinycurses/Makefile
@@ -0,0 +1,3 @@
+app-y += keyboard.o
+app-y += tinycurses.o
+app-y += colors.o
diff --git a/apps/lib/curses/tinycurses/Makefile.include b/apps/lib/curses/tinycurses/Makefile.include
new file mode 100644
index 0000000..2fe01f7
--- /dev/null
+++ b/apps/lib/curses/tinycurses/Makefile.include
@@ -0,0 +1 @@
+APP_CPPFLAGS-y += -I$(srctree)/apps/lib/curses/tinycurses/
diff --git a/apps/lib/curses/tinycurses/colors.c b/apps/lib/curses/tinycurses/colors.c
new file mode 100644
index 0000000..5065f5c
--- /dev/null
+++ b/apps/lib/curses/tinycurses/colors.c
@@ -0,0 +1,62 @@
+/*
+ * This file is part of the libpayload project.
+ *
+ * Copyright (C) 2007 Uwe Hermann <uwe@hermann-uwe.de>
+ * Copyright (C) 2008 Advanced Micro Devices, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* Color pair management */
+
+#include "local.h"
+
+unsigned char color_pairs[256] = {
+	[0] = 0x07,
+};
+
+int start_color(void)
+{
+	return 0;
+}
+
+int init_pair(short index, short fg, short bg)
+{
+	if (index == 0 || index > 255)
+		return ERR;
+
+	color_pairs[index] = ((bg & 0xF) << 4) | (fg & 0xF);
+	return 0;
+}
+
+int pair_content(short index, short *fg, short *bg)
+{
+	if (index < 0 || index > 255)
+		return ERR;
+
+	*bg = (color_pairs[index] >> 4) & 0xF;
+	*fg = color_pairs[index] & 0xF;
+
+	return 0;
+}
diff --git a/apps/lib/curses/tinycurses/curses.h b/apps/lib/curses/tinycurses/curses.h
new file mode 100644
index 0000000..d9b1bf9
--- /dev/null
+++ b/apps/lib/curses/tinycurses/curses.h
@@ -0,0 +1,1680 @@
+/****************************************************************************
+ * Copyright (c) 1998-2005,2006 Free Software Foundation, Inc.              *
+ *                                                                          *
+ * 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, distribute with modifications, sublicense, and/or sell       *
+ * copies of the Software, and to permit persons to whom the Software is    *
+ * furnished to do so, subject to the following conditions:                 *
+ *                                                                          *
+ * The above copyright notice and this permission notice shall be included  *
+ * in all copies or substantial portions of the Software.                   *
+ *                                                                          *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
+ * IN NO EVENT SHALL THE ABOVE 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.                               *
+ *                                                                          *
+ * Except as contained in this notice, the name(s) of the above copyright   *
+ * holders shall not be used in advertising or otherwise to promote the     *
+ * sale, use or other dealings in this Software without prior written       *
+ * authorization.                                                           *
+ ****************************************************************************/
+
+/****************************************************************************
+ *  Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995               *
+ *     and: Eric S. Raymond <esr@snark.thyrsus.com>                         *
+ *     and: Thomas E. Dickey                        1996-on                 *
+ ****************************************************************************/
+
+/* $Id: curses.h.in,v 1.167 2006/11/26 01:14:54 tom Exp $ */
+
+#ifndef _CURSES_H
+#define _CURSES_H
+
+#define CURSES 1
+#define CURSES_H 1
+
+/* This should be defined for the enhanced functionality to be visible.
+ * However, some of the wide-character (enhanced) functionality is missing.
+ * So we do not define it (yet).
+#define _XOPEN_CURSES 1
+ */
+
+/* These are defined only in curses.h, and are used for conditional compiles */
+#define NCURSES_VERSION_MAJOR 5
+#define NCURSES_VERSION_MINOR 6
+#define NCURSES_VERSION_PATCH 20061217
+
+/* This is defined in more than one ncurses header, for identification */
+#undef  NCURSES_VERSION
+#define NCURSES_VERSION "5.6"
+
+/*
+ * Identify the mouse encoding version.
+ */
+// #define NCURSES_MOUSE_VERSION 1
+
+/*
+ * Definitions to facilitate DLL's.
+ */
+//// #include <ncursesw/ncurses_dll.h>
+
+////---------------------------------------------------------------------------
+//// From ncurses_dll.h:
+////---------------------------------------------------------------------------
+/* Take care of non-cygwin platforms */
+#if !defined(NCURSES_IMPEXP)
+#  define NCURSES_IMPEXP /* nothing */
+#endif
+#if !defined(NCURSES_API)
+#  define NCURSES_API /* nothing */
+#endif
+#if !defined(NCURSES_EXPORT)
+#  define NCURSES_EXPORT(type) NCURSES_IMPEXP type NCURSES_API
+#endif
+#if !defined(NCURSES_EXPORT_VAR)
+#  define NCURSES_EXPORT_VAR(type) NCURSES_IMPEXP type
+#endif
+////---------------------------------------------------------------------------
+
+/*
+ * User-definable tweak to disable the include of <stdbool.h>.
+ */
+#ifndef NCURSES_ENABLE_STDBOOL_H
+#define NCURSES_ENABLE_STDBOOL_H 0	//// XXX
+#endif
+
+/*
+ * NCURSES_ATTR_T is used to quiet compiler warnings when building ncurses
+ * configured using --disable-macros.
+ */
+#ifdef NCURSES_NOMACROS
+#ifndef NCURSES_ATTR_T
+#define NCURSES_ATTR_T attr_t
+#endif
+#endif /* NCURSES_NOMACROS */
+
+#ifndef NCURSES_ATTR_T
+#define NCURSES_ATTR_T int
+#endif
+
+/*
+ * Expands to 'const' if ncurses is configured using --enable-const.  Note that
+ * doing so makes it incompatible with other implementations of X/Open Curses.
+ */
+#undef  NCURSES_CONST
+#define NCURSES_CONST const
+
+#undef NCURSES_INLINE
+#define NCURSES_INLINE inline
+
+/*
+ * The internal type used for color values
+ */
+#undef	NCURSES_COLOR_T
+#define	NCURSES_COLOR_T short
+
+/*
+ * The internal type used for window dimensions.
+ */
+#undef	NCURSES_SIZE_T
+#define	NCURSES_SIZE_T short
+
+/*
+ * Control whether tparm() supports varargs or fixed-parameter list.
+ */
+#undef NCURSES_TPARM_VARARGS
+#define NCURSES_TPARM_VARARGS 1
+
+/*
+ * NCURSES_CH_T is used in building the library, but not used otherwise in
+ * this header file, since that would make the normal/wide-character versions
+ * of the header incompatible.
+ */
+#undef	NCURSES_CH_T
+#define NCURSES_CH_T cchar_t
+
+#if 0 && defined(_LP64)
+typedef unsigned chtype;
+typedef unsigned mmask_t;
+#else
+typedef unsigned long chtype;
+typedef unsigned long mmask_t;
+#endif
+
+#include <stdio.h>
+//// #include <ncursesw/unctrl.h>
+#include <stdarg.h>	/* we need va_list */
+//// #define va_list int	// FIXME
+
+#define _XOPEN_SOURCE_EXTENDED 1	// XXX
+typedef unsigned long wchar_t;
+//// #ifdef _XOPEN_SOURCE_EXTENDED
+//// #include <stddef.h>	/* we want wchar_t */
+//// #endif /* _XOPEN_SOURCE_EXTENDED */
+
+/* XSI and SVr4 specify that curses implements 'bool'.  However, C++ may also
+ * implement it.  If so, we must use the C++ compiler's type to avoid conflict
+ * with other interfaces.
+ *
+ * A further complication is that <stdbool.h> may declare 'bool' to be a
+ * different type, such as an enum which is not necessarily compatible with
+ * C++.  If we have <stdbool.h>, make 'bool' a macro, so users may #undef it.
+ * Otherwise, let it remain a typedef to avoid conflicts with other #define's.
+ * In either case, make a typedef for NCURSES_BOOL which can be used if needed
+ * from either C or C++.
+ */
+
+#undef TRUE
+#define TRUE    1
+
+#undef FALSE
+#define FALSE   0
+
+typedef unsigned char NCURSES_BOOL;
+
+#if defined(__cplusplus)	/* __cplusplus, etc. */
+
+/* use the C++ compiler's bool type */
+#define NCURSES_BOOL bool
+
+#else			/* c89, c99, etc. */
+
+#if NCURSES_ENABLE_STDBOOL_H
+#include <stdbool.h>
+/* use whatever the C compiler decides bool really is */
+#define NCURSES_BOOL bool
+#else
+/* there is no predefined bool - use our own */
+#undef bool
+#define bool NCURSES_BOOL
+#endif
+
+#endif /* !__cplusplus, etc. */
+
+#ifdef __cplusplus
+extern "C" {
+#define NCURSES_CAST(type,value) static_cast<type>(value)
+#else
+#define NCURSES_CAST(type,value) (type)(value)
+#endif
+
+/*
+ * XSI attributes.  In the ncurses implementation, they are identical to the
+ * A_ attributes.
+ */
+#define WA_ATTRIBUTES	A_ATTRIBUTES
+#define WA_NORMAL	A_NORMAL
+#define WA_STANDOUT	A_STANDOUT
+#define WA_UNDERLINE	A_UNDERLINE
+#define WA_REVERSE	A_REVERSE
+#define WA_BLINK	A_BLINK
+#define WA_DIM		A_DIM
+#define WA_BOLD		A_BOLD
+#define WA_ALTCHARSET	A_ALTCHARSET
+#define WA_INVIS	A_INVIS
+#define WA_PROTECT	A_PROTECT
+#define WA_HORIZONTAL	A_HORIZONTAL
+#define WA_LEFT		A_LEFT
+#define WA_LOW		A_LOW
+#define WA_RIGHT	A_RIGHT
+#define WA_TOP		A_TOP
+#define WA_VERTICAL	A_VERTICAL
+
+/* colors */
+extern NCURSES_EXPORT_VAR(int) COLORS;
+extern NCURSES_EXPORT_VAR(int) COLOR_PAIRS;
+
+#define COLOR_BLACK	0
+#define COLOR_RED	1
+#define COLOR_GREEN	2
+#define COLOR_YELLOW	3
+#define COLOR_BLUE	4
+#define COLOR_MAGENTA	5
+#define COLOR_CYAN	6
+#define COLOR_WHITE	7
+
+/* line graphics */
+
+#if 0
+extern NCURSES_EXPORT_VAR(chtype*) _nc_acs_map(void);
+#define acs_map (_nc_acs_map())
+#else
+extern NCURSES_EXPORT_VAR(chtype) acs_map[];
+#endif
+
+#define NCURSES_ACS(c)	(acs_map[NCURSES_CAST(unsigned char,c)])
+
+/* VT100 symbols begin here */
+#define ACS_ULCORNER	NCURSES_ACS('l') /* upper left corner */
+#define ACS_LLCORNER	NCURSES_ACS('m') /* lower left corner */
+#define ACS_URCORNER	NCURSES_ACS('k') /* upper right corner */
+#define ACS_LRCORNER	NCURSES_ACS('j') /* lower right corner */
+#define ACS_LTEE	NCURSES_ACS('t') /* tee pointing right */
+#define ACS_RTEE	NCURSES_ACS('u') /* tee pointing left */
+#define ACS_BTEE	NCURSES_ACS('v') /* tee pointing up */
+#define ACS_TTEE	NCURSES_ACS('w') /* tee pointing down */
+#define ACS_HLINE	NCURSES_ACS('q') /* horizontal line */
+#define ACS_VLINE	NCURSES_ACS('x') /* vertical line */
+#define ACS_PLUS	NCURSES_ACS('n') /* large plus or crossover */
+#define ACS_S1		NCURSES_ACS('o') /* scan line 1 */
+#define ACS_S9		NCURSES_ACS('s') /* scan line 9 */
+#define ACS_DIAMOND	NCURSES_ACS('`') /* diamond */
+#define ACS_CKBOARD	NCURSES_ACS('a') /* checker board (stipple) */
+#define ACS_DEGREE	NCURSES_ACS('f') /* degree symbol */
+#define ACS_PLMINUS	NCURSES_ACS('g') /* plus/minus */
+#define ACS_BULLET	NCURSES_ACS('~') /* bullet */
+/* Teletype 5410v1 symbols begin here */
+#define ACS_LARROW	NCURSES_ACS(',') /* arrow pointing left */
+#define ACS_RARROW	NCURSES_ACS('+') /* arrow pointing right */
+#define ACS_DARROW	NCURSES_ACS('.') /* arrow pointing down */
+#define ACS_UARROW	NCURSES_ACS('-') /* arrow pointing up */
+#define ACS_BOARD	NCURSES_ACS('h') /* board of squares */
+#define ACS_LANTERN	NCURSES_ACS('i') /* lantern symbol */
+#define ACS_BLOCK	NCURSES_ACS('0') /* solid square block */
+/*
+ * These aren't documented, but a lot of System Vs have them anyway
+ * (you can spot pprryyzz{{||}} in a lot of AT&T terminfo strings).
+ * The ACS_names may not match AT&T's, our source didn't know them.
+ */
+#define ACS_S3		NCURSES_ACS('p') /* scan line 3 */
+#define ACS_S7		NCURSES_ACS('r') /* scan line 7 */
+#define ACS_LEQUAL	NCURSES_ACS('y') /* less/equal */
+#define ACS_GEQUAL	NCURSES_ACS('z') /* greater/equal */
+#define ACS_PI		NCURSES_ACS('{') /* Pi */
+#define ACS_NEQUAL	NCURSES_ACS('|') /* not equal */
+#define ACS_STERLING	NCURSES_ACS('}') /* UK pound sign */
+
+/*
+ * Line drawing ACS names are of the form ACS_trbl, where t is the top, r
+ * is the right, b is the bottom, and l is the left.  t, r, b, and l might
+ * be B (blank), S (single), D (double), or T (thick).  The subset defined
+ * here only uses B and S.
+ */
+#define ACS_BSSB	ACS_ULCORNER
+#define ACS_SSBB	ACS_LLCORNER
+#define ACS_BBSS	ACS_URCORNER
+#define ACS_SBBS	ACS_LRCORNER
+#define ACS_SBSS	ACS_RTEE
+#define ACS_SSSB	ACS_LTEE
+#define ACS_SSBS	ACS_BTEE
+#define ACS_BSSS	ACS_TTEE
+#define ACS_BSBS	ACS_HLINE
+#define ACS_SBSB	ACS_VLINE
+#define ACS_SSSS	ACS_PLUS
+
+#undef	ERR
+#define ERR     (-1)
+
+#undef	OK
+#define OK      (0)
+
+/* values for the _flags member */
+#define _SUBWIN         0x01	/* is this a sub-window? */
+#define _ENDLINE        0x02	/* is the window flush right? */
+#define _FULLWIN        0x04	/* is the window full-screen? */
+#define _SCROLLWIN      0x08	/* bottom edge is at screen bottom? */
+#define _ISPAD	        0x10	/* is this window a pad? */
+#define _HASMOVED       0x20	/* has cursor moved since last refresh? */
+#define _WRAPPED        0x40	/* cursor was just wrappped */
+
+/*
+ * this value is used in the firstchar and lastchar fields to mark
+ * unchanged lines
+ */
+#define _NOCHANGE       -1
+
+/*
+ * this value is used in the oldindex field to mark lines created by insertions
+ * and scrolls.
+ */
+#define _NEWINDEX	-1
+
+typedef struct screen  SCREEN;
+typedef struct _win_st WINDOW;
+
+typedef	chtype	attr_t;		/* ...must be at least as wide as chtype */
+
+#ifdef _XOPEN_SOURCE_EXTENDED
+
+#if 0
+#ifdef mblen			/* libutf8.h defines it w/o undefining first */
+#undef mblen
+#endif
+#include <libutf8.h>
+#endif
+
+#if 1
+//// #include <wchar.h>		/* ...to get mbstate_t, etc. */
+//typedef unsigned long wchar_t;	// XXX
+typedef unsigned long wint_t;	// XXX
+#endif
+
+#if 0
+typedef unsigned short wchar_t1;
+#endif
+
+#if 0
+typedef unsigned int wint_t1;
+#endif
+
+#define CCHARW_MAX	5
+typedef struct
+{
+    attr_t	attr;
+    wchar_t	chars[CCHARW_MAX];
+#if 0
+    int		ext_color;	/* color pair, must be more than 16-bits */
+#endif
+}
+cchar_t;
+
+#endif /* _XOPEN_SOURCE_EXTENDED */
+
+struct ldat;
+
+struct _win_st
+{
+	NCURSES_SIZE_T _cury, _curx; /* current cursor position */
+
+	/* window location and size */
+	NCURSES_SIZE_T _maxy, _maxx; /* maximums of x and y, NOT window size */
+	NCURSES_SIZE_T _begy, _begx; /* screen coords of upper-left-hand corner */
+
+	short   _flags;		/* window state flags */
+
+	/* attribute tracking */
+	attr_t  _attrs;		/* current attribute for non-space character */
+	chtype  _bkgd;		/* current background char/attribute pair */
+
+	/* option values set by user */
+	bool	_notimeout;	/* no time out on function-key entry? */
+	bool	_clear;		/* consider all data in the window invalid? */
+	bool	_leaveok;	/* OK to not reset cursor on exit? */
+	bool	_scroll;	/* OK to scroll this window? */
+	bool	_idlok;		/* OK to use insert/delete line? */
+	bool	_idcok;		/* OK to use insert/delete char? */
+	bool	_immed;		/* window in immed mode? (not yet used) */
+	bool	_sync;		/* window in sync mode? */
+	bool	_use_keypad;	/* process function keys into KEY_ symbols? */
+	int	_delay;		/* 0 = nodelay, <0 = blocking, >0 = delay */
+
+	struct ldat *_line;	/* the actual line data */
+
+	/* global screen state */
+	NCURSES_SIZE_T _regtop;	/* top line of scrolling region */
+	NCURSES_SIZE_T _regbottom; /* bottom line of scrolling region */
+
+	/* these are used only if this is a sub-window */
+	int	_parx;		/* x coordinate of this window in parent */
+	int	_pary;		/* y coordinate of this window in parent */
+	WINDOW	*_parent;	/* pointer to parent if a sub-window */
+
+	/* these are used only if this is a pad */
+	struct pdat
+	{
+	    NCURSES_SIZE_T _pad_y,      _pad_x;
+	    NCURSES_SIZE_T _pad_top,    _pad_left;
+	    NCURSES_SIZE_T _pad_bottom, _pad_right;
+	} _pad;
+
+	NCURSES_SIZE_T _yoffset; /* real begy is _begy + _yoffset */
+
+#ifdef _XOPEN_SOURCE_EXTENDED
+	cchar_t  _bkgrnd;	/* current background char/attribute pair */
+//// #if 0
+#if 1
+	int	_color;		/* current color-pair for non-space character */
+#endif
+#endif
+};
+
+extern NCURSES_EXPORT_VAR(WINDOW *)   stdscr;
+extern NCURSES_EXPORT_VAR(WINDOW *)   curscr;
+extern NCURSES_EXPORT_VAR(WINDOW *)   newscr;
+
+extern NCURSES_EXPORT_VAR(int)	LINES;
+extern NCURSES_EXPORT_VAR(int)	COLS;
+extern NCURSES_EXPORT_VAR(int)	TABSIZE;
+
+/*
+ * This global was an undocumented feature under AIX curses.
+ */
+extern NCURSES_EXPORT_VAR(int) ESCDELAY;	/* ESC expire time in milliseconds */
+
+/*
+ * These functions are extensions - not in XSI Curses.
+ */
+#if 1
+extern NCURSES_EXPORT(bool) is_term_resized (int, int);
+extern NCURSES_EXPORT(char *) keybound (int, int);
+extern NCURSES_EXPORT(const char *) curses_version (void);
+extern NCURSES_EXPORT(int) assume_default_colors (int, int);
+extern NCURSES_EXPORT(int) define_key (const char *, int);
+extern NCURSES_EXPORT(int) key_defined (const char *);
+extern NCURSES_EXPORT(int) keyok (int, bool);
+extern NCURSES_EXPORT(int) resize_term (int, int);
+extern NCURSES_EXPORT(int) resizeterm (int, int);
+extern NCURSES_EXPORT(int) use_default_colors (void);
+extern NCURSES_EXPORT(int) use_extended_names (bool);
+extern NCURSES_EXPORT(int) use_legacy_coding (int);
+extern NCURSES_EXPORT(int) wresize (WINDOW *, int, int);
+extern NCURSES_EXPORT(void) nofilter(void);
+#else
+#define curses_version() NCURSES_VERSION
+#endif
+
+/*
+ * This is an extension to support events...
+ */
+#if 1
+#ifdef NCURSES_WGETCH_EVENTS
+#if !defined(__BEOS__)		/* Fix _nc_timed_wait() on BEOS... */
+#  define NCURSES_EVENT_VERSION	1
+#endif	/* !defined(__BEOS__) */
+
+/*
+ * Bits to set in _nc_event.data.flags
+ */
+#  define _NC_EVENT_TIMEOUT_MSEC	1
+#  define _NC_EVENT_FILE		2
+#  define _NC_EVENT_FILE_READABLE	2
+#  if 0					/* Not supported yet... */
+#    define _NC_EVENT_FILE_WRITABLE	4
+#    define _NC_EVENT_FILE_EXCEPTION	8
+#  endif
+
+typedef struct
+{
+    int type;
+    union
+    {
+	long timeout_msec;	/* _NC_EVENT_TIMEOUT_MSEC */
+	struct
+	{
+	    unsigned int flags;
+	    int fd;
+	    unsigned int result;
+	} fev;				/* _NC_EVENT_FILE */
+    } data;
+} _nc_event;
+
+typedef struct
+{
+    int count;
+    int result_flags;	/* _NC_EVENT_TIMEOUT_MSEC or _NC_EVENT_FILE_READABLE */
+    _nc_event *events[1];
+} _nc_eventlist;
+
+extern NCURSES_EXPORT(int) wgetch_events(WINDOW *, _nc_eventlist *);	/* experimental */
+extern NCURSES_EXPORT(int) wgetnstr_events(WINDOW *,char *,int,_nc_eventlist *);/* experimental */
+
+#endif /* NCURSES_WGETCH_EVENTS */
+#endif /* NCURSES_EXT_FUNCS */
+
+/*
+ * GCC (and some other compilers) define '__attribute__'; we're using this
+ * macro to alert the compiler to flag inconsistencies in printf/scanf-like
+ * function calls.  Just in case '__attribute__' isn't defined, make a dummy.
+ * Old versions of G++ do not accept it anyway, at least not consistently with
+ * GCC.
+ */
+#if !(defined(__GNUC__) || defined(__GNUG__) || defined(__attribute__))
+#define __attribute__(p) /* nothing */
+#endif
+
+/*
+ * We cannot define these in ncurses_cfg.h, since they require parameters to be
+ * passed (that is non-portable).  If you happen to be using gcc with warnings
+ * enabled, define
+ *	GCC_PRINTF
+ *	GCC_SCANF
+ * to improve checking of calls to printw(), etc.
+ */
+#ifndef GCC_PRINTFLIKE
+#if defined(GCC_PRINTF) && !defined(printf)
+#define GCC_PRINTFLIKE(fmt,var) __attribute__((format(printf,fmt,var)))
+#else
+#define GCC_PRINTFLIKE(fmt,var) /*nothing*/
+#endif
+#endif
+
+#ifndef GCC_SCANFLIKE
+#if defined(GCC_SCANF) && !defined(scanf)
+#define GCC_SCANFLIKE(fmt,var)  __attribute__((format(scanf,fmt,var)))
+#else
+#define GCC_SCANFLIKE(fmt,var)  /*nothing*/
+#endif
+#endif
+
+#ifndef	GCC_NORETURN
+#define	GCC_NORETURN /* nothing */
+#endif
+
+#ifndef	GCC_UNUSED
+#define	GCC_UNUSED /* nothing */
+#endif
+
+/*
+ * Function prototypes.  This is the complete XSI Curses list of required
+ * functions.  Those marked `generated' will have sources generated from the
+ * macro definitions later in this file, in order to satisfy XPG4.2
+ * requirements.
+ */
+
+extern NCURSES_EXPORT(int) addch (const chtype);			/* generated */
+extern NCURSES_EXPORT(int) addchnstr (const chtype *, int);		/* generated */
+extern NCURSES_EXPORT(int) addchstr (const chtype *);			/* generated */
+extern NCURSES_EXPORT(int) addnstr (const char *, int);			/* generated */
+extern NCURSES_EXPORT(int) addstr (const char *);			/* generated */
+extern NCURSES_EXPORT(int) attroff (NCURSES_ATTR_T);			/* generated */
+extern NCURSES_EXPORT(int) attron (NCURSES_ATTR_T);			/* generated */
+extern NCURSES_EXPORT(int) attrset (NCURSES_ATTR_T);			/* generated */
+extern NCURSES_EXPORT(int) attr_get (attr_t *, short *, void *);	/* generated */
+extern NCURSES_EXPORT(int) attr_off (attr_t, void *);			/* generated */
+extern NCURSES_EXPORT(int) attr_on (attr_t, void *);			/* generated */
+extern NCURSES_EXPORT(int) attr_set (attr_t, short, void *);		/* generated */
+extern NCURSES_EXPORT(int) baudrate (void);				/* implemented */
+extern NCURSES_EXPORT(int) beep  (void);				/* implemented */
+extern NCURSES_EXPORT(int) bkgd (chtype);				/* generated */
+extern NCURSES_EXPORT(void) bkgdset (chtype);				/* generated */
+extern NCURSES_EXPORT(int) border (chtype,chtype,chtype,chtype,chtype,chtype,chtype,chtype);	/* generated */
+extern NCURSES_EXPORT(int) box (WINDOW *, chtype, chtype);		/* generated */
+extern NCURSES_EXPORT(bool) can_change_color (void);			/* implemented */
+extern NCURSES_EXPORT(int) cbreak (void);				/* implemented */
+extern NCURSES_EXPORT(int) chgat (int, attr_t, short, const void *);	/* generated */
+extern NCURSES_EXPORT(int) clear (void);				/* generated */
+extern NCURSES_EXPORT(int) clearok (WINDOW *,bool);			/* implemented */
+extern NCURSES_EXPORT(int) clrtobot (void);				/* generated */
+extern NCURSES_EXPORT(int) clrtoeol (void);				/* generated */
+extern NCURSES_EXPORT(int) color_content (short,short*,short*,short*);	/* implemented */
+extern NCURSES_EXPORT(int) color_set (short,void*);			/* generated */
+extern NCURSES_EXPORT(int) COLOR_PAIR (int);				/* generated */
+extern NCURSES_EXPORT(int) copywin (const WINDOW*,WINDOW*,int,int,int,int,int,int,int);	/* implemented */
+extern NCURSES_EXPORT(int) curs_set (int);				/* implemented */
+extern NCURSES_EXPORT(int) def_prog_mode (void);			/* implemented */
+extern NCURSES_EXPORT(int) def_shell_mode (void);			/* implemented */
+extern NCURSES_EXPORT(int) delay_output (int);				/* implemented */
+extern NCURSES_EXPORT(int) delch (void);				/* generated */
+extern NCURSES_EXPORT(void) delscreen (SCREEN *);			/* implemented */
+extern NCURSES_EXPORT(int) delwin (WINDOW *);				/* implemented */
+extern NCURSES_EXPORT(int) deleteln (void);				/* generated */
+extern NCURSES_EXPORT(WINDOW *) derwin (WINDOW *,int,int,int,int);	/* implemented */
+extern NCURSES_EXPORT(int) doupdate (void);				/* implemented */
+extern NCURSES_EXPORT(WINDOW *) dupwin (WINDOW *);			/* implemented */
+extern NCURSES_EXPORT(int) echo (void);					/* implemented */
+extern NCURSES_EXPORT(int) echochar (const chtype);			/* generated */
+extern NCURSES_EXPORT(int) erase (void);				/* generated */
+extern NCURSES_EXPORT(int) endwin (void);				/* implemented */
+extern NCURSES_EXPORT(char) erasechar (void);				/* implemented */
+extern NCURSES_EXPORT(void) filter (void);				/* implemented */
+extern NCURSES_EXPORT(int) flash (void);				/* implemented */
+extern NCURSES_EXPORT(int) flushinp (void);				/* implemented */
+extern NCURSES_EXPORT(chtype) getbkgd (WINDOW *);			/* generated */
+extern NCURSES_EXPORT(int) getch (void);				/* generated */
+extern NCURSES_EXPORT(int) getnstr (char *, int);			/* generated */
+extern NCURSES_EXPORT(int) getstr (char *);				/* generated */
+extern NCURSES_EXPORT(WINDOW *) getwin (FILE *);			/* implemented */
+extern NCURSES_EXPORT(int) halfdelay (int);				/* implemented */
+extern NCURSES_EXPORT(bool) has_colors (void);				/* implemented */
+extern NCURSES_EXPORT(bool) has_ic (void);				/* implemented */
+extern NCURSES_EXPORT(bool) has_il (void);				/* implemented */
+extern NCURSES_EXPORT(int) hline (chtype, int);				/* generated */
+extern NCURSES_EXPORT(void) idcok (WINDOW *, bool);			/* implemented */
+extern NCURSES_EXPORT(int) idlok (WINDOW *, bool);			/* implemented */
+extern NCURSES_EXPORT(void) immedok (WINDOW *, bool);			/* implemented */
+extern NCURSES_EXPORT(chtype) inch (void);				/* generated */
+extern NCURSES_EXPORT(int) inchnstr (chtype *, int);			/* generated */
+extern NCURSES_EXPORT(int) inchstr (chtype *);				/* generated */
+extern NCURSES_EXPORT(WINDOW *) initscr (void);				/* implemented */
+extern NCURSES_EXPORT(int) init_color (short,short,short,short);	/* implemented */
+extern NCURSES_EXPORT(int) init_pair (short,short,short);		/* implemented */
+extern NCURSES_EXPORT(int) innstr (char *, int);			/* generated */
+extern NCURSES_EXPORT(int) insch (chtype);				/* generated */
+extern NCURSES_EXPORT(int) insdelln (int);				/* generated */
+extern NCURSES_EXPORT(int) insertln (void);				/* generated */
+extern NCURSES_EXPORT(int) insnstr (const char *, int);			/* generated */
+extern NCURSES_EXPORT(int) insstr (const char *);			/* generated */
+extern NCURSES_EXPORT(int) instr (char *);				/* generated */
+extern NCURSES_EXPORT(int) intrflush (WINDOW *,bool);			/* implemented */
+extern NCURSES_EXPORT(bool) isendwin (void);				/* implemented */
+extern NCURSES_EXPORT(bool) is_linetouched (WINDOW *,int);		/* implemented */
+extern NCURSES_EXPORT(bool) is_wintouched (WINDOW *);			/* implemented */
+extern NCURSES_EXPORT(NCURSES_CONST char *) keyname (int);		/* implemented */
+extern NCURSES_EXPORT(int) keypad (WINDOW *,bool);			/* implemented */
+extern NCURSES_EXPORT(char) killchar (void);				/* implemented */
+extern NCURSES_EXPORT(int) leaveok (WINDOW *,bool);			/* implemented */
+extern NCURSES_EXPORT(char *) longname (void);				/* implemented */
+extern NCURSES_EXPORT(int) meta (WINDOW *,bool);			/* implemented */
+extern NCURSES_EXPORT(int) move (int, int);				/* generated */
+extern NCURSES_EXPORT(int) mvaddch (int, int, const chtype);		/* generated */
+extern NCURSES_EXPORT(int) mvaddchnstr (int, int, const chtype *, int);	/* generated */
+extern NCURSES_EXPORT(int) mvaddchstr (int, int, const chtype *);	/* generated */
+extern NCURSES_EXPORT(int) mvaddnstr (int, int, const char *, int);	/* generated */
+extern NCURSES_EXPORT(int) mvaddstr (int, int, const char *);		/* generated */
+extern NCURSES_EXPORT(int) mvchgat (int, int, int, attr_t, short, const void *);	/* generated */
+extern NCURSES_EXPORT(int) mvcur (int,int,int,int);			/* implemented */
+extern NCURSES_EXPORT(int) mvdelch (int, int);				/* generated */
+extern NCURSES_EXPORT(int) mvderwin (WINDOW *, int, int);		/* implemented */
+extern NCURSES_EXPORT(int) mvgetch (int, int);				/* generated */
+extern NCURSES_EXPORT(int) mvgetnstr (int, int, char *, int);		/* generated */
+extern NCURSES_EXPORT(int) mvgetstr (int, int, char *);			/* generated */
+extern NCURSES_EXPORT(int) mvhline (int, int, chtype, int);		/* generated */
+extern NCURSES_EXPORT(chtype) mvinch (int, int);			/* generated */
+extern NCURSES_EXPORT(int) mvinchnstr (int, int, chtype *, int);	/* generated */
+extern NCURSES_EXPORT(int) mvinchstr (int, int, chtype *);		/* generated */
+extern NCURSES_EXPORT(int) mvinnstr (int, int, char *, int);		/* generated */
+extern NCURSES_EXPORT(int) mvinsch (int, int, chtype);			/* generated */
+extern NCURSES_EXPORT(int) mvinsnstr (int, int, const char *, int);	/* generated */
+extern NCURSES_EXPORT(int) mvinsstr (int, int, const char *);		/* generated */
+extern NCURSES_EXPORT(int) mvinstr (int, int, char *);			/* generated */
+extern NCURSES_EXPORT(int) mvprintw (int,int, const char *,...)		/* implemented */
+		GCC_PRINTFLIKE(3,4);
+extern NCURSES_EXPORT(int) mvscanw (int,int, NCURSES_CONST char *,...)	/* implemented */
+		GCC_SCANFLIKE(3,4);
+extern NCURSES_EXPORT(int) mvvline (int, int, chtype, int);		/* generated */
+extern NCURSES_EXPORT(int) mvwaddch (WINDOW *, int, int, const chtype);	/* generated */
+extern NCURSES_EXPORT(int) mvwaddchnstr (WINDOW *, int, int, const chtype *, int);/* generated */
+extern NCURSES_EXPORT(int) mvwaddchstr (WINDOW *, int, int, const chtype *);	/* generated */
+extern NCURSES_EXPORT(int) mvwaddnstr (WINDOW *, int, int, const char *, int);	/* generated */
+extern NCURSES_EXPORT(int) mvwaddstr (WINDOW *, int, int, const char *);	/* generated */
+extern NCURSES_EXPORT(int) mvwchgat (WINDOW *, int, int, int, attr_t, short, const void *);/* generated */
+extern NCURSES_EXPORT(int) mvwdelch (WINDOW *, int, int);		/* generated */
+extern NCURSES_EXPORT(int) mvwgetch (WINDOW *, int, int);		/* generated */
+extern NCURSES_EXPORT(int) mvwgetnstr (WINDOW *, int, int, char *, int);	/* generated */
+extern NCURSES_EXPORT(int) mvwgetstr (WINDOW *, int, int, char *);	/* generated */
+extern NCURSES_EXPORT(int) mvwhline (WINDOW *, int, int, chtype, int);	/* generated */
+extern NCURSES_EXPORT(int) mvwin (WINDOW *,int,int);			/* implemented */
+extern NCURSES_EXPORT(chtype) mvwinch (WINDOW *, int, int);			/* generated */
+extern NCURSES_EXPORT(int) mvwinchnstr (WINDOW *, int, int, chtype *, int);	/* generated */
+extern NCURSES_EXPORT(int) mvwinchstr (WINDOW *, int, int, chtype *);		/* generated */
+extern NCURSES_EXPORT(int) mvwinnstr (WINDOW *, int, int, char *, int);		/* generated */
+extern NCURSES_EXPORT(int) mvwinsch (WINDOW *, int, int, chtype);		/* generated */
+extern NCURSES_EXPORT(int) mvwinsnstr (WINDOW *, int, int, const char *, int);	/* generated */
+extern NCURSES_EXPORT(int) mvwinsstr (WINDOW *, int, int, const char *);		/* generated */
+extern NCURSES_EXPORT(int) mvwinstr (WINDOW *, int, int, char *);		/* generated */
+extern NCURSES_EXPORT(int) mvwprintw (WINDOW*,int,int, const char *,...)	/* implemented */
+		GCC_PRINTFLIKE(4,5);
+extern NCURSES_EXPORT(int) mvwscanw (WINDOW *,int,int, NCURSES_CONST char *,...)	/* implemented */
+		GCC_SCANFLIKE(4,5);
+extern NCURSES_EXPORT(int) mvwvline (WINDOW *,int, int, chtype, int);	/* generated */
+extern NCURSES_EXPORT(int) napms (int);					/* implemented */
+extern NCURSES_EXPORT(WINDOW *) newpad (int,int);				/* implemented */
+extern NCURSES_EXPORT(SCREEN *) newterm (NCURSES_CONST char *,FILE *,FILE *);	/* implemented */
+extern NCURSES_EXPORT(WINDOW *) newwin (int,int,int,int);			/* implemented */
+extern NCURSES_EXPORT(int) nl (void);					/* implemented */
+extern NCURSES_EXPORT(int) nocbreak (void);				/* implemented */
+extern NCURSES_EXPORT(int) nodelay (WINDOW *,bool);			/* implemented */
+extern NCURSES_EXPORT(int) noecho (void);				/* implemented */
+extern NCURSES_EXPORT(int) nonl (void);					/* implemented */
+extern NCURSES_EXPORT(void) noqiflush (void);				/* implemented */
+extern NCURSES_EXPORT(int) noraw (void);				/* implemented */
+extern NCURSES_EXPORT(int) notimeout (WINDOW *,bool);			/* implemented */
+extern NCURSES_EXPORT(int) overlay (const WINDOW*,WINDOW *);		/* implemented */
+extern NCURSES_EXPORT(int) overwrite (const WINDOW*,WINDOW *);		/* implemented */
+extern NCURSES_EXPORT(int) pair_content (short,short*,short*);		/* implemented */
+extern NCURSES_EXPORT(int) PAIR_NUMBER (int);				/* generated */
+extern NCURSES_EXPORT(int) pechochar (WINDOW *, const chtype);		/* implemented */
+extern NCURSES_EXPORT(int) pnoutrefresh (WINDOW*,int,int,int,int,int,int);/* implemented */
+extern NCURSES_EXPORT(int) prefresh (WINDOW *,int,int,int,int,int,int);	/* implemented */
+extern NCURSES_EXPORT(int) printw (const char *,...)			/* implemented */
+		GCC_PRINTFLIKE(1,2);
+extern NCURSES_EXPORT(int) putwin (WINDOW *, FILE *);			/* implemented */
+extern NCURSES_EXPORT(void) qiflush (void);				/* implemented */
+extern NCURSES_EXPORT(int) raw (void);					/* implemented */
+extern NCURSES_EXPORT(int) redrawwin (WINDOW *);			/* generated */
+extern NCURSES_EXPORT(int) refresh (void);				/* generated */
+extern NCURSES_EXPORT(int) resetty (void);				/* implemented */
+extern NCURSES_EXPORT(int) reset_prog_mode (void);			/* implemented */
+extern NCURSES_EXPORT(int) reset_shell_mode (void);			/* implemented */
+extern NCURSES_EXPORT(int) ripoffline (int, int (*)(WINDOW *, int));	/* implemented */
+extern NCURSES_EXPORT(int) savetty (void);				/* implemented */
+extern NCURSES_EXPORT(int) scanw (NCURSES_CONST char *,...)		/* implemented */
+		GCC_SCANFLIKE(1,2);
+extern NCURSES_EXPORT(int) scr_dump (const char *);			/* implemented */
+extern NCURSES_EXPORT(int) scr_init (const char *);			/* implemented */
+extern NCURSES_EXPORT(int) scrl (int);					/* generated */
+extern NCURSES_EXPORT(int) scroll (WINDOW *);				/* generated */
+extern NCURSES_EXPORT(int) scrollok (WINDOW *,bool);			/* implemented */
+extern NCURSES_EXPORT(int) scr_restore (const char *);			/* implemented */
+extern NCURSES_EXPORT(int) scr_set (const char *);			/* implemented */
+extern NCURSES_EXPORT(int) setscrreg (int,int);				/* generated */
+extern NCURSES_EXPORT(SCREEN *) set_term (SCREEN *);			/* implemented */
+extern NCURSES_EXPORT(int) slk_attroff (const chtype);			/* implemented */
+extern NCURSES_EXPORT(int) slk_attr_off (const attr_t, void *);		/* generated:WIDEC */
+extern NCURSES_EXPORT(int) slk_attron (const chtype);			/* implemented */
+extern NCURSES_EXPORT(int) slk_attr_on (attr_t,void*);			/* generated:WIDEC */
+extern NCURSES_EXPORT(int) slk_attrset (const chtype);			/* implemented */
+extern NCURSES_EXPORT(attr_t) slk_attr (void);				/* implemented */
+extern NCURSES_EXPORT(int) slk_attr_set (const attr_t,short,void*);	/* implemented */
+extern NCURSES_EXPORT(int) slk_clear (void);				/* implemented */
+extern NCURSES_EXPORT(int) slk_color (short);				/* implemented */
+extern NCURSES_EXPORT(int) slk_init (int);				/* implemented */
+extern NCURSES_EXPORT(char *) slk_label (int);				/* implemented */
+extern NCURSES_EXPORT(int) slk_noutrefresh (void);			/* implemented */
+extern NCURSES_EXPORT(int) slk_refresh (void);				/* implemented */
+extern NCURSES_EXPORT(int) slk_restore (void);				/* implemented */
+extern NCURSES_EXPORT(int) slk_set (int,const char *,int);		/* implemented */
+extern NCURSES_EXPORT(int) slk_touch (void);				/* implemented */
+extern NCURSES_EXPORT(int) standout (void);				/* generated */
+extern NCURSES_EXPORT(int) standend (void);				/* generated */
+extern NCURSES_EXPORT(int) start_color (void);				/* implemented */
+extern NCURSES_EXPORT(WINDOW *) subpad (WINDOW *, int, int, int, int);	/* implemented */
+extern NCURSES_EXPORT(WINDOW *) subwin (WINDOW *,int,int,int,int);	/* implemented */
+extern NCURSES_EXPORT(int) syncok (WINDOW *, bool);			/* implemented */
+extern NCURSES_EXPORT(chtype) termattrs (void);				/* implemented */
+extern NCURSES_EXPORT(char *) termname (void);				/* implemented */
+extern NCURSES_EXPORT(void) timeout (int);				/* generated */
+extern NCURSES_EXPORT(int) touchline (WINDOW *, int, int);		/* generated */
+extern NCURSES_EXPORT(int) touchwin (WINDOW *);				/* generated */
+extern NCURSES_EXPORT(int) typeahead (int);				/* implemented */
+extern NCURSES_EXPORT(int) ungetch (int);				/* implemented */
+extern NCURSES_EXPORT(int) untouchwin (WINDOW *);			/* generated */
+extern NCURSES_EXPORT(void) use_env (bool);				/* implemented */
+extern NCURSES_EXPORT(int) vidattr (chtype);				/* implemented */
+extern NCURSES_EXPORT(int) vidputs (chtype, int (*)(int));		/* implemented */
+extern NCURSES_EXPORT(int) vline (chtype, int);				/* generated */
+extern NCURSES_EXPORT(int) vwprintw (WINDOW *, const char *,va_list);	/* implemented */
+extern NCURSES_EXPORT(int) vw_printw (WINDOW *, const char *,va_list);	/* generated */
+extern NCURSES_EXPORT(int) vwscanw (WINDOW *, NCURSES_CONST char *,va_list);	/* implemented */
+extern NCURSES_EXPORT(int) vw_scanw (WINDOW *, NCURSES_CONST char *,va_list);	/* generated */
+extern NCURSES_EXPORT(int) waddch (WINDOW *, const chtype);		/* implemented */
+extern NCURSES_EXPORT(int) waddchnstr (WINDOW *,const chtype *,int);	/* implemented */
+extern NCURSES_EXPORT(int) waddchstr (WINDOW *,const chtype *);		/* generated */
+extern NCURSES_EXPORT(int) waddnstr (WINDOW *,const char *,int);	/* implemented */
+extern NCURSES_EXPORT(int) waddstr (WINDOW *,const char *);		/* generated */
+extern NCURSES_EXPORT(int) wattron (WINDOW *, int);			/* generated */
+extern NCURSES_EXPORT(int) wattroff (WINDOW *, int);			/* generated */
+extern NCURSES_EXPORT(int) wattrset (WINDOW *, int);			/* generated */
+extern NCURSES_EXPORT(int) wattr_get (WINDOW *, attr_t *, short *, void *);	/* generated */
+extern NCURSES_EXPORT(int) wattr_on (WINDOW *, attr_t, void *);		/* implemented */
+extern NCURSES_EXPORT(int) wattr_off (WINDOW *, attr_t, void *);	/* implemented */
+extern NCURSES_EXPORT(int) wattr_set (WINDOW *, attr_t, short, void *);	/* generated */
+extern NCURSES_EXPORT(int) wbkgd (WINDOW *, chtype);			/* implemented */
+extern NCURSES_EXPORT(void) wbkgdset (WINDOW *,chtype);			/* implemented */
+extern NCURSES_EXPORT(int) wborder (WINDOW *,chtype,chtype,chtype,chtype,chtype,chtype,chtype,chtype);	/* implemented */
+extern NCURSES_EXPORT(int) wchgat (WINDOW *, int, attr_t, short, const void *);/* implemented */
+extern NCURSES_EXPORT(int) wclear (WINDOW *);				/* implemented */
+extern NCURSES_EXPORT(int) wclrtobot (WINDOW *);			/* implemented */
+extern NCURSES_EXPORT(int) wclrtoeol (WINDOW *);			/* implemented */
+extern NCURSES_EXPORT(int) wcolor_set (WINDOW*,short,void*);		/* implemented */
+extern NCURSES_EXPORT(void) wcursyncup (WINDOW *);			/* implemented */
+extern NCURSES_EXPORT(int) wdelch (WINDOW *);				/* implemented */
+extern NCURSES_EXPORT(int) wdeleteln (WINDOW *);			/* generated */
+extern NCURSES_EXPORT(int) wechochar (WINDOW *, const chtype);		/* implemented */
+extern NCURSES_EXPORT(int) werase (WINDOW *);				/* implemented */
+extern NCURSES_EXPORT(int) wgetch (WINDOW *);				/* implemented */
+extern NCURSES_EXPORT(int) wgetnstr (WINDOW *,char *,int);		/* implemented */
+extern NCURSES_EXPORT(int) wgetstr (WINDOW *, char *);			/* generated */
+extern NCURSES_EXPORT(int) whline (WINDOW *, chtype, int);		/* implemented */
+extern NCURSES_EXPORT(chtype) winch (WINDOW *);				/* implemented */
+extern NCURSES_EXPORT(int) winchnstr (WINDOW *, chtype *, int);		/* implemented */
+extern NCURSES_EXPORT(int) winchstr (WINDOW *, chtype *);		/* generated */
+extern NCURSES_EXPORT(int) winnstr (WINDOW *, char *, int);		/* implemented */
+extern NCURSES_EXPORT(int) winsch (WINDOW *, chtype);			/* implemented */
+extern NCURSES_EXPORT(int) winsdelln (WINDOW *,int);			/* implemented */
+extern NCURSES_EXPORT(int) winsertln (WINDOW *);			/* generated */
+extern NCURSES_EXPORT(int) winsnstr (WINDOW *, const char *,int);	/* implemented */
+extern NCURSES_EXPORT(int) winsstr (WINDOW *, const char *);		/* generated */
+extern NCURSES_EXPORT(int) winstr (WINDOW *, char *);			/* generated */
+extern NCURSES_EXPORT(int) wmove (WINDOW *,int,int);			/* implemented */
+extern NCURSES_EXPORT(int) wnoutrefresh (WINDOW *);			/* implemented */
+extern NCURSES_EXPORT(int) wprintw (WINDOW *, const char *,...)		/* implemented */
+		GCC_PRINTFLIKE(2,3);
+extern NCURSES_EXPORT(int) wredrawln (WINDOW *,int,int);		/* implemented */
+extern NCURSES_EXPORT(int) wrefresh (WINDOW *);				/* implemented */
+extern NCURSES_EXPORT(int) wscanw (WINDOW *, NCURSES_CONST char *,...)	/* implemented */
+		GCC_SCANFLIKE(2,3);
+extern NCURSES_EXPORT(int) wscrl (WINDOW *,int);			/* implemented */
+extern NCURSES_EXPORT(int) wsetscrreg (WINDOW *,int,int);		/* implemented */
+extern NCURSES_EXPORT(int) wstandout (WINDOW *);			/* generated */
+extern NCURSES_EXPORT(int) wstandend (WINDOW *);			/* generated */
+extern NCURSES_EXPORT(void) wsyncdown (WINDOW *);			/* implemented */
+extern NCURSES_EXPORT(void) wsyncup (WINDOW *);				/* implemented */
+extern NCURSES_EXPORT(void) wtimeout (WINDOW *,int);			/* implemented */
+extern NCURSES_EXPORT(int) wtouchln (WINDOW *,int,int,int);		/* implemented */
+extern NCURSES_EXPORT(int) wvline (WINDOW *,chtype,int);		/* implemented */
+
+/*
+ * These are also declared in <ncursesw/term.h>:
+ */
+extern NCURSES_EXPORT(int) tigetflag (NCURSES_CONST char *);		/* implemented */
+extern NCURSES_EXPORT(int) tigetnum (NCURSES_CONST char *);		/* implemented */
+extern NCURSES_EXPORT(char *) tigetstr (NCURSES_CONST char *);		/* implemented */
+extern NCURSES_EXPORT(int) putp (const char *);				/* implemented */
+
+#if NCURSES_TPARM_VARARGS
+extern NCURSES_EXPORT(char *) tparm (NCURSES_CONST char *, ...);	/* implemented */
+#else
+extern NCURSES_EXPORT(char *) tparm (NCURSES_CONST char *, long,long,long,long,long,long,long,long,long);	/* implemented */
+extern NCURSES_EXPORT(char *) tparm_varargs (NCURSES_CONST char *, ...);	/* implemented */
+#endif
+
+extern NCURSES_EXPORT_VAR(char) ttytype[];	/* needed for backward compatibility */
+
+/*
+ * These functions are not in X/Open, but we use them in macro definitions:
+ */
+extern NCURSES_EXPORT(int) getcurx (const WINDOW *);			/* generated */
+extern NCURSES_EXPORT(int) getcury (const WINDOW *);			/* generated */
+extern NCURSES_EXPORT(int) getbegx (const WINDOW *);			/* generated */
+extern NCURSES_EXPORT(int) getbegy (const WINDOW *);			/* generated */
+extern NCURSES_EXPORT(int) getmaxx (const WINDOW *);			/* generated */
+extern NCURSES_EXPORT(int) getmaxy (const WINDOW *);			/* generated */
+extern NCURSES_EXPORT(int) getparx (const WINDOW *);			/* generated */
+extern NCURSES_EXPORT(int) getpary (const WINDOW *);			/* generated */
+
+/*
+ * vid_attr() was implemented originally based on a draft of XSI curses.
+ */
+#ifndef _XOPEN_SOURCE_EXTENDED
+#define vid_attr(a,pair,opts) vidattr(a)
+#endif
+
+/* attributes */
+
+#define NCURSES_ATTR_SHIFT       8
+#define NCURSES_BITS(mask,shift) ((mask) << ((shift) + NCURSES_ATTR_SHIFT))
+
+#define A_NORMAL	(1UL - 1UL)
+#define A_ATTRIBUTES	NCURSES_BITS(~(1UL - 1UL),0)
+#define A_CHARTEXT	(NCURSES_BITS(1UL,0) - 1UL)
+#define A_COLOR		NCURSES_BITS(((1UL) << 8) - 1UL,0)
+#define A_STANDOUT	NCURSES_BITS(1UL,8)
+#define A_UNDERLINE	NCURSES_BITS(1UL,9)
+#define A_REVERSE	NCURSES_BITS(1UL,10)
+#define A_BLINK		NCURSES_BITS(1UL,11)
+#define A_DIM		NCURSES_BITS(1UL,12)
+#define A_BOLD		NCURSES_BITS(1UL,13)
+#define A_ALTCHARSET	NCURSES_BITS(1UL,14)
+#define A_INVIS		NCURSES_BITS(1UL,15)
+#define A_PROTECT	NCURSES_BITS(1UL,16)
+#define A_HORIZONTAL	NCURSES_BITS(1UL,17)
+#define A_LEFT		NCURSES_BITS(1UL,18)
+#define A_LOW		NCURSES_BITS(1UL,19)
+#define A_RIGHT		NCURSES_BITS(1UL,20)
+#define A_TOP		NCURSES_BITS(1UL,21)
+#define A_VERTICAL	NCURSES_BITS(1UL,22)
+
+/*
+ * Most of the pseudo functions are macros that either provide compatibility
+ * with older versions of curses, or provide inline functionality to improve
+ * performance.
+ */
+
+/*
+ * These pseudo functions are always implemented as macros:
+ */
+
+#define getyx(win,y,x)   	(y = getcury(win), x = getcurx(win))
+#define getbegyx(win,y,x)	(y = getbegy(win), x = getbegx(win))
+#define getmaxyx(win,y,x)	(y = getmaxy(win), x = getmaxx(win))
+#define getparyx(win,y,x)	(y = getpary(win), x = getparx(win))
+
+#define getsyx(y,x) do { if(newscr->_leaveok) (y)=(x)=-1; \
+			 else getyx(newscr,(y),(x)); \
+		    } while(0)
+#define setsyx(y,x) do { if((y)==-1 && (x)==-1) newscr->_leaveok=TRUE; \
+			 else {newscr->_leaveok=FALSE;wmove(newscr,(y),(x));} \
+		    } while(0)
+
+#ifndef NCURSES_NOMACROS
+
+/*
+ * These miscellaneous pseudo functions are provided for compatibility:
+ */
+
+#define wgetstr(w, s)		wgetnstr(w, s, -1)
+#define getnstr(s, n)		wgetnstr(stdscr, s, n)
+
+#define setterm(term)		setupterm(term, 1, (int *)0)
+
+#define fixterm()		reset_prog_mode()
+#define resetterm()		reset_shell_mode()
+#define saveterm()		def_prog_mode()
+#define crmode()		cbreak()
+#define nocrmode()		nocbreak()
+#define gettmode()
+
+/* It seems older SYSV curses versions define these */
+#define getattrs(win)		((win)?(win)->_attrs:A_NORMAL)
+#define getcurx(win)		((win)?(win)->_curx:ERR)
+#define getcury(win)		((win)?(win)->_cury:ERR)
+#define getbegx(win)		((win)?(win)->_begx:ERR)
+#define getbegy(win)		((win)?(win)->_begy:ERR)
+#define getmaxx(win)		((win)?((win)->_maxx + 1):ERR)
+#define getmaxy(win)		((win)?((win)->_maxy + 1):ERR)
+#define getparx(win)		((win)?(win)->_parx:ERR)
+#define getpary(win)		((win)?(win)->_pary:ERR)
+
+#define wstandout(win)      	(wattrset(win,A_STANDOUT))
+#define wstandend(win)      	(wattrset(win,A_NORMAL))
+
+#define wattron(win,at)		wattr_on(win, NCURSES_CAST(attr_t, at), NULL)
+#define wattroff(win,at)	wattr_off(win, NCURSES_CAST(attr_t, at), NULL)
+
+#if defined(_XOPEN_SOURCE_EXTENDED) && 0
+#define wattrset(win,at)	((win)->_color = PAIR_NUMBER(at), \
+				 (win)->_attrs = (at))
+#else
+#define wattrset(win,at)	((win)->_attrs = (at))
+#endif
+
+#define scroll(win)		wscrl(win,1)
+
+#define touchwin(win)		wtouchln((win), 0, getmaxy(win), 1)
+#define touchline(win, s, c)	wtouchln((win), s, c, 1)
+#define untouchwin(win)		wtouchln((win), 0, getmaxy(win), 0)
+
+#define box(win, v, h)		wborder(win, v, v, h, h, 0, 0, 0, 0)
+#define border(ls, rs, ts, bs, tl, tr, bl, br)	wborder(stdscr, ls, rs, ts, bs, tl, tr, bl, br)
+#define hline(ch, n)		whline(stdscr, ch, n)
+#define vline(ch, n)		wvline(stdscr, ch, n)
+
+#define winstr(w, s)		winnstr(w, s, -1)
+#define winchstr(w, s)		winchnstr(w, s, -1)
+#define winsstr(w, s)		winsnstr(w, s, -1)
+
+#define redrawwin(win)		wredrawln(win, 0, (win)->_maxy+1)
+#define waddstr(win,str)	waddnstr(win,str,-1)
+#define waddchstr(win,str)	waddchnstr(win,str,-1)
+
+/*
+ * These apply to the first 256 color pairs.
+ */
+#define COLOR_PAIR(n)	NCURSES_BITS(n, 0)
+#define PAIR_NUMBER(a)	(NCURSES_CAST(int,(((a) & A_COLOR) >> NCURSES_ATTR_SHIFT)))
+
+/*
+ * pseudo functions for standard screen
+ */
+
+#define addch(ch)		waddch(stdscr,ch)
+#define addchnstr(str,n)	waddchnstr(stdscr,str,n)
+#define addchstr(str)		waddchstr(stdscr,str)
+#define addnstr(str,n)		waddnstr(stdscr,str,n)
+#define addstr(str)		waddnstr(stdscr,str,-1)
+#define attroff(at)		wattroff(stdscr,at)
+#define attron(at)		wattron(stdscr,at)
+#define attrset(at)		wattrset(stdscr,at)
+#define attr_get(ap,cp,o)	wattr_get(stdscr,ap,cp,o)
+#define attr_off(a,o)		wattr_off(stdscr,a,o)
+#define attr_on(a,o)		wattr_on(stdscr,a,o)
+#define attr_set(a,c,o)		wattr_set(stdscr,a,c,o)
+#define bkgd(ch)		wbkgd(stdscr,ch)
+#define bkgdset(ch)		wbkgdset(stdscr,ch)
+#define chgat(n,a,c,o)		wchgat(stdscr,n,a,c,o)
+#define clear()			wclear(stdscr)
+#define clrtobot()		wclrtobot(stdscr)
+#define clrtoeol()		wclrtoeol(stdscr)
+#define color_set(c,o)		wcolor_set(stdscr,c,o)
+#define delch()			wdelch(stdscr)
+#define deleteln()		winsdelln(stdscr,-1)
+#define echochar(c)		wechochar(stdscr,c)
+#define erase()			werase(stdscr)
+#define getch()			wgetch(stdscr)
+#define getstr(str)		wgetstr(stdscr,str)
+#define inch()			winch(stdscr)
+#define inchnstr(s,n)		winchnstr(stdscr,s,n)
+#define inchstr(s)		winchstr(stdscr,s)
+#define innstr(s,n)		winnstr(stdscr,s,n)
+#define insch(c)		winsch(stdscr,c)
+#define insdelln(n)		winsdelln(stdscr,n)
+#define insertln()		winsdelln(stdscr,1)
+#define insnstr(s,n)		winsnstr(stdscr,s,n)
+#define insstr(s)		winsstr(stdscr,s)
+#define instr(s)		winstr(stdscr,s)
+#define move(y,x)		wmove(stdscr,y,x)
+#define refresh()		wrefresh(stdscr)
+#define scrl(n)			wscrl(stdscr,n)
+#define setscrreg(t,b)		wsetscrreg(stdscr,t,b)
+#define standend()		wstandend(stdscr)
+#define standout()		wstandout(stdscr)
+#define timeout(delay)		wtimeout(stdscr,delay)
+#define wdeleteln(win)		winsdelln(win,-1)
+#define winsertln(win)		winsdelln(win,1)
+
+/*
+ * mv functions
+ */
+
+#define mvwaddch(win,y,x,ch)		(wmove(win,y,x) == ERR ? ERR : waddch(win,ch))
+#define mvwaddchnstr(win,y,x,str,n)	(wmove(win,y,x) == ERR ? ERR : waddchnstr(win,str,n))
+#define mvwaddchstr(win,y,x,str)	(wmove(win,y,x) == ERR ? ERR : waddchnstr(win,str,-1))
+#define mvwaddnstr(win,y,x,str,n)	(wmove(win,y,x) == ERR ? ERR : waddnstr(win,str,n))
+#define mvwaddstr(win,y,x,str)		(wmove(win,y,x) == ERR ? ERR : waddnstr(win,str,-1))
+#define mvwdelch(win,y,x)		(wmove(win,y,x) == ERR ? ERR : wdelch(win))
+#define mvwchgat(win,y,x,n,a,c,o)	(wmove(win,y,x) == ERR ? ERR : wchgat(win,n,a,c,o))
+#define mvwgetch(win,y,x)		(wmove(win,y,x) == ERR ? ERR : wgetch(win))
+#define mvwgetnstr(win,y,x,str,n)	(wmove(win,y,x) == ERR ? ERR : wgetnstr(win,str,n))
+#define mvwgetstr(win,y,x,str)		(wmove(win,y,x) == ERR ? ERR : wgetstr(win,str))
+#define mvwhline(win,y,x,c,n)		(wmove(win,y,x) == ERR ? ERR : whline(win,c,n))
+#define mvwinch(win,y,x)		(wmove(win,y,x) == ERR ? NCURSES_CAST(chtype, ERR) : winch(win))
+#define mvwinchnstr(win,y,x,s,n)	(wmove(win,y,x) == ERR ? ERR : winchnstr(win,s,n))
+#define mvwinchstr(win,y,x,s)		(wmove(win,y,x) == ERR ? ERR : winchstr(win,s))
+#define mvwinnstr(win,y,x,s,n)		(wmove(win,y,x) == ERR ? ERR : winnstr(win,s,n))
+#define mvwinsch(win,y,x,c)		(wmove(win,y,x) == ERR ? ERR : winsch(win,c))
+#define mvwinsnstr(win,y,x,s,n)		(wmove(win,y,x) == ERR ? ERR : winsnstr(win,s,n))
+#define mvwinsstr(win,y,x,s)		(wmove(win,y,x) == ERR ? ERR : winsstr(win,s))
+#define mvwinstr(win,y,x,s)		(wmove(win,y,x) == ERR ? ERR : winstr(win,s))
+#define mvwvline(win,y,x,c,n)		(wmove(win,y,x) == ERR ? ERR : wvline(win,c,n))
+
+#define mvaddch(y,x,ch)			mvwaddch(stdscr,y,x,ch)
+#define mvaddchnstr(y,x,str,n)		mvwaddchnstr(stdscr,y,x,str,n)
+#define mvaddchstr(y,x,str)		mvwaddchstr(stdscr,y,x,str)
+#define mvaddnstr(y,x,str,n)		mvwaddnstr(stdscr,y,x,str,n)
+#define mvaddstr(y,x,str)		mvwaddstr(stdscr,y,x,str)
+#define mvchgat(y,x,n,a,c,o)		mvwchgat(stdscr,y,x,n,a,c,o)
+#define mvdelch(y,x)			mvwdelch(stdscr,y,x)
+#define mvgetch(y,x)			mvwgetch(stdscr,y,x)
+#define mvgetnstr(y,x,str,n)		mvwgetnstr(stdscr,y,x,str,n)
+#define mvgetstr(y,x,str)		mvwgetstr(stdscr,y,x,str)
+#define mvhline(y,x,c,n)		mvwhline(stdscr,y,x,c,n)
+#define mvinch(y,x)			mvwinch(stdscr,y,x)
+#define mvinchnstr(y,x,s,n)		mvwinchnstr(stdscr,y,x,s,n)
+#define mvinchstr(y,x,s)		mvwinchstr(stdscr,y,x,s)
+#define mvinnstr(y,x,s,n)		mvwinnstr(stdscr,y,x,s,n)
+#define mvinsch(y,x,c)			mvwinsch(stdscr,y,x,c)
+#define mvinsnstr(y,x,s,n)		mvwinsnstr(stdscr,y,x,s,n)
+#define mvinsstr(y,x,s)			mvwinsstr(stdscr,y,x,s)
+#define mvinstr(y,x,s)			mvwinstr(stdscr,y,x,s)
+#define mvvline(y,x,c,n)		mvwvline(stdscr,y,x,c,n)
+
+/*
+ * Some wide-character functions can be implemented without the extensions.
+ */
+#define getbkgd(win)                    ((win)->_bkgd)
+
+#define slk_attr_off(a,v)		((v) ? ERR : slk_attroff(a))
+#define slk_attr_on(a,v)		((v) ? ERR : slk_attron(a))
+
+#if defined(_XOPEN_SOURCE_EXTENDED) && 0
+#define wattr_set(win,a,p,opts)		((win)->_attrs = ((a) & ~A_COLOR), \
+					 (win)->_color = (p), \
+					 OK)
+#define wattr_get(win,a,p,opts)		((void)((a) != 0 && (*(a) = (win)->_attrs)), \
+					 (void)((p) != 0 && (*(p) = (win)->_color)), \
+					 OK)
+#else
+#define wattr_set(win,a,p,opts)		((win)->_attrs = (((a) & ~A_COLOR) | COLOR_PAIR(p)), OK)
+#define wattr_get(win,a,p,opts)		((void)((a) != 0 && (*(a) = (win)->_attrs)), \
+					 (void)((p) != 0 && (*(p) = PAIR_NUMBER((win)->_attrs))), \
+					 OK)
+#endif
+
+/*
+ * XSI curses deprecates SVr4 vwprintw/vwscanw, which are supposed to use
+ * varargs.h.  It adds new calls vw_printw/vw_scanw, which are supposed to
+ * use POSIX stdarg.h.  The ncurses versions of vwprintw/vwscanw already
+ * use stdarg.h, so...
+ */
+#define vw_printw		vwprintw
+#define vw_scanw		vwscanw
+
+/*
+ * Export fallback function for use in C++ binding.
+ */
+#if !1
+#define vsscanf(a,b,c) _nc_vsscanf(a,b,c)
+NCURSES_EXPORT(int) vsscanf(const char *, const char *, va_list);
+#endif
+
+#endif /* NCURSES_NOMACROS */
+
+/*
+ * Pseudo-character tokens outside ASCII range.  The curses wgetch() function
+ * will return any given one of these only if the corresponding k- capability
+ * is defined in your terminal's terminfo entry.
+ *
+ * Some keys (KEY_A1, etc) are arranged like this:
+ *	a1     up    a3
+ *	left   b2    right
+ *	c1     down  c3
+ *
+ * A few key codes do not depend upon the terminfo entry.
+ */
+#define KEY_CODE_YES	0400		/* A wchar_t contains a key code */
+#define KEY_MIN		0401		/* Minimum curses key */
+#define KEY_BREAK	0401		/* Break key (unreliable) */
+#define KEY_SRESET	0530		/* Soft (partial) reset (unreliable) */
+#define KEY_RESET	0531		/* Reset or hard reset (unreliable) */
+/*
+ * These definitions were generated by /home/user/ncurses-5.6/include/MKkey_defs.sh /home/user/ncurses-5.6/include/Caps
+ */
+#define KEY_DOWN	0402		/* down-arrow key */
+#define KEY_UP		0403		/* up-arrow key */
+#define KEY_LEFT	0404		/* left-arrow key */
+#define KEY_RIGHT	0405		/* right-arrow key */
+#define KEY_HOME	0406		/* home key */
+#define KEY_BACKSPACE	0407		/* backspace key */
+#define KEY_F0		0410		/* Function keys.  Space for 64 */
+#define KEY_F(n)	(KEY_F0+(n))	/* Value of function key n */
+#define KEY_DL		0510		/* delete-line key */
+#define KEY_IL		0511		/* insert-line key */
+#define KEY_DC		0512		/* delete-character key */
+#define KEY_IC		0513		/* insert-character key */
+#define KEY_EIC		0514		/* sent by rmir or smir in insert mode */
+#define KEY_CLEAR	0515		/* clear-screen or erase key */
+#define KEY_EOS		0516		/* clear-to-end-of-screen key */
+#define KEY_EOL		0517		/* clear-to-end-of-line key */
+#define KEY_SF		0520		/* scroll-forward key */
+#define KEY_SR		0521		/* scroll-backward key */
+#define KEY_NPAGE	0522		/* next-page key */
+#define KEY_PPAGE	0523		/* previous-page key */
+#define KEY_STAB	0524		/* set-tab key */
+#define KEY_CTAB	0525		/* clear-tab key */
+#define KEY_CATAB	0526		/* clear-all-tabs key */
+#define KEY_ENTER	0527		/* enter/send key */
+#define KEY_PRINT	0532		/* print key */
+#define KEY_LL		0533		/* lower-left key (home down) */
+#define KEY_A1		0534		/* upper left of keypad */
+#define KEY_A3		0535		/* upper right of keypad */
+#define KEY_B2		0536		/* center of keypad */
+#define KEY_C1		0537		/* lower left of keypad */
+#define KEY_C3		0540		/* lower right of keypad */
+#define KEY_BTAB	0541		/* back-tab key */
+#define KEY_BEG		0542		/* begin key */
+#define KEY_CANCEL	0543		/* cancel key */
+#define KEY_CLOSE	0544		/* close key */
+#define KEY_COMMAND	0545		/* command key */
+#define KEY_COPY	0546		/* copy key */
+#define KEY_CREATE	0547		/* create key */
+#define KEY_END		0550		/* end key */
+#define KEY_EXIT	0551		/* exit key */
+#define KEY_FIND	0552		/* find key */
+#define KEY_HELP	0553		/* help key */
+#define KEY_MARK	0554		/* mark key */
+#define KEY_MESSAGE	0555		/* message key */
+#define KEY_MOVE	0556		/* move key */
+#define KEY_NEXT	0557		/* next key */
+#define KEY_OPEN	0560		/* open key */
+#define KEY_OPTIONS	0561		/* options key */
+#define KEY_PREVIOUS	0562		/* previous key */
+#define KEY_REDO	0563		/* redo key */
+#define KEY_REFERENCE	0564		/* reference key */
+#define KEY_REFRESH	0565		/* refresh key */
+#define KEY_REPLACE	0566		/* replace key */
+#define KEY_RESTART	0567		/* restart key */
+#define KEY_RESUME	0570		/* resume key */
+#define KEY_SAVE	0571		/* save key */
+#define KEY_SBEG	0572		/* shifted begin key */
+#define KEY_SCANCEL	0573		/* shifted cancel key */
+#define KEY_SCOMMAND	0574		/* shifted command key */
+#define KEY_SCOPY	0575		/* shifted copy key */
+#define KEY_SCREATE	0576		/* shifted create key */
+#define KEY_SDC		0577		/* shifted delete-character key */
+#define KEY_SDL		0600		/* shifted delete-line key */
+#define KEY_SELECT	0601		/* select key */
+#define KEY_SEND	0602		/* shifted end key */
+#define KEY_SEOL	0603		/* shifted clear-to-end-of-line key */
+#define KEY_SEXIT	0604		/* shifted exit key */
+#define KEY_SFIND	0605		/* shifted find key */
+#define KEY_SHELP	0606		/* shifted help key */
+#define KEY_SHOME	0607		/* shifted home key */
+#define KEY_SIC		0610		/* shifted insert-character key */
+#define KEY_SLEFT	0611		/* shifted left-arrow key */
+#define KEY_SMESSAGE	0612		/* shifted message key */
+#define KEY_SMOVE	0613		/* shifted move key */
+#define KEY_SNEXT	0614		/* shifted next key */
+#define KEY_SOPTIONS	0615		/* shifted options key */
+#define KEY_SPREVIOUS	0616		/* shifted previous key */
+#define KEY_SPRINT	0617		/* shifted print key */
+#define KEY_SREDO	0620		/* shifted redo key */
+#define KEY_SREPLACE	0621		/* shifted replace key */
+#define KEY_SRIGHT	0622		/* shifted right-arrow key */
+#define KEY_SRSUME	0623		/* shifted resume key */
+#define KEY_SSAVE	0624		/* shifted save key */
+#define KEY_SSUSPEND	0625		/* shifted suspend key */
+#define KEY_SUNDO	0626		/* shifted undo key */
+#define KEY_SUSPEND	0627		/* suspend key */
+#define KEY_UNDO	0630		/* undo key */
+#define KEY_MOUSE	0631		/* Mouse event has occurred */
+#define KEY_RESIZE	0632		/* Terminal resize event */
+#define KEY_EVENT	0633		/* We were interrupted by an event */
+
+#define KEY_MAX		0777		/* Maximum key value is 0633 */
+/*
+ * This file is part of ncurses, designed to be appended after curses.h.in
+ * (see that file for the relevant copyright).
+ */
+#ifdef _XOPEN_SOURCE_EXTENDED
+
+/* $Id: curses.wide,v 1.32 2006/05/27 19:44:23 tom Exp $ */
+
+extern NCURSES_EXPORT_VAR(cchar_t *) _nc_wacs;
+
+#define NCURSES_WACS(c)	(&_nc_wacs[(unsigned char)c])
+
+#define WACS_BSSB	NCURSES_WACS('l')
+#define WACS_SSBB	NCURSES_WACS('m')
+#define WACS_BBSS	NCURSES_WACS('k')
+#define WACS_SBBS	NCURSES_WACS('j')
+#define WACS_SBSS	NCURSES_WACS('u')
+#define WACS_SSSB	NCURSES_WACS('t')
+#define WACS_SSBS	NCURSES_WACS('v')
+#define WACS_BSSS	NCURSES_WACS('w')
+#define WACS_BSBS	NCURSES_WACS('q')
+#define WACS_SBSB	NCURSES_WACS('x')
+#define WACS_SSSS	NCURSES_WACS('n')
+
+#define WACS_ULCORNER	WACS_BSSB
+#define WACS_LLCORNER	WACS_SSBB
+#define WACS_URCORNER	WACS_BBSS
+#define WACS_LRCORNER	WACS_SBBS
+#define WACS_RTEE	WACS_SBSS
+#define WACS_LTEE	WACS_SSSB
+#define WACS_BTEE	WACS_SSBS
+#define WACS_TTEE	WACS_BSSS
+#define WACS_HLINE	WACS_BSBS
+#define WACS_VLINE	WACS_SBSB
+#define WACS_PLUS	WACS_SSSS
+
+#define WACS_S1		NCURSES_WACS('o') /* scan line 1 */
+#define WACS_S9 	NCURSES_WACS('s') /* scan line 9 */
+#define WACS_DIAMOND	NCURSES_WACS('`') /* diamond */
+#define WACS_CKBOARD	NCURSES_WACS('a') /* checker board */
+#define WACS_DEGREE	NCURSES_WACS('f') /* degree symbol */
+#define WACS_PLMINUS	NCURSES_WACS('g') /* plus/minus */
+#define WACS_BULLET	NCURSES_WACS('~') /* bullet */
+
+	/* Teletype 5410v1 symbols */
+#define WACS_LARROW	NCURSES_WACS(',') /* arrow left */
+#define WACS_RARROW	NCURSES_WACS('+') /* arrow right */
+#define WACS_DARROW	NCURSES_WACS('.') /* arrow down */
+#define WACS_UARROW	NCURSES_WACS('-') /* arrow up */
+#define WACS_BOARD	NCURSES_WACS('h') /* board of squares */
+#define WACS_LANTERN	NCURSES_WACS('i') /* lantern symbol */
+#define WACS_BLOCK	NCURSES_WACS('0') /* solid square block */
+
+	/* ncurses extensions */
+#define WACS_S3		NCURSES_WACS('p') /* scan line 3 */
+#define WACS_S7		NCURSES_WACS('r') /* scan line 7 */
+#define WACS_LEQUAL	NCURSES_WACS('y') /* less/equal */
+#define WACS_GEQUAL	NCURSES_WACS('z') /* greater/equal */
+#define WACS_PI		NCURSES_WACS('{') /* Pi */
+#define WACS_NEQUAL	NCURSES_WACS('|') /* not equal */
+#define WACS_STERLING	NCURSES_WACS('}') /* UK pound sign */
+
+/*
+ * Function prototypes for wide-character operations.
+ *
+ * "generated" comments should include ":WIDEC" to make the corresponding
+ * functions ifdef'd in lib_gen.c
+ *
+ * "implemented" comments do not need this marker.
+ */
+
+extern NCURSES_EXPORT(int) add_wch (const cchar_t *);			/* generated:WIDEC */
+extern NCURSES_EXPORT(int) add_wchnstr (const cchar_t *, int);		/* generated:WIDEC */
+extern NCURSES_EXPORT(int) add_wchstr (const cchar_t *);		/* generated:WIDEC */
+extern NCURSES_EXPORT(int) addnwstr (const wchar_t *, int);		/* generated:WIDEC */
+extern NCURSES_EXPORT(int) addwstr (const wchar_t *);			/* generated:WIDEC */
+extern NCURSES_EXPORT(int) bkgrnd (const cchar_t *);			/* generated:WIDEC */
+extern NCURSES_EXPORT(void) bkgrndset (const cchar_t *);		/* generated:WIDEC */
+extern NCURSES_EXPORT(int) border_set (const cchar_t*,const cchar_t*,const cchar_t*,const cchar_t*,const cchar_t*,const cchar_t*,const cchar_t*,const cchar_t*); /* generated:WIDEC */
+extern NCURSES_EXPORT(int) box_set (WINDOW *, const cchar_t *, const cchar_t *);	/* generated:WIDEC */
+extern NCURSES_EXPORT(int) echo_wchar (const cchar_t *);		/* generated:WIDEC */
+extern NCURSES_EXPORT(int) erasewchar (wchar_t*);			/* implemented */
+extern NCURSES_EXPORT(int) get_wch (wint_t *);				/* generated:WIDEC */
+extern NCURSES_EXPORT(int) get_wstr (wint_t *);				/* generated:WIDEC */
+extern NCURSES_EXPORT(int) getbkgrnd (cchar_t *);			/* generated:WIDEC */
+extern NCURSES_EXPORT(int) getcchar (const cchar_t *, wchar_t*, attr_t*, short*, void*);	/* implemented */
+extern NCURSES_EXPORT(int) getn_wstr (wint_t *, int);			/* generated:WIDEC */
+extern NCURSES_EXPORT(int) hline_set (const cchar_t *, int);		/* generated:WIDEC */
+extern NCURSES_EXPORT(int) in_wch (cchar_t *);				/* generated:WIDEC */
+extern NCURSES_EXPORT(int) in_wchnstr (cchar_t *, int);			/* generated:WIDEC */
+extern NCURSES_EXPORT(int) in_wchstr (cchar_t *);			/* generated:WIDEC */
+extern NCURSES_EXPORT(int) innwstr (wchar_t *, int);			/* generated:WIDEC */
+extern NCURSES_EXPORT(int) ins_nwstr (const wchar_t *, int);		/* generated:WIDEC */
+extern NCURSES_EXPORT(int) ins_wch (const cchar_t *);			/* generated:WIDEC */
+extern NCURSES_EXPORT(int) ins_wstr (const wchar_t *);			/* generated:WIDEC */
+extern NCURSES_EXPORT(int) inwstr (wchar_t *);				/* generated:WIDEC */
+extern NCURSES_EXPORT(NCURSES_CONST char*) key_name (wchar_t);		/* implemented */
+extern NCURSES_EXPORT(int) killwchar (wchar_t *);			/* implemented */
+extern NCURSES_EXPORT(int) mvadd_wch (int, int, const cchar_t *);	/* generated:WIDEC */
+extern NCURSES_EXPORT(int) mvadd_wchnstr (int, int, const cchar_t *, int);/* generated:WIDEC */
+extern NCURSES_EXPORT(int) mvadd_wchstr (int, int, const cchar_t *);	/* generated:WIDEC */
+extern NCURSES_EXPORT(int) mvaddnwstr (int, int, const wchar_t *, int);	/* generated:WIDEC */
+extern NCURSES_EXPORT(int) mvaddwstr (int, int, const wchar_t *);	/* generated:WIDEC */
+extern NCURSES_EXPORT(int) mvget_wch (int, int, wint_t *);		/* generated:WIDEC */
+extern NCURSES_EXPORT(int) mvget_wstr (int, int, wint_t *);		/* generated:WIDEC */
+extern NCURSES_EXPORT(int) mvgetn_wstr (int, int, wint_t *, int);	/* generated:WIDEC */
+extern NCURSES_EXPORT(int) mvhline_set (int, int, const cchar_t *, int);	/* generated:WIDEC */
+extern NCURSES_EXPORT(int) mvin_wch (int, int, cchar_t *);		/* generated:WIDEC */
+extern NCURSES_EXPORT(int) mvin_wchnstr (int, int, cchar_t *, int);	/* generated:WIDEC */
+extern NCURSES_EXPORT(int) mvin_wchstr (int, int, cchar_t *);		/* generated:WIDEC */
+extern NCURSES_EXPORT(int) mvinnwstr (int, int, wchar_t *, int);	/* generated:WIDEC */
+extern NCURSES_EXPORT(int) mvins_nwstr (int, int, const wchar_t *, int);	/* generated:WIDEC */
+extern NCURSES_EXPORT(int) mvins_wch (int, int, const cchar_t *);	/* generated:WIDEC */
+extern NCURSES_EXPORT(int) mvins_wstr (int, int, const wchar_t *);	/* generated:WIDEC */
+extern NCURSES_EXPORT(int) mvinwstr (int, int, wchar_t *);		/* generated:WIDEC */
+extern NCURSES_EXPORT(int) mvvline_set (int, int, const cchar_t *, int);	/* generated:WIDEC */
+extern NCURSES_EXPORT(int) mvwadd_wch (WINDOW *, int, int, const cchar_t *);	/* generated:WIDEC */
+extern NCURSES_EXPORT(int) mvwadd_wchnstr (WINDOW *, int, int, const cchar_t *, int); /* generated:WIDEC */
+extern NCURSES_EXPORT(int) mvwadd_wchstr (WINDOW *, int, int, const cchar_t *);	/* generated:WIDEC */
+extern NCURSES_EXPORT(int) mvwaddnwstr (WINDOW *, int, int, const wchar_t *, int);/* generated:WIDEC */
+extern NCURSES_EXPORT(int) mvwaddwstr (WINDOW *, int, int, const wchar_t *);	/* generated:WIDEC */
+extern NCURSES_EXPORT(int) mvwget_wch (WINDOW *, int, int, wint_t *);	/* generated:WIDEC */
+extern NCURSES_EXPORT(int) mvwget_wstr (WINDOW *, int, int, wint_t *);	/* generated:WIDEC */
+extern NCURSES_EXPORT(int) mvwgetn_wstr (WINDOW *, int, int, wint_t *, int);/* generated:WIDEC */
+extern NCURSES_EXPORT(int) mvwhline_set (WINDOW *, int, int, const cchar_t *, int);/* generated:WIDEC */
+extern NCURSES_EXPORT(int) mvwin_wch (WINDOW *, int, int, cchar_t *);	/* generated:WIDEC */
+extern NCURSES_EXPORT(int) mvwin_wchnstr (WINDOW *, int,int, cchar_t *,int);	/* generated:WIDEC */
+extern NCURSES_EXPORT(int) mvwin_wchstr (WINDOW *, int, int, cchar_t *);	/* generated:WIDEC */
+extern NCURSES_EXPORT(int) mvwinnwstr (WINDOW *, int, int, wchar_t *, int);	/* generated:WIDEC */
+extern NCURSES_EXPORT(int) mvwins_nwstr (WINDOW *, int,int, const wchar_t *,int); /* generated:WIDEC */
+extern NCURSES_EXPORT(int) mvwins_wch (WINDOW *, int, int, const cchar_t *);	/* generated:WIDEC */
+extern NCURSES_EXPORT(int) mvwins_wstr (WINDOW *, int, int, const wchar_t *);	/* generated:WIDEC */
+extern NCURSES_EXPORT(int) mvwinwstr (WINDOW *, int, int, wchar_t *);		/* generated:WIDEC */
+extern NCURSES_EXPORT(int) mvwvline_set (WINDOW *, int,int, const cchar_t *,int); /* generated:WIDEC */
+extern NCURSES_EXPORT(int) pecho_wchar (WINDOW *, const cchar_t *);	/* implemented */
+extern NCURSES_EXPORT(int) setcchar (cchar_t *, const wchar_t *, const attr_t, short, const void *);	/* implemented */
+extern NCURSES_EXPORT(int) slk_wset (int, const wchar_t *, int);	/* implemented */
+extern NCURSES_EXPORT(attr_t) term_attrs (void);			/* implemented */
+extern NCURSES_EXPORT(int) unget_wch (const wchar_t);			/* implemented */
+extern NCURSES_EXPORT(int) vid_attr (attr_t, short, void *);		/* implemented */
+extern NCURSES_EXPORT(int) vid_puts (attr_t, short, void *, int (*)(int)); /* implemented */
+extern NCURSES_EXPORT(int) vline_set (const cchar_t *, int);		/* generated:WIDEC */
+extern NCURSES_EXPORT(int) wadd_wch (WINDOW *,const cchar_t *);		/* implemented */
+extern NCURSES_EXPORT(int) wadd_wchnstr (WINDOW *,const cchar_t *,int);	/* implemented */
+extern NCURSES_EXPORT(int) wadd_wchstr (WINDOW *,const cchar_t *);	/* generated:WIDEC */
+extern NCURSES_EXPORT(int) waddnwstr (WINDOW *,const wchar_t *,int);	/* implemented */
+extern NCURSES_EXPORT(int) waddwstr (WINDOW *,const wchar_t *);		/* generated:WIDEC */
+extern NCURSES_EXPORT(int) wbkgrnd (WINDOW *,const cchar_t *);		/* implemented */
+extern NCURSES_EXPORT(void) wbkgrndset (WINDOW *,const cchar_t *);	/* implemented */
+extern NCURSES_EXPORT(int) wborder_set (WINDOW *,const cchar_t*,const cchar_t*,const cchar_t*,const cchar_t*,const cchar_t*,const cchar_t*,const cchar_t*,const cchar_t*);	/* implemented */
+extern NCURSES_EXPORT(int) wecho_wchar (WINDOW *, const cchar_t *);	/* implemented */
+extern NCURSES_EXPORT(int) wget_wch (WINDOW *, wint_t *);		/* implemented */
+extern NCURSES_EXPORT(int) wget_wstr (WINDOW *, wint_t *);		/* generated:WIDEC */
+extern NCURSES_EXPORT(int) wgetbkgrnd (WINDOW *, cchar_t *);		/* generated:WIDEC */
+extern NCURSES_EXPORT(int) wgetn_wstr (WINDOW *,wint_t *, int);		/* implemented */
+extern NCURSES_EXPORT(int) whline_set (WINDOW *, const cchar_t *, int);	/* implemented */
+extern NCURSES_EXPORT(int) win_wch (WINDOW *, cchar_t *);		/* implemented */
+extern NCURSES_EXPORT(int) win_wchnstr (WINDOW *, cchar_t *, int);	/* implemented */
+extern NCURSES_EXPORT(int) win_wchstr (WINDOW *, cchar_t *);		/* generated:WIDEC */
+extern NCURSES_EXPORT(int) winnwstr (WINDOW *, wchar_t *, int);		/* implemented */
+extern NCURSES_EXPORT(int) wins_nwstr (WINDOW *, const wchar_t *, int);	/* implemented */
+extern NCURSES_EXPORT(int) wins_wch (WINDOW *, const cchar_t *);	/* implemented */
+extern NCURSES_EXPORT(int) wins_wstr (WINDOW *, const wchar_t *);	/* generated:WIDEC */
+extern NCURSES_EXPORT(int) winwstr (WINDOW *, wchar_t *);		/* implemented */
+extern NCURSES_EXPORT(wchar_t*) wunctrl (cchar_t *);			/* implemented */
+extern NCURSES_EXPORT(int) wvline_set (WINDOW *, const cchar_t *, int);	/* implemented */
+
+#ifndef NCURSES_NOMACROS
+
+/*
+ * XSI curses macros for XPG4 conformance.
+ */
+#define add_wch(c)			wadd_wch(stdscr,c)
+#define add_wchnstr(str,n)		wadd_wchnstr(stdscr,str,n)
+#define add_wchstr(str)			wadd_wchstr(stdscr,str)
+#define addnwstr(wstr,n)		waddnwstr(stdscr,wstr,n)
+#define addwstr(wstr)			waddwstr(stdscr,wstr)
+#define bkgrnd(c)			wbkgrnd(stdscr,c)
+#define bkgrndset(c)			wbkgrndset(stdscr,c)
+#define border_set(l,r,t,b,tl,tr,bl,br) wborder_set(stdscr,l,r,t,b,tl,tr,bl,br)
+#define box_set(w,v,h)			wborder_set(w,v,v,h,h,0,0,0,0)
+#define echo_wchar(c)			wecho_wchar(stdscr,c)
+#define get_wch(c)			wget_wch(stdscr,c)
+#define get_wstr(t)			wget_wstr(stdscr,t)
+#define getbkgrnd(wch)			wgetbkgrnd(stdscr,wch)
+#define getn_wstr(t,n)			wgetn_wstr(stdscr,t,n)
+#define hline_set(c,n)			whline_set(stdscr,c,n)
+#define in_wch(c)			win_wch(stdscr,c)
+#define in_wchnstr(c,n)			win_wchnstr(stdscr,c,n)
+#define in_wchstr(c)			win_wchstr(stdscr,c)
+#define innwstr(c,n)			winnwstr(stdscr,c,n)
+#define ins_nwstr(t,n)			wins_nwstr(stdscr,t,n)
+#define ins_wch(c)			wins_wch(stdscr,c)
+#define ins_wstr(t)			wins_wstr(stdscr,t)
+#define inwstr(c)			winwstr(stdscr,c)
+#define vline_set(c,n)			wvline_set(stdscr,c,n)
+#define wadd_wchstr(win,str)		wadd_wchnstr(win,str,-1)
+#define waddwstr(win,wstr)		waddnwstr(win,wstr,-1)
+#define wget_wstr(w,t)			wgetn_wstr(w,t,-1)
+//// #define wgetbkgrnd(win,wch)		(*wch = win->_bkgrnd, OK)
+#define win_wchstr(w,c)			win_wchnstr(w,c,-1)
+#define wins_wstr(w,t)			wins_nwstr(w,t,-1)
+
+#define mvadd_wch(y,x,c)		mvwadd_wch(stdscr,y,x,c)
+#define mvadd_wchnstr(y,x,s,n)		mvwadd_wchnstr(stdscr,y,x,s,n)
+#define mvadd_wchstr(y,x,s)		mvwadd_wchstr(stdscr,y,x,s)
+#define mvaddnwstr(y,x,wstr,n)		mvwaddnwstr(stdscr,y,x,wstr,n)
+#define mvaddwstr(y,x,wstr)		mvwaddwstr(stdscr,y,x,wstr)
+#define mvget_wch(y,x,c)		mvwget_wch(stdscr,y,x,c)
+#define mvget_wstr(y,x,t)		mvwget_wstr(stdscr,y,x,t)
+#define mvgetn_wstr(y,x,t,n)		mvwgetn_wstr(stdscr,y,x,t,n)
+#define mvhline_set(y,x,c,n)		mvwhline_set(stdscr,y,x,c,n)
+#define mvin_wch(y,x,c)			mvwin_wch(stdscr,y,x,c)
+#define mvin_wchnstr(y,x,c,n)		mvwin_wchnstr(stdscr,y,x,c,n)
+#define mvin_wchstr(y,x,c)		mvwin_wchstr(stdscr,y,x,c)
+#define mvinnwstr(y,x,c,n)		mvwinnwstr(stdscr,y,x,c,n)
+#define mvins_nwstr(y,x,t,n)		mvwins_nwstr(stdscr,y,x,t,n)
+#define mvins_wch(y,x,c)		mvwins_wch(stdscr,y,x,c)
+#define mvins_wstr(y,x,t)		mvwins_wstr(stdscr,y,x,t)
+#define mvinwstr(y,x,c)			mvwinwstr(stdscr,y,x,c)
+#define mvvline_set(y,x,c,n)		mvwvline_set(stdscr,y,x,c,n)
+
+#define mvwadd_wch(win,y,x,c)		(wmove(win,y,x) == ERR ? ERR : wadd_wch(win,c))
+#define mvwadd_wchnstr(win,y,x,s,n)	(wmove(win,y,x) == ERR ? ERR : wadd_wchnstr(win,s,n))
+#define mvwadd_wchstr(win,y,x,s)	(wmove(win,y,x) == ERR ? ERR : wadd_wchstr(win,s))
+#define mvwaddnwstr(win,y,x,wstr,n)	(wmove(win,y,x) == ERR ? ERR : waddnwstr(win,wstr,n))
+#define mvwaddwstr(win,y,x,wstr)	(wmove(win,y,x) == ERR ? ERR : waddwstr(win,wstr))
+#define mvwget_wch(win,y,x,c)		(wmove(win,y,x) == ERR ? ERR : wget_wch(win,c))
+#define mvwget_wstr(win,y,x,t)		(wmove(win,y,x) == ERR ? ERR : wget_wstr(win,t))
+#define mvwgetn_wstr(win,y,x,t,n)	(wmove(win,y,x) == ERR ? ERR : wgetn_wstr(win,t,n))
+#define mvwhline_set(win,y,x,c,n)	(wmove(win,y,x) == ERR ? ERR : whline_set(win,c,n))
+#define mvwin_wch(win,y,x,c)		(wmove(win,y,x) == ERR ? ERR : win_wch(win,c))
+#define mvwin_wchnstr(win,y,x,c,n)	(wmove(win,y,x) == ERR ? ERR : win_wchnstr(win,c,n))
+#define mvwin_wchstr(win,y,x,c)		(wmove(win,y,x) == ERR ? ERR : win_wchstr(win,c))
+#define mvwinnwstr(win,y,x,c,n)		(wmove(win,y,x) == ERR ? ERR : winnwstr(win,c,n))
+#define mvwins_nwstr(win,y,x,t,n)	(wmove(win,y,x) == ERR ? ERR : wins_nwstr(win,t,n))
+#define mvwins_wch(win,y,x,c)		(wmove(win,y,x) == ERR ? ERR : wins_wch(win,c))
+#define mvwins_wstr(win,y,x,t)		(wmove(win,y,x) == ERR ? ERR : wins_wstr(win,t))
+#define mvwinwstr(win,y,x,c)		(wmove(win,y,x) == ERR ? ERR : winwstr(win,c))
+#define mvwvline_set(win,y,x,c,n)	(wmove(win,y,x) == ERR ? ERR : wvline_set(win,c,n))
+
+#endif /* NCURSES_NOMACROS */
+
+#if defined(TRACE) || defined(NCURSES_TEST)
+extern NCURSES_EXPORT(const char *) _nc_viswbuf(const wchar_t *);
+extern NCURSES_EXPORT(const char *) _nc_viswibuf(const wint_t *);
+#endif
+
+#endif /* _XOPEN_SOURCE_EXTENDED */
+/*
+ * This file is part of ncurses, designed to be appended after curses.h.in
+ * (see that file for the relevant copyright).
+ */
+/* $Id: curses.tail,v 1.14 2006/05/27 16:28:29 tom Exp $ */
+
+/* mouse interface */
+
+#ifdef NCURSES_MOUSE_VERSION
+#if NCURSES_MOUSE_VERSION > 1
+#define NCURSES_MOUSE_MASK(b,m) ((m) << (((b) - 1) * 5))
+#else
+#define NCURSES_MOUSE_MASK(b,m) ((m) << (((b) - 1) * 6))
+#endif
+
+#define	NCURSES_BUTTON_RELEASED	001L
+#define	NCURSES_BUTTON_PRESSED	002L
+#define	NCURSES_BUTTON_CLICKED	004L
+#define	NCURSES_DOUBLE_CLICKED	010L
+#define	NCURSES_TRIPLE_CLICKED	020L
+#define	NCURSES_RESERVED_EVENT	040L
+
+/* event masks */
+#define	BUTTON1_RELEASED	NCURSES_MOUSE_MASK(1, NCURSES_BUTTON_RELEASED)
+#define	BUTTON1_PRESSED		NCURSES_MOUSE_MASK(1, NCURSES_BUTTON_PRESSED)
+#define	BUTTON1_CLICKED		NCURSES_MOUSE_MASK(1, NCURSES_BUTTON_CLICKED)
+#define	BUTTON1_DOUBLE_CLICKED	NCURSES_MOUSE_MASK(1, NCURSES_DOUBLE_CLICKED)
+#define	BUTTON1_TRIPLE_CLICKED	NCURSES_MOUSE_MASK(1, NCURSES_TRIPLE_CLICKED)
+
+#define	BUTTON2_RELEASED	NCURSES_MOUSE_MASK(2, NCURSES_BUTTON_RELEASED)
+#define	BUTTON2_PRESSED		NCURSES_MOUSE_MASK(2, NCURSES_BUTTON_PRESSED)
+#define	BUTTON2_CLICKED		NCURSES_MOUSE_MASK(2, NCURSES_BUTTON_CLICKED)
+#define	BUTTON2_DOUBLE_CLICKED	NCURSES_MOUSE_MASK(2, NCURSES_DOUBLE_CLICKED)
+#define	BUTTON2_TRIPLE_CLICKED	NCURSES_MOUSE_MASK(2, NCURSES_TRIPLE_CLICKED)
+
+#define	BUTTON3_RELEASED	NCURSES_MOUSE_MASK(3, NCURSES_BUTTON_RELEASED)
+#define	BUTTON3_PRESSED		NCURSES_MOUSE_MASK(3, NCURSES_BUTTON_PRESSED)
+#define	BUTTON3_CLICKED		NCURSES_MOUSE_MASK(3, NCURSES_BUTTON_CLICKED)
+#define	BUTTON3_DOUBLE_CLICKED	NCURSES_MOUSE_MASK(3, NCURSES_DOUBLE_CLICKED)
+#define	BUTTON3_TRIPLE_CLICKED	NCURSES_MOUSE_MASK(3, NCURSES_TRIPLE_CLICKED)
+
+#define	BUTTON4_RELEASED	NCURSES_MOUSE_MASK(4, NCURSES_BUTTON_RELEASED)
+#define	BUTTON4_PRESSED		NCURSES_MOUSE_MASK(4, NCURSES_BUTTON_PRESSED)
+#define	BUTTON4_CLICKED		NCURSES_MOUSE_MASK(4, NCURSES_BUTTON_CLICKED)
+#define	BUTTON4_DOUBLE_CLICKED	NCURSES_MOUSE_MASK(4, NCURSES_DOUBLE_CLICKED)
+#define	BUTTON4_TRIPLE_CLICKED	NCURSES_MOUSE_MASK(4, NCURSES_TRIPLE_CLICKED)
+
+/*
+ * In 32 bits the version-1 scheme does not provide enough space for a 5th
+ * button, unless we choose to change the ABI by omitting the reserved-events.
+ */
+#if NCURSES_MOUSE_VERSION > 1
+
+#define	BUTTON5_RELEASED	NCURSES_MOUSE_MASK(5, NCURSES_BUTTON_RELEASED)
+#define	BUTTON5_PRESSED		NCURSES_MOUSE_MASK(5, NCURSES_BUTTON_PRESSED)
+#define	BUTTON5_CLICKED		NCURSES_MOUSE_MASK(5, NCURSES_BUTTON_CLICKED)
+#define	BUTTON5_DOUBLE_CLICKED	NCURSES_MOUSE_MASK(5, NCURSES_DOUBLE_CLICKED)
+#define	BUTTON5_TRIPLE_CLICKED	NCURSES_MOUSE_MASK(5, NCURSES_TRIPLE_CLICKED)
+
+#define	BUTTON_CTRL		NCURSES_MOUSE_MASK(6, 0001L)
+#define	BUTTON_SHIFT		NCURSES_MOUSE_MASK(6, 0002L)
+#define	BUTTON_ALT		NCURSES_MOUSE_MASK(6, 0004L)
+#define	REPORT_MOUSE_POSITION	NCURSES_MOUSE_MASK(6, 0010L)
+
+#else
+
+#define	BUTTON1_RESERVED_EVENT	NCURSES_MOUSE_MASK(1, NCURSES_RESERVED_EVENT)
+#define	BUTTON2_RESERVED_EVENT	NCURSES_MOUSE_MASK(2, NCURSES_RESERVED_EVENT)
+#define	BUTTON3_RESERVED_EVENT	NCURSES_MOUSE_MASK(3, NCURSES_RESERVED_EVENT)
+#define	BUTTON4_RESERVED_EVENT	NCURSES_MOUSE_MASK(4, NCURSES_RESERVED_EVENT)
+
+#define	BUTTON_CTRL		NCURSES_MOUSE_MASK(5, 0001L)
+#define	BUTTON_SHIFT		NCURSES_MOUSE_MASK(5, 0002L)
+#define	BUTTON_ALT		NCURSES_MOUSE_MASK(5, 0004L)
+#define	REPORT_MOUSE_POSITION	NCURSES_MOUSE_MASK(5, 0010L)
+
+#endif
+
+#define	ALL_MOUSE_EVENTS	(REPORT_MOUSE_POSITION - 1)
+
+/* macros to extract single event-bits from masks */
+#define	BUTTON_RELEASE(e, x)		((e) & (001 << (6 * ((x) - 1))))
+#define	BUTTON_PRESS(e, x)		((e) & (002 << (6 * ((x) - 1))))
+#define	BUTTON_CLICK(e, x)		((e) & (004 << (6 * ((x) - 1))))
+#define	BUTTON_DOUBLE_CLICK(e, x)	((e) & (010 << (6 * ((x) - 1))))
+#define	BUTTON_TRIPLE_CLICK(e, x)	((e) & (020 << (6 * ((x) - 1))))
+#define	BUTTON_RESERVED_EVENT(e, x)	((e) & (040 << (6 * ((x) - 1))))
+
+typedef struct
+{
+    short id;		/* ID to distinguish multiple devices */
+    int x, y, z;	/* event coordinates (character-cell) */
+    mmask_t bstate;	/* button state bits */
+}
+MEVENT;
+
+extern NCURSES_EXPORT(int) getmouse (MEVENT *);
+extern NCURSES_EXPORT(int) ungetmouse (MEVENT *);
+extern NCURSES_EXPORT(mmask_t) mousemask (mmask_t, mmask_t *);
+extern NCURSES_EXPORT(bool) wenclose (const WINDOW *, int, int);
+extern NCURSES_EXPORT(int) mouseinterval (int);
+extern NCURSES_EXPORT(bool) wmouse_trafo (const WINDOW*, int*, int*, bool);
+extern NCURSES_EXPORT(bool) mouse_trafo (int*, int*, bool);              /* generated */
+
+#define mouse_trafo(y,x,to_screen) wmouse_trafo(stdscr,y,x,to_screen)
+#endif
+
+/* other non-XSI functions */
+
+extern NCURSES_EXPORT(int) mcprint (char *, int);	/* direct data to printer */
+extern NCURSES_EXPORT(int) has_key (int);		/* do we have given key? */
+
+/* Debugging : use with libncurses_g.a */
+
+extern NCURSES_EXPORT(void) _tracef (const char *, ...) GCC_PRINTFLIKE(1,2);
+extern NCURSES_EXPORT(void) _tracedump (const char *, WINDOW *);
+extern NCURSES_EXPORT(char *) _traceattr (attr_t);
+extern NCURSES_EXPORT(char *) _traceattr2 (int, chtype);
+extern NCURSES_EXPORT(char *) _nc_tracebits (void);
+extern NCURSES_EXPORT(char *) _tracechar (int);
+extern NCURSES_EXPORT(char *) _tracechtype (chtype);
+extern NCURSES_EXPORT(char *) _tracechtype2 (int, chtype);
+#ifdef _XOPEN_SOURCE_EXTENDED
+#define _tracech_t		_tracecchar_t
+extern NCURSES_EXPORT(char *) _tracecchar_t (const cchar_t *);
+#define _tracech_t2		_tracecchar_t2
+extern NCURSES_EXPORT(char *) _tracecchar_t2 (int, const cchar_t *);
+#else
+#define _tracech_t		_tracechtype
+#define _tracech_t2		_tracechtype2
+#endif
+#ifdef NCURSES_MOUSE_VERSION
+extern NCURSES_EXPORT(char *) _tracemouse (const MEVENT *);
+#endif
+extern NCURSES_EXPORT(void) trace (const unsigned int);
+
+/* trace masks */
+#define TRACE_DISABLE	0x0000	/* turn off tracing */
+#define TRACE_TIMES	0x0001	/* trace user and system times of updates */
+#define TRACE_TPUTS	0x0002	/* trace tputs calls */
+#define TRACE_UPDATE	0x0004	/* trace update actions, old & new screens */
+#define TRACE_MOVE	0x0008	/* trace cursor moves and scrolls */
+#define TRACE_CHARPUT	0x0010	/* trace all character outputs */
+#define TRACE_ORDINARY	0x001F	/* trace all update actions */
+#define TRACE_CALLS	0x0020	/* trace all curses calls */
+#define TRACE_VIRTPUT	0x0040	/* trace virtual character puts */
+#define TRACE_IEVENT	0x0080	/* trace low-level input processing */
+#define TRACE_BITS	0x0100	/* trace state of TTY control bits */
+#define TRACE_ICALLS	0x0200	/* trace internal/nested calls */
+#define TRACE_CCALLS	0x0400	/* trace per-character calls */
+#define TRACE_DATABASE	0x0800	/* trace read/write of terminfo/termcap data */
+#define TRACE_ATTRS	0x1000	/* trace attribute updates */
+
+#define TRACE_SHIFT	13	/* number of bits in the trace masks */
+#define TRACE_MAXIMUM	((1 << TRACE_SHIFT) - 1) /* maximum trace level */
+
+#if defined(TRACE) || defined(NCURSES_TEST)
+extern NCURSES_EXPORT_VAR(int) _nc_optimize_enable;		/* enable optimizations */
+extern NCURSES_EXPORT(const char *) _nc_visbuf (const char *);
+#define OPTIMIZE_MVCUR		0x01	/* cursor movement optimization */
+#define OPTIMIZE_HASHMAP	0x02	/* diff hashing to detect scrolls */
+#define OPTIMIZE_SCROLL		0x04	/* scroll optimization */
+#define OPTIMIZE_ALL		0xff	/* enable all optimizations (dflt) */
+#endif
+
+#ifdef __cplusplus
+
+#ifndef NCURSES_NOMACROS
+
+/* these names conflict with STL */
+#undef box
+#undef clear
+#undef erase
+#undef move
+#undef refresh
+
+#endif /* NCURSES_NOMACROS */
+
+}
+#endif
+
+/* Local functions not defined in normal curses */
+
+void curses_enable_vga(int);
+void curses_enable_serial(int);
+
+int curses_vga_enabled(void);
+int curses_serial_enabled(void);
+
+#endif /* _CURSES_H */
diff --git a/apps/lib/curses/tinycurses/curses.priv.h b/apps/lib/curses/tinycurses/curses.priv.h
new file mode 100644
index 0000000..78b7ff3
--- /dev/null
+++ b/apps/lib/curses/tinycurses/curses.priv.h
@@ -0,0 +1,1317 @@
+/****************************************************************************
+ * Copyright (c) 1998-2005,2006 Free Software Foundation, Inc.              *
+ *                                                                          *
+ * 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, distribute with modifications, sublicense, and/or sell       *
+ * copies of the Software, and to permit persons to whom the Software is    *
+ * furnished to do so, subject to the following conditions:                 *
+ *                                                                          *
+ * The above copyright notice and this permission notice shall be included  *
+ * in all copies or substantial portions of the Software.                   *
+ *                                                                          *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
+ * IN NO EVENT SHALL THE ABOVE 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.                               *
+ *                                                                          *
+ * Except as contained in this notice, the name(s) of the above copyright   *
+ * holders shall not be used in advertising or otherwise to promote the     *
+ * sale, use or other dealings in this Software without prior written       *
+ * authorization.                                                           *
+ ****************************************************************************/
+
+/****************************************************************************
+ *  Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995               *
+ *     and: Eric S. Raymond <esr@snark.thyrsus.com>                         *
+ *     and: Thomas E. Dickey                        1996-on                 *
+ ****************************************************************************/
+
+
+/*
+ * $Id: curses.priv.h,v 1.314 2006/12/10 00:55:14 tom Exp $
+ *
+ *	curses.priv.h
+ *
+ *	Header file for curses library objects which are private to
+ *	the library.
+ *
+ */
+
+#ifndef _CURSES_PRIV_H
+#define _CURSES_PRIV_H 1
+
+//// #include <ncurses_dll.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+//// #include <ncurses_cfg.h>
+
+#if USE_RCS_IDS
+#define MODULE_ID(id) static const char Ident[] = id;
+#else
+#define MODULE_ID(id) /*nothing*/
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+//// #if HAVE_SYS_BSDTYPES_H
+//// #include <sys/bsdtypes.h>	/* needed for ISC */
+//// #endif
+
+#if HAVE_LIMITS_H
+# include <limits.h>
+//// #elif HAVE_SYS_PARAM_H
+//// # include <sys/param.h>
+#endif
+////
+//// #include <assert.h>
+#include <stdio.h>
+
+#include <errno.h>
+
+#if DECL_ERRNO
+extern int errno;
+#endif
+
+//// #include <nc_panel.h>
+////
+//// /* Some systems have a broken 'select()', but workable 'poll()'.  Use that */
+//// #if HAVE_WORKING_POLL
+//// #define USE_FUNC_POLL 1
+//// #if HAVE_POLL_H
+//// #include <poll.h>
+//// #else
+//// #include <sys/poll.h>
+//// #endif
+//// #else
+//// #define USE_FUNC_POLL 0
+//// #endif
+////
+//// /* include signal.h before curses.h to work-around defect in glibc 2.1.3 */
+//// #include <signal.h>
+
+/* Alessandro Rubini's GPM (general-purpose mouse) */
+#if HAVE_LIBGPM && HAVE_GPM_H
+#define USE_GPM_SUPPORT 1
+#else
+#define USE_GPM_SUPPORT 0
+#endif
+
+/* QNX mouse support */
+#if defined(__QNX__) && !defined(__QNXNTO__)
+#define USE_QNX_MOUSE 1
+#else
+#define USE_QNX_MOUSE 0
+#endif
+
+/* EMX mouse support */
+#ifdef __EMX__
+#define USE_EMX_MOUSE 1
+#else
+#define USE_EMX_MOUSE 0
+#endif
+
+#define DEFAULT_MAXCLICK 166
+#define EV_MAX		8	/* size of mouse circular event queue */
+
+/*
+ * If we don't have signals to support it, don't add a sigwinch handler.
+ * In any case, resizing is an extended feature.  Use it if we've got it.
+ */
+#if !NCURSES_EXT_FUNCS
+#undef HAVE_SIZECHANGE
+#define HAVE_SIZECHANGE 0
+#endif
+
+#if HAVE_SIZECHANGE && defined(SIGWINCH)
+#define USE_SIZECHANGE 1
+#else
+#define USE_SIZECHANGE 0
+#undef USE_SIGWINCH
+#define USE_SIGWINCH 0
+#endif
+
+/*
+ * If desired, one can configure this, disabling environment variables that
+ * point to custom terminfo/termcap locations.
+ */
+#ifdef USE_ROOT_ENVIRON
+#define use_terminfo_vars() 1
+#else
+#define use_terminfo_vars() _nc_env_access()
+extern NCURSES_EXPORT(int) _nc_env_access (void);
+#endif
+
+/*
+ * Not all platforms have memmove; some have an equivalent bcopy.  (Some may
+ * have neither).
+ */
+#if USE_OK_BCOPY
+#define memmove(d,s,n) bcopy(s,d,n)
+#elif USE_MY_MEMMOVE
+#define memmove(d,s,n) _nc_memmove(d,s,n)
+extern NCURSES_EXPORT(void *) _nc_memmove (void *, const void *, size_t);
+#endif
+
+/*
+ * Scroll hints are useless when hashmap is used
+ */
+//// #if !USE_SCROLL_HINTS
+//// #if !USE_HASHMAP
+//// #define USE_SCROLL_HINTS 1
+//// #else
+//// #define USE_SCROLL_HINTS 0
+//// #endif
+//// #endif
+
+#if USE_SCROLL_HINTS
+#define if_USE_SCROLL_HINTS(stmt) stmt
+#else
+#define if_USE_SCROLL_HINTS(stmt) /*nothing*/
+#endif
+
+/*
+ * Note:  ht/cbt expansion flakes out randomly under Linux 1.1.47, but only
+ * when we're throwing control codes at the screen at high volume.  To see
+ * this, re-enable USE_HARD_TABS and run worm for a while.  Other systems
+ * probably don't want to define this either due to uncertainties about tab
+ * delays and expansion in raw mode.
+ */
+
+struct tries {
+	struct tries    *child;     /* ptr to child.  NULL if none          */
+	struct tries    *sibling;   /* ptr to sibling.  NULL if none        */
+	unsigned char    ch;        /* character at this node               */
+	unsigned short   value;     /* code of string so far.  0 if none.   */
+};
+
+/*
+ * Common/troublesome character definitions
+ */
+#define L_BRACE '{'
+#define R_BRACE '}'
+#define S_QUOTE '\''
+#define D_QUOTE '"'
+
+#define VT_ACSC "``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~"
+
+/*
+ * Structure for palette tables
+ */
+
+typedef struct
+{
+    short red, green, blue;	/* what color_content() returns */
+    short r, g, b;		/* params to init_color() */
+    int init;			/* true if we called init_color() */
+}
+color_t;
+
+#define MAXCOLUMNS    135
+#define MAXLINES      66
+#define FIFO_SIZE     MAXCOLUMNS+2  /* for nocbreak mode input */
+
+#define ACS_LEN       128
+
+#define WINDOWLIST struct _win_list
+
+#if USE_WIDEC_SUPPORT
+#define _nc_bkgd    _bkgrnd
+#else
+#undef _XOPEN_SOURCE_EXTENDED
+#define _nc_bkgd    _bkgd
+#define wgetbkgrnd(win, wch)	*wch = win->_bkgd
+#define wbkgrnd	    wbkgd
+#endif
+
+//// #include <curses.h>	/* we'll use -Ipath directive to get the right one! */
+//// #include <term.h>
+//// #include <term_entry.h>
+//// #include <nc_tparm.h>
+
+#if NCURSES_EXT_COLORS && USE_WIDEC_SUPPORT
+#define if_EXT_COLORS(stmt)	stmt
+#define NetPair(value,p)	(value).ext_color = (p), \
+				AttrOf(value) &= ALL_BUT_COLOR, \
+				AttrOf(value) |= (A_COLOR & COLOR_PAIR((p > 255) ? 255 : p))
+#define SetPair(value,p)	(value).ext_color = (p)
+#define GetPair(value)		(value).ext_color
+#define unColor(n)		(AttrOf(n) & ALL_BUT_COLOR)
+#define GET_WINDOW_PAIR(w)	(w)->_color
+#define SET_WINDOW_PAIR(w,p)	(w)->_color = (p)
+#define SameAttrOf(a,b)		(AttrOf(a) == AttrOf(b) && GetPair(a) == GetPair(b))
+#define VIDATTR(attr, pair)	vid_attr(attr, pair, 0)
+#else
+#define if_EXT_COLORS(stmt)	/* nothing */
+#define SetPair(value,p)	RemAttr(value, A_COLOR), \
+				SetAttr(value, AttrOf(value) | (A_COLOR & COLOR_PAIR(p)))
+#define GetPair(value)		PAIR_NUMBER(AttrOf(value))
+#define unColor(n)		(AttrOf(n) & ALL_BUT_COLOR)
+#define GET_WINDOW_PAIR(w)	PAIR_NUMBER(WINDOW_ATTRS(w))
+#define SET_WINDOW_PAIR(w,p)	WINDOW_ATTRS(w) &= ALL_BUT_COLOR, \
+				WINDOW_ATTRS(w) |= (A_COLOR & COLOR_PAIR(p))
+#define SameAttrOf(a,b)		(AttrOf(a) == AttrOf(b))
+#define VIDATTR(attr, pair)	vidattr(attr)
+#endif
+
+#define WINDOW_ATTRS(w)		((w)->_attrs)
+
+#define SCREEN_ATTRS(s)		(*((s)->_current_attr))
+#define GET_SCREEN_PAIR(s)	GetPair(SCREEN_ATTRS(s))
+#define SET_SCREEN_PAIR(s,p)	SetPair(SCREEN_ATTRS(s), p)
+
+/*
+ * Definitions for color pairs
+ */
+typedef unsigned colorpair_t;	/* type big enough to store PAIR_OF() */
+#define C_SHIFT 9		/* we need more bits than there are colors */
+#define C_MASK			((1 << C_SHIFT) - 1)
+#define PAIR_OF(fg, bg)		((((fg) & C_MASK) << C_SHIFT) | ((bg) & C_MASK))
+#define isDefaultColor(c)	((c) >= COLOR_DEFAULT || (c) < 0)
+
+#define COLOR_DEFAULT		C_MASK
+
+#if defined(USE_TERMLIB) && !defined(NEED_NCURSES_CH_T)
+
+#undef NCURSES_CH_T		/* this is not a termlib feature */
+#define NCURSES_CH_T void	/* ...but we need a pointer in SCREEN */
+
+#endif	/* USE_TERMLIB */
+
+#ifndef USE_TERMLIB
+struct ldat
+{
+	NCURSES_CH_T	*text;		/* text of the line */
+	NCURSES_SIZE_T	firstchar;	/* first changed character in the line */
+	NCURSES_SIZE_T	lastchar;	/* last changed character in the line */
+	NCURSES_SIZE_T	oldindex;	/* index of the line at last update */
+};
+#endif	/* USE_TERMLIB */
+
+typedef enum {
+	M_XTERM	= -1		/* use xterm's mouse tracking? */
+	,M_NONE = 0		/* no mouse device */
+#if USE_GPM_SUPPORT
+	,M_GPM			/* use GPM */
+#endif
+#if USE_SYSMOUSE
+	,M_SYSMOUSE		/* FreeBSD sysmouse on console */
+#endif
+} MouseType;
+
+/*
+ * Structures for scrolling.
+ */
+
+typedef struct {
+	unsigned long hashval;
+	int oldcount, newcount;
+	int oldindex, newindex;
+} HASHMAP;
+
+/*
+ * Structures for soft labels.
+ */
+
+struct _SLK;
+
+#ifndef USE_TERMLIB
+
+typedef struct
+{
+	char *ent_text;		/* text for the label */
+	char *form_text;	/* formatted text (left/center/...) */
+	int ent_x;		/* x coordinate of this field */
+	char dirty;		/* this label has changed */
+	char visible;		/* field is visible */
+} slk_ent;
+
+typedef struct _SLK {
+	char dirty;		/* all labels have changed */
+	char hidden;		/* soft labels are hidden */
+	WINDOW *win;
+	slk_ent *ent;
+	short  maxlab;		/* number of available labels */
+	short  labcnt;		/* number of allocated labels */
+	short  maxlen;		/* length of labels */
+	NCURSES_CH_T attr;	/* soft label attribute */
+} SLK;
+
+#endif	/* USE_TERMLIB */
+
+typedef	struct {
+	int	line;		/* lines to take, < 0 => from bottom*/
+	int	(*hook)(WINDOW *, int); /* callback for user	    */
+	WINDOW *w;		/* maybe we need this for cleanup   */
+} ripoff_t;
+
+#if USE_GPM_SUPPORT
+#undef buttons			/* term.h defines this, and gpm uses it! */
+#include <gpm.h>
+
+#ifdef HAVE_LIBDL
+/* link dynamically to GPM */
+typedef int *TYPE_gpm_fd;
+typedef int (*TYPE_Gpm_Open) (Gpm_Connect *, int);
+typedef int (*TYPE_Gpm_Close) (void);
+typedef int (*TYPE_Gpm_GetEvent) (Gpm_Event *);
+
+#define my_gpm_fd       SP->_mouse_gpm_fd
+#define my_Gpm_Open     SP->_mouse_Gpm_Open
+#define my_Gpm_Close    SP->_mouse_Gpm_Close
+#define my_Gpm_GetEvent SP->_mouse_Gpm_GetEvent
+#else
+/* link statically to GPM */
+#define my_gpm_fd       &gpm_fd
+#define my_Gpm_Open     Gpm_Open
+#define my_Gpm_Close    Gpm_Close
+#define my_Gpm_GetEvent Gpm_GetEvent
+#endif /* HAVE_LIBDL */
+#endif /* USE_GPM_SUPPORT */
+
+/*
+ * The SCREEN structure.
+ */
+
+struct screen {
+	int		_ifd;		/* input file ptr for screen	    */
+	FILE		*_ofp;		/* output file ptr for screen	    */
+	char		*_setbuf;	/* buffered I/O for output	    */
+	bool		_filtered;	/* filter() was called		    */
+	bool		_buffered;	/* setvbuf uses _setbuf data	    */
+	int		_checkfd;	/* filedesc for typeahead check	    */
+	//// TERMINAL	*_term;		/* terminal type information	    */
+	short		_lines;		/* screen lines			    */
+	short		_columns;	/* screen columns		    */
+
+	short		_lines_avail;	/* lines available for stdscr	    */
+	short		_topstolen;	/* lines stolen from top	    */
+	ripoff_t	_rippedoff[5];	/* list of lines stolen		    */
+	int		_rip_count;	/* ...and total lines stolen	    */
+
+	WINDOW		*_curscr;	/* current screen		    */
+	WINDOW		*_newscr;	/* virtual screen to be updated to  */
+	WINDOW		*_stdscr;	/* screen's full-window context	    */
+
+	struct tries	*_keytry;	/* "Try" for use with keypad mode   */
+	struct tries	*_key_ok;	/* Disabled keys via keyok(,FALSE)  */
+	bool		_tried;		/* keypad mode was initialized	    */
+	bool		_keypad_on;	/* keypad mode is currently on	    */
+
+	bool		_called_wgetch;	/* check for recursion in wgetch()  */
+	int		_fifo[FIFO_SIZE];	/* input push-back buffer   */
+	short		_fifohead,	/* head of fifo queue		    */
+			_fifotail,	/* tail of fifo queue		    */
+			_fifopeek,	/* where to peek for next char	    */
+			_fifohold;	/* set if breakout marked	    */
+
+	int		_endwin;	/* are we out of window mode?	    */
+	NCURSES_CH_T	*_current_attr; /* holds current attributes set	    */
+	int		_coloron;	/* is color enabled?		    */
+	int		_color_defs;	/* are colors modified		    */
+	int		_cursor;	/* visibility of the cursor	    */
+	int		_cursrow;	/* physical cursor row		    */
+	int		_curscol;	/* physical cursor column	    */
+	bool		_notty;		/* true if we cannot switch non-tty */
+	int		_nl;		/* True if NL -> CR/NL is on	    */
+	int		_raw;		/* True if in raw mode		    */
+	int		_cbreak;	/* 1 if in cbreak mode		    */
+					/* > 1 if in halfdelay mode	    */
+	int		_echo;		/* True if echo on		    */
+	int		_use_meta;	/* use the meta key?		    */
+	struct _SLK	*_slk;		/* ptr to soft key struct / NULL    */
+	int		slk_format;	/* selected format for this screen  */
+	/* cursor movement costs; units are 10ths of milliseconds */
+#if NCURSES_NO_PADDING
+	int		_no_padding;	/* flag to set if padding disabled  */
+#endif
+	int		_char_padding;	/* cost of character put	    */
+	int		_cr_cost;	/* cost of (carriage_return)	    */
+	int		_cup_cost;	/* cost of (cursor_address)	    */
+	int		_home_cost;	/* cost of (cursor_home)	    */
+	int		_ll_cost;	/* cost of (cursor_to_ll)	    */
+#if USE_HARD_TABS
+	int		_ht_cost;	/* cost of (tab)		    */
+	int		_cbt_cost;	/* cost of (backtab)		    */
+#endif /* USE_HARD_TABS */
+	int		_cub1_cost;	/* cost of (cursor_left)	    */
+	int		_cuf1_cost;	/* cost of (cursor_right)	    */
+	int		_cud1_cost;	/* cost of (cursor_down)	    */
+	int		_cuu1_cost;	/* cost of (cursor_up)		    */
+	int		_cub_cost;	/* cost of (parm_cursor_left)	    */
+	int		_cuf_cost;	/* cost of (parm_cursor_right)	    */
+	int		_cud_cost;	/* cost of (parm_cursor_down)	    */
+	int		_cuu_cost;	/* cost of (parm_cursor_up)	    */
+	int		_hpa_cost;	/* cost of (column_address)	    */
+	int		_vpa_cost;	/* cost of (row_address)	    */
+	/* used in tty_update.c, must be chars */
+	int		_ed_cost;	/* cost of (clr_eos)		    */
+	int		_el_cost;	/* cost of (clr_eol)		    */
+	int		_el1_cost;	/* cost of (clr_bol)		    */
+	int		_dch1_cost;	/* cost of (delete_character)	    */
+	int		_ich1_cost;	/* cost of (insert_character)	    */
+	int		_dch_cost;	/* cost of (parm_dch)		    */
+	int		_ich_cost;	/* cost of (parm_ich)		    */
+	int		_ech_cost;	/* cost of (erase_chars)	    */
+	int		_rep_cost;	/* cost of (repeat_char)	    */
+	int		_hpa_ch_cost;	/* cost of (column_address)	    */
+	int		_cup_ch_cost;	/* cost of (cursor_address)	    */
+	int		_cuf_ch_cost;	/* cost of (parm_cursor_right)	    */
+	int		_inline_cost;	/* cost of inline-move		    */
+	int		_smir_cost;	/* cost of (enter_insert_mode)	    */
+	int		_rmir_cost;	/* cost of (exit_insert_mode)	    */
+	int		_ip_cost;	/* cost of (insert_padding)	    */
+	/* used in lib_mvcur.c */
+	char *		_address_cursor;
+	/* used in tty_update.c */
+	int		_scrolling;	/* 1 if terminal's smart enough to  */
+
+	/* used in lib_color.c */
+	color_t		*_color_table;	/* screen's color palette	     */
+	int		_color_count;	/* count of colors in palette	     */
+	colorpair_t	*_color_pairs;	/* screen's color pair list	     */
+	int		_pair_count;	/* count of color pairs		     */
+#if NCURSES_EXT_FUNCS
+	bool		_default_color; /* use default colors		     */
+	bool		_has_sgr_39_49; /* has ECMA default color support    */
+	int		_default_fg;	/* assumed default foreground	     */
+	int		_default_bg;	/* assumed default background	     */
+#endif
+	chtype		_ok_attributes; /* valid attributes for terminal     */
+	chtype		_xmc_suppress;	/* attributes to suppress if xmc     */
+	chtype		_xmc_triggers;	/* attributes to process if xmc	     */
+	chtype *	_acs_map;	/* the real alternate-charset map    */
+	bool *		_screen_acs_map;
+
+
+	/* used in lib_vidattr.c */
+	bool		_use_rmso;	/* true if we may use 'rmso'	     */
+	bool		_use_rmul;	/* true if we may use 'rmul'	     */
+
+	/*
+	 * These data correspond to the state of the idcok() and idlok()
+	 * functions.  A caveat is in order here:  the XSI and SVr4
+	 * documentation specify that these functions apply to the window which
+	 * is given as an argument.  However, ncurses implements this logic
+	 * only for the newscr/curscr update process, _not_ per-window.
+	 */
+	bool		_nc_sp_idlok;
+	bool		_nc_sp_idcok;
+#define _nc_idlok SP->_nc_sp_idlok
+#define _nc_idcok SP->_nc_sp_idcok
+
+#ifdef NCURSES_MOUSE_VERSION
+	/*
+	 * These are the data that support the mouse interface.
+	 */
+	bool		_mouse_initialized;
+	MouseType	_mouse_type;
+	int		_maxclick;
+	bool		(*_mouse_event) (SCREEN *);
+	bool		(*_mouse_inline)(SCREEN *);
+	bool		(*_mouse_parse) (int);
+	void		(*_mouse_resume)(SCREEN *);
+	void		(*_mouse_wrap)	(SCREEN *);
+	int		_mouse_fd;	/* file-descriptor, if any */
+	bool		_mouse_active;	/* true if initialized */
+	mmask_t		_mouse_mask;
+	NCURSES_CONST char *_mouse_xtermcap; /* string to enable/disable mouse */
+	MEVENT		_mouse_events[EV_MAX];	/* hold the last mouse event seen */
+	MEVENT		*_mouse_eventp;	/* next free slot in event queue */
+#endif
+
+#if USE_GPM_SUPPORT
+	bool		_mouse_gpm_loaded;
+	bool		_mouse_gpm_found;
+#ifdef HAVE_LIBDL
+	TYPE_gpm_fd	_mouse_gpm_fd;
+	TYPE_Gpm_Open	_mouse_Gpm_Open;
+	TYPE_Gpm_Close	_mouse_Gpm_Close;
+	TYPE_Gpm_GetEvent _mouse_Gpm_GetEvent;
+#endif
+	Gpm_Connect	_mouse_gpm_connect;
+#endif /* USE_GPM_SUPPORT */
+
+#if USE_EMX_MOUSE
+	int		_emxmouse_wfd;
+	int		_emxmouse_thread;
+	int		_emxmouse_activated;
+	char		_emxmouse_buttons[4];
+#endif
+
+#if USE_SYSMOUSE
+	MEVENT		_sysmouse_fifo[FIFO_SIZE];
+	int		_sysmouse_head;
+	int		_sysmouse_tail;
+	int		_sysmouse_char_width;	/* character width */
+	int		_sysmouse_char_height;	/* character height */
+	int		_sysmouse_old_buttons;
+	int		_sysmouse_new_buttons;
+#endif
+
+	/*
+	 * This supports automatic resizing
+	 */
+#if USE_SIZECHANGE
+	int		(*_resize)(int,int);
+#endif
+
+	/*
+	 * These are data that support the proper handling of the panel stack on an
+	 * per screen basis.
+	 */
+	//// struct panelhook _panelHook;
+	/*
+	 * Linked-list of all windows, to support '_nc_resizeall()' and
+	 * '_nc_freeall()'
+	 */
+	WINDOWLIST	*_nc_sp_windows;
+#define _nc_windows SP->_nc_sp_windows
+
+	bool		_sig_winch;
+	SCREEN		*_next_screen;
+
+	/* hashes for old and new lines */
+	unsigned long	*oldhash, *newhash;
+	HASHMAP		*hashtab;
+	int		hashtab_len;
+
+	bool		_cleanup;	/* cleanup after int/quit signal */
+	int		(*_outch)(int); /* output handler if not putc */
+
+	int		_legacy_coding;	/* see use_legacy_coding() */
+
+	/*
+	 * ncurses/ncursesw are the same up to this point.
+	 */
+#if USE_WIDEC_SUPPORT
+	/* recent versions of 'screen' have partially-working support for
+	 * UTF-8, but do not permit ACS at the same time (see tty_update.c).
+	 */
+	bool		_screen_acs_fix;
+#endif
+};
+
+extern NCURSES_EXPORT_VAR(SCREEN *) _nc_screen_chain;
+
+	WINDOWLIST {
+	WINDOW	win;	/* first, so WINDOW_EXT() works */
+	WINDOWLIST *next;
+#ifdef _XOPEN_SOURCE_EXTENDED
+	char addch_work[(MB_LEN_MAX * 9) + 1];
+	unsigned addch_used;	/* number of bytes in addch_work[] */
+	int addch_x;		/* x-position for addch_work[] */
+	int addch_y;		/* y-position for addch_work[] */
+#endif
+};
+
+#define WINDOW_EXT(win,field) (((WINDOWLIST *)(win))->field)
+
+/* usually in <limits.h> */
+#ifndef UCHAR_MAX
+#define UCHAR_MAX 255
+#endif
+
+/* The terminfo source is assumed to be 7-bit ASCII */
+#define is7bits(c)	((unsigned)(c) < 128)
+
+/* Checks for isprint() should be done on 8-bit characters (non-wide) */
+#define is8bits(c)	((unsigned)(c) <= UCHAR_MAX)
+
+#ifndef min
+#define min(a,b)	((a) > (b)  ?  (b)  :  (a))
+#endif
+
+#ifndef max
+#define max(a,b)	((a) < (b)  ?  (b)  :  (a))
+#endif
+
+/* usually in <unistd.h> */
+#ifndef STDIN_FILENO
+#define STDIN_FILENO 0
+#endif
+
+#ifndef STDOUT_FILENO
+#define STDOUT_FILENO 1
+#endif
+
+#ifndef STDERR_FILENO
+#define STDERR_FILENO 2
+#endif
+
+#ifndef EXIT_SUCCESS
+#define EXIT_SUCCESS 0
+#endif
+
+#ifndef EXIT_FAILURE
+#define EXIT_FAILURE 1
+#endif
+
+#ifndef R_OK
+#define	R_OK	4		/* Test for read permission.  */
+#endif
+#ifndef W_OK
+#define	W_OK	2		/* Test for write permission.  */
+#endif
+#ifndef X_OK
+#define	X_OK	1		/* Test for execute permission.  */
+#endif
+#ifndef F_OK
+#define	F_OK	0		/* Test for existence.  */
+#endif
+
+#if HAVE_FCNTL_H
+//// #include <fcntl.h>		/* may define O_BINARY	*/
+#endif
+
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
+#ifdef TRACE
+#define TRACE_OUTCHARS(n) _nc_outchars += (n);
+#else
+#define TRACE_OUTCHARS(n) /* nothing */
+#endif
+
+#define UChar(c)	((unsigned char)(c))
+#define ChCharOf(c)	((c) & (chtype)A_CHARTEXT)
+#define ChAttrOf(c)	((c) & (chtype)A_ATTRIBUTES)
+
+#ifndef MB_LEN_MAX
+#define MB_LEN_MAX 8 /* should be >= MB_CUR_MAX, but that may be a function */
+#endif
+
+#if USE_WIDEC_SUPPORT /* { */
+#define isEILSEQ(status) ((status == (size_t)-1) && (errno == EILSEQ))
+
+#define init_mb(state)	memset(&state, 0, sizeof(state))
+
+#if NCURSES_EXT_COLORS
+#define NulColor	, 0
+#else
+#define NulColor	/* nothing */
+#endif
+
+#define NulChar		0,0,0,0	/* FIXME: see CCHARW_MAX */
+#define CharOf(c)	((c).chars[0])
+#define AttrOf(c)	((c).attr)
+#define AddAttr(c,a)	AttrOf(c) |= ((a) & A_ATTRIBUTES)
+#define RemAttr(c,a)	AttrOf(c) &= ~((a) & A_ATTRIBUTES)
+#define SetAttr(c,a)	AttrOf(c) = ((a) & A_ATTRIBUTES)
+#define NewChar2(c,a)	{ a, { c, NulChar } NulColor }
+#define NewChar(ch)	NewChar2(ChCharOf(ch), ChAttrOf(ch))
+#define CharEq(a,b)	(!memcmp(&(a), &(b), sizeof(a)))
+#define SetChar(ch,c,a) do {							    \
+			    NCURSES_CH_T *_cp = &ch;				    \
+			    memset(_cp, 0, sizeof(ch));				    \
+			    _cp->chars[0] = (c);					    \
+			    _cp->attr = (a);					    \
+			    if_EXT_COLORS(SetPair(ch, PAIR_NUMBER(a)));		    \
+			} while (0)
+#define CHREF(wch)	(&wch)
+#define CHDEREF(wch)	(*wch)
+#define ARG_CH_T	NCURSES_CH_T *
+#define CARG_CH_T	const NCURSES_CH_T *
+#define PUTC_DATA	char PUTC_buf[MB_LEN_MAX]; int PUTC_i, PUTC_n; \
+			mbstate_t PUT_st; wchar_t PUTC_ch
+#define PUTC_INIT	init_mb (PUT_st)
+#define PUTC(ch,b)	do { if(!isWidecExt(ch)) {				    \
+			if (Charable(ch)) {					    \
+			    fputc(CharOf(ch), b);				    \
+			    TRACE_OUTCHARS(1);					    \
+			} else {						    \
+			    PUTC_INIT;						    \
+			    for (PUTC_i = 0; PUTC_i < CCHARW_MAX; ++PUTC_i) {	    \
+				PUTC_ch = (ch).chars[PUTC_i];			    \
+				if (PUTC_ch == L'\0')				    \
+				    break;					    \
+				PUTC_n = wcrtomb(PUTC_buf,			    \
+						 (ch).chars[PUTC_i], &PUT_st);	    \
+				if (PUTC_n <= 0) {				    \
+				    if (PUTC_ch && is8bits(PUTC_ch) && PUTC_i == 0) \
+					putc(PUTC_ch,b);			    \
+				    break;					    \
+				}						    \
+				fwrite(PUTC_buf, (unsigned) PUTC_n, 1, b);	    \
+			    }							    \
+			    TRACE_OUTCHARS(PUTC_i);				    \
+			} } } while (0)
+
+#define BLANK		{ WA_NORMAL, {' '} NulColor }
+#define ZEROS		{ WA_NORMAL, {'\0'} NulColor }
+#define ISBLANK(ch)	((ch).chars[0] == L' ' && (ch).chars[1] == L'\0')
+
+	/*
+	 * Wide characters cannot be represented in the A_CHARTEXT mask of
+	 * attr_t's but an application might have set a narrow character there.
+	 * But even in that case, it would only be a printable character, or
+	 * zero.  Otherwise we can use those bits to tell if a cell is the
+	 * first or extension part of a wide character.
+	 */
+#define WidecExt(ch)	(AttrOf(ch) & A_CHARTEXT)
+#define isWidecBase(ch)	(WidecExt(ch) == 1)
+#define isWidecExt(ch)	(WidecExt(ch) > 1 && WidecExt(ch) < 32)
+#define SetWidecExt(dst, ext)	AttrOf(dst) &= ~A_CHARTEXT,		\
+				AttrOf(dst) |= (ext + 1)
+
+#define if_WIDEC(code)  code
+#define Charable(ch)	((SP != 0 && SP->_legacy_coding)		\
+			 || (AttrOf(ch) & A_ALTCHARSET)			\
+			 || (!isWidecExt(ch) &&				\
+			     (ch).chars[1] == L'\0' &&			\
+			     _nc_is_charable(CharOf(ch))))
+
+#define L(ch)		L ## ch
+#else /* }{ */
+#define CharOf(c)	ChCharOf(c)
+#define AttrOf(c)	ChAttrOf(c)
+#define AddAttr(c,a)	c |= (a)
+#define RemAttr(c,a)	c &= ~((a) & A_ATTRIBUTES)
+#define SetAttr(c,a)	c = ((c) & ~A_ATTRIBUTES) | (a)
+#define NewChar(ch)	(ch)
+#define NewChar2(c,a)	((c) | (a))
+#define CharEq(a,b)	((a) == (b))
+#define SetChar(ch,c,a)	ch = (c) | (a)
+#define CHREF(wch)	wch
+#define CHDEREF(wch)	wch
+#define ARG_CH_T	NCURSES_CH_T
+#define CARG_CH_T	NCURSES_CH_T
+#define PUTC_DATA	int data = 0
+#define PUTC(ch,b)	do { data = CharOf(ch); putc(data,b); } while (0)
+
+#define BLANK		(' '|A_NORMAL)
+#define ZEROS		('\0'|A_NORMAL)
+#define ISBLANK(ch)	(CharOf(ch) == ' ')
+
+#define isWidecExt(ch)	(0)
+#define if_WIDEC(code) /* nothing */
+
+#define L(ch)		ch
+#endif /* } */
+
+#define AttrOfD(ch)	AttrOf(CHDEREF(ch))
+#define CharOfD(ch)	CharOf(CHDEREF(ch))
+#define SetChar2(wch,ch)    SetChar(wch,ChCharOf(ch),ChAttrOf(ch))
+
+#define BLANK_ATTR	A_NORMAL
+#define BLANK_TEXT	L(' ')
+
+#define CHANGED     -1
+
+#define LEGALYX(w, y, x) \
+	      ((w) != 0 && \
+		((x) >= 0 && (x) <= (w)->_maxx && \
+		 (y) >= 0 && (y) <= (w)->_maxy))
+
+#define CHANGED_CELL(line,col) \
+	if (line->firstchar == _NOCHANGE) \
+		line->firstchar = line->lastchar = col; \
+	else if ((col) < line->firstchar) \
+		line->firstchar = col; \
+	else if ((col) > line->lastchar) \
+		line->lastchar = col
+
+#define CHANGED_RANGE(line,start,end) \
+	if (line->firstchar == _NOCHANGE \
+	 || line->firstchar > (start)) \
+		line->firstchar = start; \
+	if (line->lastchar == _NOCHANGE \
+	 || line->lastchar < (end)) \
+		line->lastchar = end
+
+#define CHANGED_TO_EOL(line,start,end) \
+	if (line->firstchar == _NOCHANGE \
+	 || line->firstchar > (start)) \
+		line->firstchar = start; \
+	line->lastchar = end
+
+#define SIZEOF(v) (sizeof(v)/sizeof(v[0]))
+
+#define FreeIfNeeded(p)  if ((p) != 0) free(p)
+
+/* FreeAndNull() is not a comma-separated expression because some compilers
+ * do not accept a mixture of void with values.
+ */
+#define FreeAndNull(p)   free(p); p = 0
+
+//// #include <nc_alloc.h>
+
+/*
+ * TTY bit definition for converting tabs to spaces.
+ */
+#ifdef TAB3
+# define OFLAGS_TABS TAB3	/* POSIX specifies TAB3 */
+#else
+# ifdef XTABS
+#  define OFLAGS_TABS XTABS	/* XTABS is usually the "same" */
+# else
+#  ifdef OXTABS
+#   define OFLAGS_TABS OXTABS	/* the traditional BSD equivalent */
+#  else
+#   define OFLAGS_TABS 0
+#  endif
+# endif
+#endif
+
+/*
+ * Prefixes for call/return points of library function traces.  We use these to
+ * instrument the public functions so that the traces can be easily transformed
+ * into regression scripts.
+ */
+#define T_CALLED(fmt) "called {" fmt
+#define T_CREATE(fmt) "create :" fmt
+#define T_RETURN(fmt) "return }" fmt
+
+#ifdef TRACE
+
+#define START_TRACE() \
+	if ((_nc_tracing & TRACE_MAXIMUM) == 0) { \
+	    int t = _nc_getenv_num("NCURSES_TRACE"); \
+	    if (t >= 0) \
+		trace((unsigned) t); \
+	}
+
+#define TR(n, a)	if (_nc_tracing & (n)) _tracef a
+#define T(a)		TR(TRACE_CALLS, a)
+#define TPUTS_TRACE(s)	_nc_tputs_trace = s;
+#define TRACE_RETURN(value,type) return _nc_retrace_##type(value)
+
+#define returnAttr(code)	TRACE_RETURN(code,attr_t)
+#define returnBits(code)	TRACE_RETURN(code,unsigned)
+#define returnBool(code)	TRACE_RETURN(code,bool)
+#define returnCPtr(code)	TRACE_RETURN(code,cptr)
+#define returnCVoidPtr(code)	TRACE_RETURN(code,cvoid_ptr)
+#define returnChar(code)	TRACE_RETURN(code,chtype)
+#define returnCode(code)	TRACE_RETURN(code,int)
+#define returnPtr(code)		TRACE_RETURN(code,ptr)
+#define returnSP(code)		TRACE_RETURN(code,sp)
+#define returnVoid		T((T_RETURN(""))); return
+#define returnVoidPtr(code)	TRACE_RETURN(code,void_ptr)
+#define returnWin(code)		TRACE_RETURN(code,win)
+
+extern NCURSES_EXPORT(NCURSES_BOOL)     _nc_retrace_bool (NCURSES_BOOL);
+extern NCURSES_EXPORT(NCURSES_CONST void *) _nc_retrace_cvoid_ptr (NCURSES_CONST void *);
+extern NCURSES_EXPORT(SCREEN *)         _nc_retrace_sp (SCREEN *);
+extern NCURSES_EXPORT(WINDOW *)         _nc_retrace_win (WINDOW *);
+extern NCURSES_EXPORT(attr_t)           _nc_retrace_attr_t (attr_t);
+extern NCURSES_EXPORT(char *)           _nc_retrace_ptr (char *);
+extern NCURSES_EXPORT(char *)           _nc_trace_ttymode(TTY *tty);
+extern NCURSES_EXPORT(char *)           _nc_varargs (const char *, va_list);
+extern NCURSES_EXPORT(chtype)           _nc_retrace_chtype (chtype);
+extern NCURSES_EXPORT(const char *)     _nc_altcharset_name(attr_t, chtype);
+extern NCURSES_EXPORT(const char *)     _nc_retrace_cptr (const char *);
+extern NCURSES_EXPORT(int)              _nc_retrace_int (int);
+extern NCURSES_EXPORT(unsigned)         _nc_retrace_unsigned (unsigned);
+extern NCURSES_EXPORT(void *)           _nc_retrace_void_ptr (void *);
+extern NCURSES_EXPORT(void)             _nc_fifo_dump (void);
+extern NCURSES_EXPORT_VAR(const char *) _nc_tputs_trace;
+extern NCURSES_EXPORT_VAR(long)         _nc_outchars;
+extern NCURSES_EXPORT_VAR(unsigned)     _nc_tracing;
+
+#if USE_WIDEC_SUPPORT
+extern NCURSES_EXPORT(const char *) _nc_viswbuf2 (int, const wchar_t *);
+extern NCURSES_EXPORT(const char *) _nc_viswbufn (const wchar_t *, int);
+#endif
+
+extern NCURSES_EXPORT(const char *) _nc_viscbuf2 (int, const NCURSES_CH_T *, int);
+extern NCURSES_EXPORT(const char *) _nc_viscbuf (const NCURSES_CH_T *, int);
+
+#else /* !TRACE */
+
+#define START_TRACE() /* nothing */
+
+#define T(a)
+#define TR(n, a)
+#define TPUTS_TRACE(s)
+
+#define returnAttr(code)	return code
+#define returnBits(code)	return code
+#define returnBool(code)	return code
+#define returnCPtr(code)	return code
+#define returnCVoidPtr(code)	return code
+#define returnChar(code)	return code
+#define returnCode(code)	return code
+#define returnPtr(code)		return code
+#define returnSP(code)		return code
+#define returnVoid		return
+#define returnVoidPtr(code)	return code
+#define returnWin(code)		return code
+
+#endif /* TRACE/!TRACE */
+
+/*
+ * Return-codes for tgetent() and friends.
+ */
+#define TGETENT_YES  1		/* entry is found */
+#define TGETENT_NO   0		/* entry is not found */
+#define TGETENT_ERR -1		/* an error occurred */
+
+extern NCURSES_EXPORT(const char *) _nc_visbuf2 (int, const char *);
+extern NCURSES_EXPORT(const char *) _nc_visbufn (const char *, int);
+
+#define empty_module(name) \
+extern	NCURSES_EXPORT(void) name (void); \
+	NCURSES_EXPORT(void) name (void) { }
+
+#define ALL_BUT_COLOR ((chtype)~(A_COLOR))
+#define NONBLANK_ATTR (A_NORMAL|A_BOLD|A_DIM|A_BLINK)
+#define XMC_CHANGES(c) ((c) & SP->_xmc_suppress)
+
+#define toggle_attr_on(S,at) {\
+   if (PAIR_NUMBER(at) > 0) {\
+      (S) = ((S) & ALL_BUT_COLOR) | (at);\
+   } else {\
+      (S) |= (at);\
+   }\
+   TR(TRACE_ATTRS, ("new attribute is %s", _traceattr((S))));}
+
+
+#define toggle_attr_off(S,at) {\
+   if (PAIR_NUMBER(at) > 0) {\
+      (S) &= ~(at|A_COLOR);\
+   } else {\
+      (S) &= ~(at);\
+   }\
+   TR(TRACE_ATTRS, ("new attribute is %s", _traceattr((S))));}
+
+#define DelCharCost(count) \
+		((parm_dch != 0) \
+		? SP->_dch_cost \
+		: ((delete_character != 0) \
+			? (SP->_dch1_cost * count) \
+			: INFINITY))
+
+#define InsCharCost(count) \
+		((parm_ich != 0) \
+		? SP->_ich_cost \
+		: ((enter_insert_mode && exit_insert_mode) \
+		  ? SP->_smir_cost + SP->_rmir_cost + (SP->_ip_cost * count) \
+		  : ((insert_character != 0) \
+		    ? ((SP->_ich1_cost + SP->_ip_cost) * count) \
+		    : INFINITY)))
+
+#if USE_XMC_SUPPORT
+#define UpdateAttrs(c)	if (!SameAttrOf(SCREEN_ATTRS(SP), c)) { \
+				attr_t chg = AttrOf(SCREEN_ATTRS(SP)); \
+				VIDATTR(AttrOf(c), GetPair(c)); \
+				if (magic_cookie_glitch > 0 \
+				 && XMC_CHANGES((chg ^ AttrOf(SCREEN_ATTRS(SP))))) { \
+					T(("%s @%d before glitch %d,%d", \
+						__FILE__, __LINE__, \
+						SP->_cursrow, \
+						SP->_curscol)); \
+					_nc_do_xmc_glitch(chg); \
+				} \
+			}
+#else
+#define UpdateAttrs(c)	if (!SameAttrOf(SCREEN_ATTRS(SP), c)) \
+				VIDATTR(AttrOf(c), GetPair(c));
+#endif
+
+/*
+ * Macros to make additional parameter to implement wgetch_events()
+ */
+#ifdef NCURSES_WGETCH_EVENTS
+#define EVENTLIST_0th(param) param
+#define EVENTLIST_1st(param) param
+#define EVENTLIST_2nd(param) , param
+#else
+#define EVENTLIST_0th(param) void
+#define EVENTLIST_1st(param) /* nothing */
+#define EVENTLIST_2nd(param) /* nothing */
+#endif
+
+#if NCURSES_EXPANDED && NCURSES_EXT_FUNCS
+
+#undef  toggle_attr_on
+#define toggle_attr_on(S,at) _nc_toggle_attr_on(&(S), at)
+extern NCURSES_EXPORT(void) _nc_toggle_attr_on (attr_t *, attr_t);
+
+#undef  toggle_attr_off
+#define toggle_attr_off(S,at) _nc_toggle_attr_off(&(S), at)
+extern NCURSES_EXPORT(void) _nc_toggle_attr_off (attr_t *, attr_t);
+
+#undef  DelCharCost
+#define DelCharCost(count) _nc_DelCharCost(count)
+extern NCURSES_EXPORT(int) _nc_DelCharCost (int);
+
+#undef  InsCharCost
+#define InsCharCost(count) _nc_InsCharCost(count)
+extern NCURSES_EXPORT(int) _nc_InsCharCost (int);
+
+#undef  UpdateAttrs
+#define UpdateAttrs(c) _nc_UpdateAttrs(c)
+extern NCURSES_EXPORT(void) _nc_UpdateAttrs (NCURSES_CH_T);
+
+#else
+
+extern NCURSES_EXPORT(void) _nc_expanded (void);
+
+#endif
+
+#if !HAVE_GETCWD
+#define getcwd(buf,len) getwd(buf)
+#endif
+
+/* charable.c */
+#if USE_WIDEC_SUPPORT
+extern NCURSES_EXPORT(bool) _nc_is_charable(wchar_t);
+extern NCURSES_EXPORT(int) _nc_to_char(wint_t);
+extern NCURSES_EXPORT(wint_t) _nc_to_widechar(int);
+#endif
+
+/* doupdate.c */
+#if USE_XMC_SUPPORT
+extern NCURSES_EXPORT(void) _nc_do_xmc_glitch (attr_t);
+#endif
+
+/* hardscroll.c */
+#if defined(TRACE) || defined(SCROLLDEBUG) || defined(HASHDEBUG)
+extern NCURSES_EXPORT(void) _nc_linedump (void);
+#endif
+
+/* lib_acs.c */
+extern NCURSES_EXPORT(void) _nc_init_acs (void);	/* corresponds to traditional 'init_acs()' */
+extern NCURSES_EXPORT(int) _nc_msec_cost (const char *const, int);  /* used by 'tack' program */
+
+/* lib_addch.c */
+#if USE_WIDEC_SUPPORT
+NCURSES_EXPORT(int) _nc_build_wch(WINDOW *win, ARG_CH_T ch);
+#endif
+
+/* lib_addstr.c */
+#if USE_WIDEC_SUPPORT && !defined(USE_TERMLIB)
+extern NCURSES_EXPORT(int) _nc_wchstrlen(const cchar_t *);
+#endif
+
+/* lib_color.c */
+extern NCURSES_EXPORT(bool) _nc_reset_colors(void);
+
+/* lib_getch.c */
+extern NCURSES_EXPORT(int) _nc_wgetch(WINDOW *, unsigned long *, int EVENTLIST_2nd(_nc_eventlist *));
+
+/* lib_insch.c */
+extern NCURSES_EXPORT(int) _nc_insert_ch(WINDOW *, chtype);
+
+/* lib_mvcur.c */
+#define INFINITY	1000000	/* cost: too high to use */
+
+extern NCURSES_EXPORT(void) _nc_mvcur_init (void);
+extern NCURSES_EXPORT(void) _nc_mvcur_resume (void);
+extern NCURSES_EXPORT(void) _nc_mvcur_wrap (void);
+
+extern NCURSES_EXPORT(int) _nc_scrolln (int, int, int, int);
+
+extern NCURSES_EXPORT(void) _nc_screen_init (void);
+extern NCURSES_EXPORT(void) _nc_screen_resume (void);
+extern NCURSES_EXPORT(void) _nc_screen_wrap (void);
+
+/* lib_mouse.c */
+extern NCURSES_EXPORT(int) _nc_has_mouse (void);
+
+/* lib_mvcur.c */
+#define INFINITY	1000000	/* cost: too high to use */
+#define BAUDBYTE	9	/* 9 = 7 bits + 1 parity + 1 stop */
+
+/* lib_setup.c */
+extern NCURSES_EXPORT(char *) _nc_get_locale(void);
+extern NCURSES_EXPORT(int) _nc_unicode_locale(void);
+extern NCURSES_EXPORT(int) _nc_locale_breaks_acs(void);
+extern NCURSES_EXPORT(int) _nc_setupterm(NCURSES_CONST char *, int, int *, bool);
+
+/* lib_tstp.c */
+#if USE_SIGWINCH
+extern NCURSES_EXPORT(int) _nc_handle_sigwinch(int);
+#else
+#define _nc_handle_sigwinch(a) /* nothing */
+#endif
+
+/* lib_wacs.c */
+#if USE_WIDEC_SUPPORT
+extern NCURSES_EXPORT(void) _nc_init_wacs(void);
+#endif
+
+typedef struct {
+    char *s_head;	/* beginning of the string (may be null) */
+    char *s_tail;	/* end of the string (may be null) */
+    size_t s_size;	/* current remaining size available */
+    size_t s_init;	/* total size available */
+} string_desc;
+
+/* strings.c */
+extern NCURSES_EXPORT(string_desc *) _nc_str_init (string_desc *, char *, size_t);
+extern NCURSES_EXPORT(string_desc *) _nc_str_null (string_desc *, size_t);
+extern NCURSES_EXPORT(string_desc *) _nc_str_copy (string_desc *, string_desc *);
+extern NCURSES_EXPORT(bool) _nc_safe_strcat (string_desc *, const char *);
+extern NCURSES_EXPORT(bool) _nc_safe_strcpy (string_desc *, const char *);
+
+#if !HAVE_STRSTR
+#define strstr _nc_strstr
+extern NCURSES_EXPORT(char *) _nc_strstr (const char *, const char *);
+#endif
+
+/* safe_sprintf.c */
+extern NCURSES_EXPORT(char *) _nc_printf_string (const char *, va_list);
+
+/* tries.c */
+extern NCURSES_EXPORT(void) _nc_add_to_try (struct tries **, const char *, unsigned);
+extern NCURSES_EXPORT(char *) _nc_expand_try (struct tries *, unsigned, int *, size_t);
+extern NCURSES_EXPORT(int) _nc_remove_key (struct tries **, unsigned);
+extern NCURSES_EXPORT(int) _nc_remove_string (struct tries **, const char *);
+
+/* elsewhere ... */
+//// extern NCURSES_EXPORT(ENTRY *) _nc_delink_entry(ENTRY *, TERMTYPE *);
+extern NCURSES_EXPORT(WINDOW *) _nc_makenew (int, int, int, int, int);
+extern NCURSES_EXPORT(char *) _nc_trace_buf (int, size_t);
+extern NCURSES_EXPORT(char *) _nc_trace_bufcat (int, const char *);
+extern NCURSES_EXPORT(int) _nc_access (const char *, int);
+extern NCURSES_EXPORT(int) _nc_baudrate (int);
+extern NCURSES_EXPORT(int) _nc_freewin (WINDOW *);
+extern NCURSES_EXPORT(int) _nc_getenv_num (const char *);
+extern NCURSES_EXPORT(int) _nc_keypad (bool);
+extern NCURSES_EXPORT(int) _nc_ospeed (int);
+extern NCURSES_EXPORT(int) _nc_outch (int);
+//// extern NCURSES_EXPORT(int) _nc_read_termcap_entry (const char *const, TERMTYPE *const);
+extern NCURSES_EXPORT(int) _nc_setupscreen (int, int, FILE *, bool, int);
+extern NCURSES_EXPORT(int) _nc_timed_wait(int, int, int * EVENTLIST_2nd(_nc_eventlist *));
+extern NCURSES_EXPORT(void) _nc_do_color (short, short, bool, int (*)(int));
+extern NCURSES_EXPORT(void) _nc_flush (void);
+//// extern NCURSES_EXPORT(void) _nc_free_entry(ENTRY *, TERMTYPE *);
+extern NCURSES_EXPORT(void) _nc_freeall (void);
+extern NCURSES_EXPORT(void) _nc_hash_map (void);
+extern NCURSES_EXPORT(void) _nc_init_keytry (void);
+extern NCURSES_EXPORT(void) _nc_keep_tic_dir (const char *);
+extern NCURSES_EXPORT(void) _nc_make_oldhash (int i);
+extern NCURSES_EXPORT(void) _nc_scroll_oldhash (int n, int top, int bot);
+extern NCURSES_EXPORT(void) _nc_scroll_optimize (void);
+extern NCURSES_EXPORT(void) _nc_set_buffer (FILE *, bool);
+extern NCURSES_EXPORT(void) _nc_signal_handler (bool);
+extern NCURSES_EXPORT(void) _nc_synchook (WINDOW *);
+extern NCURSES_EXPORT(void) _nc_trace_tries (struct tries *);
+
+#if NO_LEAKS
+extern NCURSES_EXPORT(void) _nc_alloc_entry_leaks(void);
+extern NCURSES_EXPORT(void) _nc_captoinfo_leaks(void);
+extern NCURSES_EXPORT(void) _nc_comp_scan_leaks(void);
+extern NCURSES_EXPORT(void) _nc_keyname_leaks(void);
+extern NCURSES_EXPORT(void) _nc_tgetent_leaks(void);
+#endif
+
+#ifndef USE_TERMLIB
+extern NCURSES_EXPORT(NCURSES_CH_T) _nc_render (WINDOW *, NCURSES_CH_T);
+extern NCURSES_EXPORT(int) _nc_waddch_nosync (WINDOW *, const NCURSES_CH_T);
+extern NCURSES_EXPORT(void) _nc_scroll_window (WINDOW *, int const, NCURSES_SIZE_T const, NCURSES_SIZE_T const, NCURSES_CH_T);
+#endif
+
+#if USE_WIDEC_SUPPORT && !defined(USE_TERMLIB)
+#ifdef linux
+extern NCURSES_EXPORT(size_t) _nc_wcrtomb (char *, wchar_t, mbstate_t *);
+#else
+#define _nc_wcrtomb(s,wc,ps) wcrtomb(s,wc,ps)
+#endif
+#endif
+
+#if USE_SIZECHANGE
+extern NCURSES_EXPORT(void) _nc_update_screensize (void);
+#endif
+
+#if HAVE_RESIZETERM
+extern NCURSES_EXPORT(void) _nc_resize_margins (WINDOW *);
+#else
+#define _nc_resize_margins(wp) /* nothing */
+#endif
+
+#ifdef NCURSES_WGETCH_EVENTS
+extern NCURSES_EXPORT(int) _nc_eventlist_timeout(_nc_eventlist *);
+#else
+#define wgetch_events(win, evl) wgetch(win)
+#define wgetnstr_events(win, str, maxlen, evl) wgetnstr(win, str, maxlen)
+#endif
+
+/*
+ * Not everyone has vsscanf(), but we'd like to use it for scanw().
+ */
+#if !HAVE_VSSCANF
+extern int vsscanf(const char *str, const char *format, va_list __arg);
+#endif
+
+/* scroll indices */
+extern NCURSES_EXPORT_VAR(int *) _nc_oldnums;
+
+#define USE_SETBUF_0 0
+
+#define NC_BUFFERED(flag) _nc_set_buffer(SP->_ofp, flag)
+
+#define NC_OUTPUT ((SP != 0) ? SP->_ofp : stdout)
+
+/*
+ * On systems with a broken linker, define 'SP' as a function to force the
+ * linker to pull in the data-only module with 'SP'.
+ */
+#if BROKEN_LINKER
+#define SP _nc_screen()
+extern NCURSES_EXPORT(SCREEN *) _nc_screen (void);
+extern NCURSES_EXPORT(int) _nc_alloc_screen (void);
+extern NCURSES_EXPORT(void) _nc_set_screen (SCREEN *);
+#else
+/* current screen is private data; avoid possible linking conflicts too */
+extern NCURSES_EXPORT_VAR(SCREEN *) SP;
+#define _nc_alloc_screen() ((SP = typeCalloc(SCREEN, 1)) != 0)
+#define _nc_set_screen(sp) SP = sp
+#endif
+
+/*
+ * We don't want to use the lines or columns capabilities internally, because
+ * if the application is running multiple screens under X, it's quite possible
+ * they could all have type xterm but have different sizes!  So...
+ */
+#define screen_lines	SP->_lines
+#define screen_columns	SP->_columns
+
+extern NCURSES_EXPORT_VAR(int) _nc_slk_format;  /* != 0 if slk_init() called */
+extern NCURSES_EXPORT(int) _nc_slk_initialize (WINDOW *, int);
+
+/*
+ * Some constants related to SLK's
+ */
+#define MAX_SKEY_OLD	   8	/* count of soft keys */
+#define MAX_SKEY_LEN_OLD   8	/* max length of soft key text */
+#define MAX_SKEY_PC       12    /* This is what most PC's have */
+#define MAX_SKEY_LEN_PC    5
+
+/* Macro to check whether or not we use a standard format */
+#define SLK_STDFMT(fmt) (fmt < 3)
+/* Macro to determine height of label window */
+#define SLK_LINES(fmt)  (SLK_STDFMT(fmt) ? 1 : ((fmt) - 2))
+
+#define MAX_SKEY(fmt)     (SLK_STDFMT(fmt)? MAX_SKEY_OLD : MAX_SKEY_PC)
+#define MAX_SKEY_LEN(fmt) (SLK_STDFMT(fmt)? MAX_SKEY_LEN_OLD : MAX_SKEY_LEN_PC)
+
+extern NCURSES_EXPORT(int) _nc_ripoffline (int line, int (*init)(WINDOW *,int));
+
+/*
+ * Common error messages
+ */
+#define MSG_NO_MEMORY "Out of memory"
+#define MSG_NO_INPUTS "Premature EOF"
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CURSES_PRIV_H */
diff --git a/apps/lib/curses/tinycurses/keyboard.c b/apps/lib/curses/tinycurses/keyboard.c
new file mode 100644
index 0000000..2122d86
--- /dev/null
+++ b/apps/lib/curses/tinycurses/keyboard.c
@@ -0,0 +1,247 @@
+/*
+ * This file is part of the libpayload project.
+ *
+ * Copyright (C) 2007 Uwe Hermann <uwe@hermann-uwe.de>
+ * Copyright (C) 2008 Advanced Micro Devices, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * This file handles reading keystrokes from serial and the console
+ * and "cooking" them so that they are correct for curses.
+ * Also, implement key related functions (mainly wgetch)
+ *
+ * TODO:
+ * Actually cook the serial (handle special keys)
+ */
+
+#include "local.h"
+#include <unistd.h>
+
+static int _halfdelay = 0;
+
+/* ============== Serial ==================== */
+
+#ifdef CONFIG_SERIAL_CONSOLE
+/* We treat serial like a vt100 terminal.  For now we
+   do the cooking in here, but we should probably eventually
+   pass it to dedicated vt100 code */
+
+static int getkeyseq(char *buffer, int len, int max)
+{
+	int i;
+
+	while (1) {
+		for(i = 0; i < 75; i++) {
+			if (tstc())
+				break;
+			usleep(100);
+		}
+
+		if (i == 75)
+			return len;
+
+		buffer[len++] = getchar();
+		if (len == max)
+			return len;
+	}
+}
+
+static struct {
+	const char *seq;
+	int key;
+} escape_codes[] = {
+	{ "[A", KEY_UP },
+	{ "[B", KEY_DOWN },
+	{ "[C", KEY_RIGHT },
+	{ "[D", KEY_LEFT },
+	{ "[F", KEY_END },
+	{ "[H", KEY_HOME },
+	{ "[2~", KEY_IC },
+	{ "[3~", KEY_DC },
+	{ "[5~", KEY_PPAGE },
+	{ "[6~", KEY_NPAGE },
+	{ "OP", KEY_F(1) },
+	{ "OQ", KEY_F(2) },
+	{ "OR", KEY_F(3) },
+	{ "OS", KEY_F(4) },
+	{ "[15~", KEY_F(5) },
+	{ "[17~", KEY_F(6) },
+	{ "[18~", KEY_F(7) },
+	{ "[19~", KEY_F(8) },
+	{ "[20~", KEY_F(9) },
+	{ "[21~", KEY_F(10) },
+	{ "[23~", KEY_F(11) },
+	{ "[24~", KEY_F(12) },
+	{ NULL },
+};
+
+static int handle_escape(void)
+{
+	char buffer[5];
+	int len = getkeyseq(buffer, 0, sizeof(buffer));
+	int i, t;
+
+	if (len == 0)
+		return 27;
+
+	for(i = 0; escape_codes[i].seq != NULL; i++) {
+		const char *p = escape_codes[i].seq;
+
+		for(t = 0; t < len; t++) {
+			if (!*p || *p != buffer[t])
+				break;
+			p++;
+		}
+
+		if (t == len)
+			return escape_codes[i].key;
+	}
+
+	return 0;
+}
+
+static int cook_serial(unsigned char ch)
+{
+	switch(ch) {
+	case 8:
+		return KEY_BACKSPACE;
+
+	case 13:
+		return KEY_ENTER;
+
+	case 27:
+		return handle_escape();
+
+	default:
+		return ch;
+	}
+}
+#endif
+
+/* ================ Keyboard ================ */
+
+static int curses_getchar(int _delay)
+{
+#if defined(CONFIG_SERIAL_CONSOLE)
+	unsigned short c;
+#endif
+
+	do {
+#ifdef CONFIG_SERIAL_CONSOLE
+		if ((curses_flags & F_ENABLE_SERIAL) &&
+		    tstc()) {
+			c = getchar();
+			return cook_serial(c);
+		}
+#endif
+
+		if (_delay == 0)
+			break;
+
+		if (_delay > 0) {
+			usleep(1000);
+			_delay--;
+		}
+
+
+	} while (1);
+
+	return ERR;
+}
+
+/* === Public functions === */
+
+int wgetch(WINDOW *win)
+{
+	int _delay = -1;
+
+	if (_halfdelay)
+		_delay = _halfdelay;
+	else
+		_delay = win->_delay;
+
+	return curses_getchar(_delay);
+}
+
+int nodelay(WINDOW *win, NCURSES_BOOL flag)
+{
+	win->_delay = flag ? 0 : -1;
+	return 0;
+}
+
+int halfdelay(int tenths)
+{
+	if (tenths > 255)
+		return ERR;
+
+	_halfdelay = tenths;
+	return 0;
+}
+
+int nocbreak(void)
+{
+	/* Remove half delay timeout. */
+	_halfdelay = 0;
+	return 0;
+}
+
+#ifdef CONFIG_VGA_VIDEO_CONSOLE
+void curses_enable_vga(int state)
+{
+	if (state)
+		curses_flags |= F_ENABLE_CONSOLE;
+	else
+		curses_flags &= ~F_ENABLE_CONSOLE;
+}
+
+int curses_vga_enabled(void)
+{
+	return (curses_flags & F_ENABLE_CONSOLE) != 0;
+}
+#else
+void curses_enable_vga(int state) { }
+int curses_vga_enabled(void) { return 0; }
+#endif
+
+#ifdef CONFIG_SERIAL_CONSOLE
+void curses_enable_serial(int state)
+{
+	if (state)
+		curses_flags |= F_ENABLE_SERIAL;
+	else
+		curses_flags &= ~F_ENABLE_SERIAL;
+}
+
+int curses_serial_enabled(void)
+{
+	return (curses_flags & F_ENABLE_SERIAL) != 0;
+}
+
+#else
+void curses_enable_serial(int state) { }
+int curses_serial_enabled(void) { return 0; }
+#endif
+
diff --git a/apps/lib/curses/tinycurses/local.h b/apps/lib/curses/tinycurses/local.h
new file mode 100644
index 0000000..42ea152
--- /dev/null
+++ b/apps/lib/curses/tinycurses/local.h
@@ -0,0 +1,89 @@
+/*
+ * This file is part of the libpayload project.
+ *
+ * Copyright (C) 2007 Uwe Hermann <uwe@hermann-uwe.de>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CURSES_LOCAL_H
+#define _CURSES_LOCAL_H
+
+/* For curses.priv.h: */
+#define USE_RCS_IDS 0
+#define DECL_ERRNO 0
+#define HAVE_LIBGPM 0
+#define NCURSES_EXT_FUNCS 0
+#define USE_OK_BCOPY 0
+#define USE_MY_MEMMOVE 0
+#define USE_SCROLL_HINTS 0
+#define USE_HASHMAP 0
+#define USE_WIDEC_SUPPORT 0	/* We do _not_ want wide character support. */
+// #define NCURSES_EXT_COLORS 1
+#define NCURSES_EXT_COLORS 0
+#define USE_SYSMOUSE 0
+#define NCURSES_NO_PADDING 0
+#define USE_HARD_TABS 0
+#define HAVE_FCNTL_H 0
+#define HAVE_LIMITS_H 1
+#define HAVE_UNISTD_H 1
+#define USE_XMC_SUPPORT 0
+#define NCURSES_EXPANDED 0
+#define HAVE_GETCWD 0
+#define USE_XMC_SUPPORT 0
+#define HAVE_STRSTR 1
+#define NO_LEAKS 0
+#define HAVE_RESIZETERM 0
+#define HAVE_VSSCANF 0
+#define BROKEN_LINKER 0
+
+#undef USE_TERMLIB
+
+#include <curses.h>
+#include <curses.priv.h>
+
+#define SCREEN_X 80
+#define SCREEN_Y 25
+
+/* Flags used to determine what output methods are available */
+
+#ifdef CONFIG_VIDEO_CONSOLE
+#define F_ENABLE_CONSOLE 0x01
+#else
+#define F_ENABLE_CONSOLE 0x00
+#endif
+
+#define CONFIG_SERIAL_CONSOLE
+#ifdef CONFIG_SERIAL_CONSOLE
+#define F_ENABLE_SERIAL  0x02
+#else
+#define F_ENABLE_SERIAL  0x00
+#endif
+
+extern int curses_flags;
+
+/* Share the color table for easy lookup */
+extern unsigned char color_pairs[256];
+
+#endif
diff --git a/apps/lib/curses/tinycurses/tinycurses.c b/apps/lib/curses/tinycurses/tinycurses.c
new file mode 100644
index 0000000..e09c0a5
--- /dev/null
+++ b/apps/lib/curses/tinycurses/tinycurses.c
@@ -0,0 +1,1016 @@
+/*
+ * This file is part of the libpayload project.
+ *
+ * Copyright (C) 2007 Uwe Hermann <uwe@hermann-uwe.de>
+ * Copyright (C) 2008 Ulf Jordan <jordan@chalmers.se>
+ * Copyright (C) 2008-2009 coresystems GmbH
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * This is a tiny implementation of the (n)curses library intended to be
+ * used in embedded/firmware/BIOS code where no libc or operating system
+ * environment is available and code size is very important.
+ *
+ * Design goals:
+ *  - Small object code.
+ *  - Self-contained.
+ *    - Doesn't require a libc (no glibc/uclibc/dietlibc/klibc/newlib).
+ *    - Works without any other external libraries or header files.
+ *  - Works without an underlying operating system.
+ *    - Doesn't use files, signals, syscalls, ttys, library calls, etc.
+ *  - Doesn't do any dynamic memory allocation (no malloc() and friends).
+ *     - All data structures are statically allocated.
+ *  - Supports standard VGA console (80x25) and serial port console.
+ *     - This includes character output and keyboard input over serial.
+ *  - Supports beep() through a minimal PC speaker driver.
+ *
+ * Limitations:
+ *  - Only implements a small subset of the (n)curses functions.
+ *  - Only implements very few sanity checks (for smaller code).
+ *     - Thus: Don't do obviously stupid things in your code.
+ *  - Doesn't implement the 'form', 'panel', and 'menu' extensions.
+ *  - Only implements C bindings (no C++, Ada95, or others).
+ *  - Doesn't include wide character support.
+ */
+
+#include <utils/ansi.h>
+
+#include "local.h"
+
+#undef _XOPEN_SOURCE_EXTENDED
+#define _XOPEN_SOURCE_EXTENDED 1
+
+#define CONFIG_SERIAL_ACS_FALLBACK
+
+#define MAX_WINDOWS 3
+
+/* Statically allocate all structures (no malloc())! */
+static WINDOW window_list[MAX_WINDOWS];
+static int window_count = 1;
+
+// struct ldat foo;
+static struct ldat ldat_list[MAX_WINDOWS][SCREEN_Y];
+static int ldat_count = 0;
+
+/* One item bigger than SCREEN_X to reserve space for a NUL byte. */
+static NCURSES_CH_T linebuf_list[SCREEN_Y * MAX_WINDOWS][SCREEN_X + 1];
+static int linebuf_count = 0;
+
+/* Globals */
+int COLORS;		/* Currently unused? */
+int COLOR_PAIRS = 255;
+WINDOW *stdscr;
+WINDOW *curscr;
+WINDOW *newscr;
+int LINES = 25;
+int COLS = 80;
+int TABSIZE;
+int ESCDELAY;
+// char ttytype[];
+// cchar_t *_nc_wacs;
+SCREEN *SP;
+chtype acs_map[128];
+
+/* See terminfo(5). */
+chtype fallback_acs_map[128] =
+	{
+	' ',	' ',	' ',	' ',	' ',	' ',	' ',	' ',
+	' ',	' ',	' ',	' ',	' ',	' ',	' ',	' ',
+	' ',	' ',	' ',	' ',	' ',	' ',	' ',	' ',
+	' ',	' ',	' ',	' ',	' ',	' ',	' ',	' ',
+	' ',	' ',	' ',	' ',	' ',	' ',	' ',	' ',
+	' ',	' ',	' ',	'>',	'<',	'^',	'v',	' ',
+	'#',	' ',	' ',	' ',	' ',	' ',	' ',	' ',
+	' ',	' ',	' ',	' ',	' ',	' ',	' ',	' ',
+	' ',	' ',	' ',	' ',	' ',	' ',	' ',	' ',
+	' ',	' ',	' ',	' ',	' ',	' ',	' ',	' ',
+	' ',	' ',	' ',	' ',	' ',	' ',	' ',	' ',
+	' ',	' ',	' ',	' ',	' ',	' ',	' ',	' ',
+	'+',	':',	' ',	' ',	' ',	' ',	'\\',   '#',
+	'#',	'#',	'+',	'+',	'+',	'+',	'+',	'~',
+	'-',	'-',	'-',	'_',	'+',	'+',	'+',	'+',
+	'|',	'<',	'>',	'*',	'!',	'f',	'o',	' ',
+	};
+
+#ifdef CONFIG_SERIAL_CONSOLE
+#ifdef CONFIG_SERIAL_ACS_FALLBACK
+chtype serial_acs_map[128];
+#else
+/* See acsc of vt100. */
+chtype serial_acs_map[128] =
+	{
+	0,	0,	0,	0,	0,	0,	0,	0,
+	0,	0,	0,	0,	0,	0,	0,	0,
+	0,	0,	0,	0,	0,	0,	0,	0,
+	0,	0,	0,	0,	0,	0,	0,	0,
+	0,	0,	0,	0,	0,	0,	0,	0,
+	0,	0,	0,	0,	0,	0,	0,	0,
+	0,	0,	0,	0,	0,	0,	0,	0,
+	0,	0,	0,	0,	0,	0,	0,	0,
+	0,	0,	0,	0,	0,	0,	0,	0,
+	0,	0,	0,	0,	0,	0,	0,	0,
+	0,	0,	0,	0,	0,	0,	0,	0,
+	0,	0,	0,	0,	0,	0,	0,	0,
+	'`',	'a',	0,	0,	0,	0,	'f',	'g',
+	0,	0,	'j',	'k',	'l',	'm',	'n',	'o',
+	'p',	'q',	'r',	's',	't',	'u',	'v',	'w',
+	'x',	'y',	'z',	'{',	'|',	'}',	'~',	0,
+	};
+#endif
+#endif
+
+#ifdef CONFIG_VIDEO_CONSOLE
+/* See acsc of linux. */
+chtype console_acs_map[128] =
+	{
+	0,	0,	0,	0,	0,	0,	0,	0,
+	0,	0,	0,	0,	0,	0,	0,	0,
+	0,	0,	0,	0,	0,	0,	0,	0,
+	0,	0,	0,	0,	0,	0,	0,	0,
+	0,	0,	0,	0,	0,	0,	0,	0,
+	0,	0,	0,	'\020', '\021', '\030', '\031',	0,
+	'\333',	0,	0,	0,	0,	0,	0,	0,
+	0,	0,	0,	0,	0,	0,	0,	0,
+	0,	0,	0,	0,	0,	0,	0,	0,
+	0,	0,	0,	0,	0,	0,	0,	0,
+	0,	0,	0,	0,	0,	0,	0,	0,
+	0,	0,	0,	0,	0,	0,	0,	0,
+	'\004',	'\261',	0,	0,	0,	0,	'\370',	'\361',
+	'\260',	'\316',	'\331',	'\277',	'\332',	'\300',	'\305',	'~',
+	'\304',	'\304',	'\304',	'_',	'\303', '\264', '\301',	'\302',
+	'\263',	'\363',	'\362',	'\343',	'\330',	'\234',	'\376',	0,
+	};
+#endif
+
+// FIXME: Ugly (and insecure!) hack!
+char sprintf_tmp[1024];
+
+
+int curses_flags = (F_ENABLE_CONSOLE | F_ENABLE_SERIAL);
+
+/* Return bit mask for clearing color pair number if given ch has color */
+#define COLOR_MASK(ch) (~(attr_t)((ch) & A_COLOR ? A_COLOR : 0))
+
+/* Compute a rendition of the given char correct for the current context. */
+static inline NCURSES_CH_T render_char(WINDOW *win, NCURSES_CH_T ch)
+{
+	/* TODO. */
+	return ch;
+}
+
+/* Make render_char() visible while still allowing us to inline it below. */
+NCURSES_CH_T _nc_render(WINDOW *win, NCURSES_CH_T ch)
+{
+	return render_char(win, ch);
+}
+
+/*
+ * Implementations of most functions marked 'implemented' in include/curses.h:
+ */
+
+// int baudrate(void) {}
+int beep(void)
+{
+	/* TODO: Flash the screen if beeping fails? */
+#ifdef CONFIG_SPEAKER
+	speaker_tone(1760, 500);	/* 1760 == note A6 */
+#endif
+	return OK;
+}
+// bool can_change_color(void) {}
+int cbreak(void) { /* TODO */ return 0; }
+/* D */ int clearok(WINDOW *win, bool flag) { win->_clear = flag; return OK; }
+// int color_content(short color, short *r, short *g, short *b) {}
+int curs_set(int on)
+{
+#ifdef CONFIG_SERIAL_CONSOLE
+	if (curses_flags & F_ENABLE_SERIAL) {
+		ansi_cursor_enable(on);
+	}
+#endif
+#ifdef CONFIG_VIDEO_CONSOLE
+	if (curses_flags & F_ENABLE_CONSOLE) {
+		video_console_cursor_enable(on);
+	}
+#endif
+
+	return OK;
+}
+// int def_prog_mode(void) {}
+// int def_shell_mode(void) {}
+// int delay_output(int) {}
+// void delscreen(SCREEN *) {}
+int delwin(WINDOW *win)
+{
+	/* TODO: Don't try to delete stdscr. */
+	/* TODO: Don't delete parent windows before subwindows. */
+
+	// if (win->_flags & _SUBWIN)
+	// 	touchwin(win->_parent);
+	// else if (curscr != 0)
+	// 	touchwin(curscr);
+
+	// return _nc_freewin(win);
+	return OK;
+}
+WINDOW *derwin(WINDOW *orig, int num_lines, int num_columns, int begy, int begx)
+{
+#if 0
+	WINDOW *win = NULL;
+	int i;
+	int flags = _SUBWIN;
+
+	/* Make sure window fits inside the original one. */
+	if (begy < 0 || begx < 0 || orig == 0 || num_lines < 0
+	    || num_columns < 0)
+		return NULL;
+
+	if (begy + num_lines > orig->_maxy + 1
+	    || begx + num_columns > orig->_maxx + 1)
+		return NULL;
+
+	if (num_lines == 0)
+		num_lines = orig->_maxy + 1 - begy;
+
+	if (num_columns == 0)
+		num_columns = orig->_maxx + 1 - begx;
+
+	if (orig->_flags & _ISPAD)
+		flags |= _ISPAD;
+
+	// FIXME
+	if ((win = _nc_makenew(num_lines, num_columns, orig->_begy + begy,
+	                        orig->_begx + begx, flags)) == 0)
+	     return NULL;
+
+	win->_pary = begy;
+	win->_parx = begx;
+	WINDOW_ATTRS(win) = WINDOW_ATTRS(orig);
+	win->_nc_bkgd = orig->_nc_bkgd;
+
+	for (i = 0; i < num_lines; i++)
+		win->_line[i].text = &orig->_line[begy++].text[begx];
+
+	win->_parent = orig;
+
+	return win;
+#else
+	return NULL;
+#endif
+}
+int doupdate(void) { /* TODO */ return(0); }
+// WINDOW * dupwin (WINDOW *) {}
+/* D */ int echo(void) { SP->_echo = TRUE; return OK; }
+int endwin(void)
+{
+	if (!SP)
+		return ERR;
+
+	SP->_endwin = TRUE;
+#ifdef NCURSES_MOUSE_VERSION
+	SP->_mouse_wrap(SP);
+#endif
+	// _nc_screen_wrap();
+	// _nc_mvcur_wrap();       /* wrap up cursor addressing */
+	// return reset_shell_mode();
+	return OK;	// FIXME
+}
+// char erasechar (void) {}
+// void filter (void) {}
+// int flash(void) {}
+int flushinp(void) { /* TODO */ return 0; }
+// WINDOW *getwin (FILE *) {}
+bool has_colors (void) { return(TRUE); }
+// bool has_ic (void) {}
+// bool has_il (void) {}
+// void idcok (WINDOW *, bool) {}
+// int idlok (WINDOW *, bool) {}
+void immedok(WINDOW *win, bool flag) { win->_immed = flag; }
+/** Note: Must _not_ be called twice! */
+WINDOW *initscr(void)
+{
+	int i;
+
+	// newterm(name, stdout, stdin);
+	// def_prog_mode();
+
+	for (i = 0; i < 128; i++)
+	  acs_map[i] = (chtype) i | A_ALTCHARSET;
+#ifdef CONFIG_SERIAL_CONSOLE
+	if (curses_flags & F_ENABLE_SERIAL) {
+		ansi_clear();
+	}
+#endif
+#ifdef CONFIG_VIDEO_CONSOLE
+	if (curses_flags & F_ENABLE_CONSOLE) {
+		/* Clear the screen and kill the cursor */
+
+		video_console_clear();
+		video_console_cursor_enable(0);
+	}
+#endif
+
+	// Speaker init?
+
+	stdscr = newwin(SCREEN_Y, SCREEN_X, 0, 0);
+	// TODO: curscr, newscr?
+
+	werase(stdscr);
+
+	return stdscr;
+}
+// int intrflush (WINDOW *,bool) {}
+/* D */ bool isendwin(void) { return ((SP == NULL) ? FALSE : SP->_endwin); }
+// bool is_linetouched (WINDOW *,int) {}
+// bool is_wintouched (WINDOW *) {}
+// NCURSES_CONST char * keyname (int) {}
+int keypad (WINDOW *win, bool flag) { /* TODO */ return 0; }
+// char killchar (void) {}
+/* D */ int leaveok(WINDOW *win, bool flag) { win->_leaveok = flag; return OK; }
+// char *longname (void) {}
+// int meta (WINDOW *,bool) {}
+// int mvcur (int,int,int,int) {}
+// int mvderwin (WINDOW *, int, int) {}
+int mvprintw(int y, int x, const char *fmt, ...)
+{
+	va_list argp;
+	int code;
+
+	if (move(y, x) == ERR)
+		return ERR;
+
+	va_start(argp, fmt);
+	code = vwprintw(stdscr, fmt, argp);
+	va_end(argp);
+
+	return code;
+}
+// int mvscanw (int,int, NCURSES_CONST char *,...) {}
+// int mvwin (WINDOW *,int,int) {}
+int mvwprintw(WINDOW *win, int y, int x, const char *fmt, ...)
+{
+	va_list argp;
+	int code;
+
+	if (wmove(win, y, x) == ERR)
+		return ERR;
+
+	va_start(argp, fmt);
+	code = vwprintw(win, fmt, argp);
+	va_end(argp);
+
+	return code;
+}
+// int mvwscanw (WINDOW *,int,int, NCURSES_CONST char *,...) {}
+// int napms (int) {}
+// WINDOW *newpad (int,int) {}
+// SCREEN *newterm (NCURSES_CONST char *,FILE *,FILE *) {}
+WINDOW *newwin(int num_lines, int num_columns, int begy, int begx)
+{
+	int i;
+
+	/* Use next statically allocated window. */
+	// TODO: Error handling.
+	// TODO: WINDOWLIST?
+	WINDOW *win = &window_list[window_count++];
+
+	// bool is_pad = (flags & _ISPAD);
+
+	// TODO: Checks.
+
+	win->_cury = 0;
+	win->_curx = 0;
+	win->_maxy = num_lines - 1;
+	win->_maxx = num_columns - 1;
+	win->_begy = begy;
+	win->_begx = begx;
+	// win->_yoffset = SP->_topstolen;
+
+	win->_line = ldat_list[ldat_count++];
+
+	/* FIXME: Is this right? Should the window attributes be normal? */
+	win->_color = PAIR_NUMBER(0);
+	win->_attrs = A_NORMAL;
+
+	for (i = 0; i < num_lines; i++)
+		win->_line[i].text =
+		     (NCURSES_CH_T *)&linebuf_list[linebuf_count++];
+
+	return win;
+}
+/* D */ int nl(void) { SP->_nl = TRUE; return OK; }
+/* D */ int noecho(void) { SP->_echo = FALSE; return OK; }
+/* D */ int nonl(void) { SP->_nl = FALSE; return OK; }
+// void noqiflush (void) {}
+// int noraw (void) {}
+/* D */ int notimeout (WINDOW *win, bool f) { win->_notimeout = f; return OK; }
+// int overlay (const WINDOW*,WINDOW *) {}
+// int overwrite (const WINDOW*,WINDOW *) {}
+// int pair_content (short,short*,short*) {}
+// int pechochar (WINDOW *, const chtype) {}
+// int pnoutrefresh (WINDOW*,int,int,int,int,int,int) {}
+// int prefresh (WINDOW *,int,int,int,int,int,int) {}
+int printw(const char *fmt, ...)
+{
+	va_list argp;
+	int code;
+
+	va_start(argp, fmt);
+	code = vwprintw(stdscr, fmt, argp);
+	va_end(argp);
+
+	return code;
+}
+// int putwin (WINDOW *, FILE *) {}
+// void qiflush (void) {}
+// int raw (void) {}
+// int resetty (void) {}
+// int reset_prog_mode (void) {}
+// int reset_shell_mode (void) {}
+// int ripoffline (int, int (*)(WINDOW *, int)) {}
+// int savetty (void) {}
+// int scanw (NCURSES_CONST char *,...) {}
+// int scr_dump (const char *) {}
+// int scr_init (const char *) {}
+/* D */ int scrollok(WINDOW *win, bool flag) { win->_scroll = flag; return OK; }
+// int scr_restore (const char *) {}
+// int scr_set (const char *) {}
+// SCREEN *set_term (SCREEN *) {}
+// int slk_attroff (const chtype) {}
+// int slk_attron (const chtype) {}
+// int slk_attrset (const chtype) {}
+// attr_t slk_attr (void) {}
+// int slk_attr_set (const attr_t,short,void*) {}
+// int slk_clear (void) {}
+// int slk_color (short) {}
+// int slk_init (int) {}
+/* D */ char *slk_label(int n)
+{
+	// TODO: Needed?
+	// if (SP == NULL || SP->_slk == NULL || n < 1 || n > SP->_slk->labcnt)
+	// 	return NULL;
+	return SP->_slk->ent[n - 1].ent_text;
+}
+// int slk_noutrefresh (void) {}
+// int slk_refresh (void) {}
+// int slk_restore (void) {}
+// int slk_set (int,const char *,int) {}
+// int slk_touch (void) {}
+
+// WINDOW *subpad (WINDOW *, int, int, int, int) {}
+WINDOW *subwin(WINDOW *w, int l, int c, int y, int x)
+{
+	return derwin(w, l, c, y - w->_begy, x - w->_begx);
+}
+// int syncok (WINDOW *, bool) {}
+// chtype termattrs (void) {}
+// char *termname (void) {}
+// int typeahead (int) {}
+int ungetch(int ch) { /* TODO */ return ERR; }
+// void use_env (bool) {}
+// int vidattr (chtype) {}
+// int vidputs (chtype, int (*)(int)) {}
+int vwprintw(WINDOW *win, const char *fmt, va_list argp)
+{
+	vsprintf((char *)&sprintf_tmp, fmt, argp);
+
+	/* TODO: Error handling? */
+	return waddstr(win, (char *)&sprintf_tmp);
+}
+// int vwscanw (WINDOW *, NCURSES_CONST char *,va_list) {}
+int waddch(WINDOW *win, const chtype ch)
+{
+	int code = ERR;
+	// NCURSES_CH_T wch;
+	// SetChar2(wch, ch);
+
+	if (win->_line[win->_cury].firstchar == _NOCHANGE ||
+			win->_line[win->_cury].firstchar > win->_curx)
+		win->_line[win->_cury].firstchar = win->_curx;
+
+	win->_line[win->_cury].text[win->_curx].chars[0] =
+		((ch) & (chtype)A_CHARTEXT);
+
+	win->_line[win->_cury].text[win->_curx].attr = WINDOW_ATTRS(win);
+	win->_line[win->_cury].text[win->_curx].attr |=
+		((ch) & (chtype)A_ATTRIBUTES);
+
+	if (win->_line[win->_cury].lastchar == _NOCHANGE ||
+			win->_line[win->_cury].lastchar < win->_curx)
+		win->_line[win->_cury].lastchar = win->_curx;
+
+	win->_curx++;	// FIXME
+
+	// if (win && (waddch_nosync(win, wch) != ERR)) {
+	// 	_nc_synchook(win);
+	// 	code = OK;
+	// }
+
+	return code;
+}
+// int waddchnstr (WINDOW *,const chtype *,int) {}
+int waddnstr(WINDOW *win, const char *astr, int n)
+{
+	int code = OK;
+	const char *str = astr;
+
+	if (!str)
+		return ERR;
+
+	if (n < 0)
+		n = strlen(astr);
+
+	if (win->_line[win->_cury].firstchar == _NOCHANGE ||
+			win->_line[win->_cury].firstchar > win->_curx)
+		win->_line[win->_cury].firstchar = win->_curx;
+
+	while ((n-- > 0) && (*str != '\0')) {
+	// while (*str != '\0') {
+		win->_line[win->_cury].text[win->_curx].chars[0] = *str++;
+		win->_line[win->_cury].text[win->_curx].attr = WINDOW_ATTRS(win)
+;
+		win->_curx++;	// FIXME
+
+		// NCURSES_CH_T ch;
+		// SetChar(ch, UChar(*str++), A_NORMAL);
+		// if (_nc_waddch_nosync(win, ch) == ERR) {
+		// 	code = ERR;
+		// 	break;
+		// }
+	}
+
+	if (win->_line[win->_cury].lastchar == _NOCHANGE ||
+			win->_line[win->_cury].lastchar < win->_curx)
+		win->_line[win->_cury].lastchar = win->_curx;
+
+	return code;
+}
+int wattr_on(WINDOW *win, attr_t at, void *opts GCC_UNUSED)
+{
+	if (at & A_COLOR)
+		win->_color = PAIR_NUMBER(at);
+	// toggle_attr_on(WINDOW_ATTRS(win), at);
+	return OK;
+}
+int wattr_off(WINDOW *win, attr_t at, void *opts GCC_UNUSED)
+{
+	if (at & A_COLOR)
+		win->_color = 0;
+	// toggle_attr_off(WINDOW_ATTRS(win), at);
+	return 0;
+}
+int wbkgd (WINDOW *win, chtype ch) { /* TODO */ return 0; }
+void wbkgdset(WINDOW *win, chtype ch) { /* TODO */ }
+
+int wborder(WINDOW *win, chtype ls, chtype rs, chtype ts, chtype bs,
+		chtype tl, chtype tr, chtype bl, chtype br)
+{
+	int x, y;
+
+	if (ls == 0) ls = ACS_VLINE;
+	if (rs == 0) rs = ACS_VLINE;
+	if (ts == 0) ts = ACS_HLINE;
+	if (bs == 0) bs = ACS_HLINE;
+	if (tl == 0) tl = ACS_ULCORNER;
+	if (tr == 0) tr = ACS_URCORNER;
+	if (bl == 0) bl = ACS_LLCORNER;
+	if (br == 0) br = ACS_LRCORNER;
+
+	for(y = 0; y <= win->_maxy; y++) {
+
+		if (y == 0) {
+			 mvwaddch(win, y, 0, tl);
+
+			for(x = 1; x < win->_maxx; x++)
+				mvwaddch(win, y, x, ts);
+
+			mvwaddch(win, y, win->_maxx, tr);
+		}
+		else if (y == win->_maxy) {
+			mvwaddch(win, y, 0, bl);
+
+			for(x = 1; x < win->_maxx; x++)
+				mvwaddch(win, y, x, bs);
+
+			mvwaddch(win, y, win->_maxx, br);
+		}
+		else {
+			mvwaddch(win, y, 0, ls);
+			mvwaddch(win, y, win->_maxx, rs);
+		}
+	}
+
+	return OK;
+}
+
+// int wchgat (WINDOW *, int, attr_t, short, const void *) {}
+/* D */ int wclear(WINDOW *win)
+{
+	if (werase(win) == ERR)
+		return ERR;
+	win->_clear = TRUE;
+	return OK;
+}
+// int wclrtobot (WINDOW *) {}
+int wclrtoeol(WINDOW *win) { /* TODO */ return ERR; }
+int wcolor_set(WINDOW *win, short color_pair_number, void *opts)
+{
+	if (!opts && (color_pair_number >= 0)
+	    && (color_pair_number < COLOR_PAIRS)) {
+		SET_WINDOW_PAIR(win, color_pair_number);
+		if_EXT_COLORS(win->_color = color_pair_number);
+		return OK;
+	}
+	return ERR;
+}
+// void wcursyncup (WINDOW *) {}
+// int wdelch (WINDOW *) {}
+// int wechochar (WINDOW *, const chtype) {}
+int werase(WINDOW *win)
+{
+	int x, y;
+	for (y = 0; y <= win->_maxy; y++) {
+		for (x = 0; x <= win->_maxx; x++) {
+			win->_line[y].text[x].chars[0] = ' ';
+			win->_line[y].text[x].attr = WINDOW_ATTRS(win);
+		}
+		// Should we check instead?
+		win->_line[y].firstchar = 0;
+		win->_line[y].lastchar = win->_maxx;
+	}
+	return OK;
+}
+// int wgetnstr (WINDOW *,char *,int) {}
+int whline(WINDOW *win, chtype ch, int n)
+{
+	NCURSES_SIZE_T start, end;
+	struct ldat *line = &(win->_line[win->_cury]);
+	NCURSES_CH_T wch;
+
+	start = win->_curx;
+	end = start + n - 1;
+	if (end > win->_maxx)
+		end = win->_maxx;
+
+	CHANGED_RANGE(line, start, end);
+
+	//// TODO:
+	//// if (ch == 0)
+	////     SetChar2(wch, ACS_HLINE);
+	//// else
+	////     SetChar2(wch, ch);
+	// Ugly hack:
+	wch.chars[0] = ((ch) & (chtype)A_CHARTEXT);
+	wch.attr = ((ch) & (chtype)A_ATTRIBUTES);
+	wch = _nc_render(win, wch);
+
+	while (end >= start) {
+		line->text[end] = wch;
+		end--;
+	}
+
+	//// _nc_synchook(win);
+
+	return OK;
+}
+/* D */ chtype winch(WINDOW *win)
+{
+	//// TODO
+	// return (CharOf(win->_line[win->_cury].text[win->_curx]) |
+	//         AttrOf(win->_line[win->_cury].text[win->_curx]));
+	return OK;	// FIXME
+}
+// int winchnstr (WINDOW *, chtype *, int) {}
+// int winnstr (WINDOW *, char *, int) {}
+// int winsch (WINDOW *, chtype) {}
+// int winsdelln (WINDOW *,int) {}
+// int winsnstr (WINDOW *, const char *,int) {}
+/* D */ int wmove(WINDOW *win, int y, int x)
+{
+	if (!LEGALYX(win, y, x))
+		return ERR;
+	win->_curx = (NCURSES_SIZE_T) x;
+	win->_cury = (NCURSES_SIZE_T) y;
+	win->_flags &= ~_WRAPPED;
+	win->_flags |= _HASMOVED;
+	return OK;
+}
+
+#define SWAP_RED_BLUE(c) \
+	(((c) & 0x4400) >> 2) | ((c) & 0xAA00) | (((c) & 0x1100) << 2)
+int wnoutrefresh(WINDOW *win)
+{
+#ifdef CONFIG_SERIAL_CONSOLE
+	// FIXME.
+	int serial_is_bold = 0;
+	int serial_is_reverse = 0;
+	int serial_is_altcharset = 0;
+	int serial_cur_pair = 0;
+
+	int need_altcharset;
+	short fg, bg;
+#endif
+	int x, y;
+	chtype ch;
+
+#ifdef CONFIG_SERIAL_CONSOLE
+	ansi_end_bold();
+	ansi_end_altcharset();
+#endif
+
+	for (y = 0; y <= win->_maxy; y++) {
+
+		if (win->_line[y].firstchar == _NOCHANGE)
+			continue;
+
+		/* Position the serial cursor */
+
+#ifdef CONFIG_SERIAL_CONSOLE
+		if (curses_flags & F_ENABLE_SERIAL)
+			ansi_set_cursor(win->_begy + y, win->_begx +
+					win->_line[y].firstchar);
+#endif
+
+		for (x = win->_line[y].firstchar; x <= win->_line[y].lastchar; x++) {
+			attr_t attr = win->_line[y].text[x].attr;
+
+#ifdef CONFIG_SERIAL_CONSOLE
+			if (curses_flags & F_ENABLE_SERIAL) {
+				ch = win->_line[y].text[x].chars[0];
+
+				if (attr & A_BOLD) {
+					if (!serial_is_bold) {
+						ansi_start_bold();
+						serial_is_bold = 1;
+					}
+				} else {
+					if (serial_is_bold) {
+						ansi_end_bold();
+						serial_is_bold = 0;
+						/* work around serial.c
+						 * shortcoming:
+						 */
+						serial_is_reverse = 0;
+						serial_cur_pair = 0;
+					}
+				}
+
+				if (attr & A_REVERSE) {
+					if (!serial_is_reverse) {
+						ansi_start_reverse();
+						serial_is_reverse = 1;
+					}
+				} else {
+					if (serial_is_reverse) {
+						ansi_end_reverse();
+						serial_is_reverse = 0;
+						/* work around serial.c
+						 * shortcoming:
+						 */
+						serial_is_bold = 0;
+						serial_cur_pair = 0;
+					}
+				}
+
+				need_altcharset = 0;
+				if (attr & A_ALTCHARSET) {
+					if (serial_acs_map[ch & 0x7f]) {
+						ch = serial_acs_map[ch & 0x7f];
+						need_altcharset = 1;
+					} else
+						ch = fallback_acs_map[ch & 0x7f];
+				}
+				if (need_altcharset && !serial_is_altcharset) {
+					ansi_start_altcharset();
+					serial_is_altcharset = 1;
+				}
+				if (!need_altcharset && serial_is_altcharset) {
+					ansi_end_altcharset();
+					serial_is_altcharset = 0;
+				}
+
+				if (serial_cur_pair != PAIR_NUMBER(attr)) {
+					pair_content(PAIR_NUMBER(attr),
+						     &fg, &bg);
+					ansi_set_color(fg + 30, bg + 40);
+					serial_cur_pair = PAIR_NUMBER(attr);
+				}
+
+				putchar(ch);
+
+			}
+#endif
+#ifdef CONFIG_VIDEO_CONSOLE
+			unsigned int c =
+				((int)color_pairs[PAIR_NUMBER(attr)]) << 8;
+
+			c = SWAP_RED_BLUE(c);
+
+			if (curses_flags & F_ENABLE_CONSOLE) {
+				ch = win->_line[y].text[x].chars[0];
+
+				/* Handle some of the attributes. */
+				if (attr & A_BOLD)
+					c |= 0x0800;
+				if (attr & A_DIM)
+					c &= ~0x800;
+				if (attr & A_REVERSE) {
+					unsigned char tmp = (c >> 8) & 0xf;
+					c = (c >> 4) & 0xf00;
+					c |= tmp << 12;
+				}
+				if (attr & A_ALTCHARSET) {
+					if (console_acs_map[ch & 0x7f])
+						ch = console_acs_map[ch & 0x7f];
+					else
+						ch = fallback_acs_map[ch & 0x7f];
+				}
+
+				/*
+				 * FIXME: Somewhere along the line, the
+				 * character value is getting sign-extented.
+				 * For now grab just the 8 bit character,
+				 * but this will break wide characters!
+				 */
+				c |= (chtype) (ch & 0xff);
+				video_console_putc(win->_begy + y, win->_begx + x, c);
+			}
+#endif
+		}
+		win->_line[y].firstchar = _NOCHANGE;
+		win->_line[y].lastchar = _NOCHANGE;
+	}
+
+#ifdef CONFIG_SERIAL_CONSOLE
+	if (curses_flags & F_ENABLE_SERIAL)
+		ansi_set_cursor(win->_begy + win->_cury, win->_begx + win->_curx);
+#endif
+
+#ifdef CONFIG_VIDEO_CONSOLE
+	if (curses_flags & F_ENABLE_CONSOLE)
+		video_console_set_cursor(win->_begx + win->_curx, win->_begy + win->_cury);
+#endif
+
+	return OK;
+}
+int wprintw(WINDOW *win, const char *fmt, ...)
+{
+	va_list argp;
+	int code;
+
+	va_start(argp, fmt);
+	code = vwprintw(win, fmt, argp);
+	va_end(argp);
+
+	return code;
+}
+
+int wredrawln (WINDOW *win, int beg_line, int num_lines)
+{
+	int i;
+
+	for (i = beg_line; i < beg_line + num_lines; i++) {
+		win->_line[i].firstchar = 0;
+		win->_line[i].lastchar = win->_maxx;
+	}
+
+	return OK;
+}
+
+int wrefresh(WINDOW *win)
+{
+	int code;
+
+	// FIXME
+	return wnoutrefresh(win);
+
+	// XXX
+
+	if (win == curscr) {
+		curscr->_clear = TRUE;
+		// code = doupdate();
+	} else if ((code = wnoutrefresh(win)) == OK) {
+		if (win->_clear)
+			newscr->_clear = TRUE;
+		// code = doupdate();
+		/*
+		 * Reset the clearok() flag in case it was set for the special
+		 * case in hardscroll.c (if we don't reset it here, we'll get 2
+		 * refreshes because the flag is copied from stdscr to newscr).
+		 * Resetting the flag shouldn't do any harm, anyway.
+		 */
+		win->_clear = FALSE;
+	}
+
+	return code;
+}
+// int wscanw (WINDOW *, NCURSES_CONST char *,...) {}
+int wscrl(WINDOW *win, int n)
+{
+	int x, y;
+
+	if (!win->_scroll)
+		return ERR;
+
+	if (n == 0)
+		return OK;
+
+	for (y = 0; y <= (win->_maxy - n); y++) {
+		win->_line[y].firstchar = win->_line[y + n].firstchar;
+		win->_line[y].lastchar = win->_line[y + n].lastchar;
+		for (x = 0; x <= win->_maxx; x++) {
+			if ((win->_line[y].text[x].chars[0] != win->_line[y + n].text[x].chars[0]) ||
+					(win->_line[y].text[x].attr != win->_line[y + n].text[x].attr)) {
+				if (win->_line[y].firstchar == _NOCHANGE)
+					win->_line[y].firstchar = x;
+
+				win->_line[y].lastchar = x;
+
+				win->_line[y].text[x].chars[0] = win->_line[y + n].text[x].chars[0];
+				win->_line[y].text[x].attr = win->_line[y + n].text[x].attr;
+			}
+		}
+	}
+
+	for (y = (win->_maxy+1 - n); y <= win->_maxy; y++) {
+		for (x = 0; x <= win->_maxx; x++) {
+			if ((win->_line[y].text[x].chars[0] != ' ') ||
+					(win->_line[y].text[x].attr != A_NORMAL)) {
+				if (win->_line[y].firstchar == _NOCHANGE)
+					win->_line[y].firstchar = x;
+
+				win->_line[y].lastchar = x;
+
+				win->_line[y].text[x].chars[0] = ' ';
+				win->_line[y].text[x].attr = A_NORMAL;
+			}
+		}
+	}
+
+	// _nc_scroll_window(win, n, win->_regtop, win->_regbottom, win->_nc_bkgd);
+	// _nc_synchook(win);
+
+	return OK;
+}
+int wsetscrreg(WINDOW *win, int top, int bottom)
+{
+	if (top >= 0 && top <= win->_maxy && bottom >= 0 &&
+	    bottom <= win->_maxy && bottom > top) {
+		win->_regtop = (NCURSES_SIZE_T) top;
+		win->_regbottom = (NCURSES_SIZE_T) bottom;
+		return OK;
+	}
+	return ERR;
+}
+// void wsyncdown (WINDOW *) {}
+// void wsyncup (WINDOW *) {}
+/* D */ void wtimeout(WINDOW *win, int _delay) { win->_delay = _delay; }
+/* D */ int wtouchln(WINDOW *win, int y, int n, int changed)
+{
+	int i;
+
+	// if ((n < 0) || (y < 0) || (y > win->_maxy))
+	//     return ERR;
+
+	for (i = y; i < y + n; i++) {
+		if (i > win->_maxy)
+			break;
+		win->_line[i].firstchar = changed ? 0 : _NOCHANGE;
+		win->_line[i].lastchar = changed ? win->_maxx : _NOCHANGE;
+	}
+	return OK;
+}
+// int wvline (WINDOW *,chtype,int) {}
+// int tigetflag (NCURSES_CONST char *) {}
+// int tigetnum (NCURSES_CONST char *) {}
+// char *tigetstr (NCURSES_CONST char *) {}
+// int putp (const char *) {}
+// #if NCURSES_TPARM_VARARGS
+// char *tparm (NCURSES_CONST char *, ...) {}
+// #else
+// char *tparm (NCURSES_CONST char *, long,long,long,long,long,long,long,long,long) {}
+// char *tparm_varargs (NCURSES_CONST char *, ...) {}
+// #endif
-- 
1.7.10.4


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH 13/20] app: curses: add pdcurses
  2013-03-06  9:29 ` [PATCH 01/20] Makefile: x_flags prepare for apps support Jean-Christophe PLAGNIOL-VILLARD
                     ` (10 preceding siblings ...)
  2013-03-06  9:29   ` [PATCH 12/20] app: add tinycurses support Jean-Christophe PLAGNIOL-VILLARD
@ 2013-03-06  9:29   ` Jean-Christophe PLAGNIOL-VILLARD
  2013-03-06  9:29   ` [PATCH 14/20] app: add test curses Jean-Christophe PLAGNIOL-VILLARD
                     ` (6 subsequent siblings)
  18 siblings, 0 replies; 31+ messages in thread
From: Jean-Christophe PLAGNIOL-VILLARD @ 2013-03-06  9:29 UTC (permalink / raw)
  To: barebox

backend inspided by coreboot core but with ansi support

Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
---
 apps/lib/curses/Kconfig                      |    7 +
 apps/lib/curses/Makefile                     |    1 +
 apps/lib/curses/Makefile.include             |    1 +
 apps/lib/curses/pdcurses/Makefile            |   89 ++
 apps/lib/curses/pdcurses/Makefile.include    |    1 +
 apps/lib/curses/pdcurses/backend/Makefile    |    6 +
 apps/lib/curses/pdcurses/backend/barebox.h   |   21 +
 apps/lib/curses/pdcurses/backend/config.h    |  136 +++
 apps/lib/curses/pdcurses/backend/pdcdisp.c   |  107 ++
 apps/lib/curses/pdcurses/backend/pdcgetsc.c  |   47 +
 apps/lib/curses/pdcurses/backend/pdckbd.c    |  161 +++
 apps/lib/curses/pdcurses/backend/pdcscrn.c   |  162 +++
 apps/lib/curses/pdcurses/backend/pdcsetsc.c  |   35 +
 apps/lib/curses/pdcurses/backend/pdcutil.c   |   26 +
 apps/lib/curses/pdcurses/include/curses.h    | 1378 ++++++++++++++++++++++++++
 apps/lib/curses/pdcurses/include/panel.h     |   58 ++
 apps/lib/curses/pdcurses/pdcurses/Makefile   |   39 +
 apps/lib/curses/pdcurses/pdcurses/README     |   25 +
 apps/lib/curses/pdcurses/pdcurses/addch.c    |  408 ++++++++
 apps/lib/curses/pdcurses/pdcurses/addchstr.c |  242 +++++
 apps/lib/curses/pdcurses/pdcurses/addstr.c   |  237 +++++
 apps/lib/curses/pdcurses/pdcurses/attr.c     |  349 +++++++
 apps/lib/curses/pdcurses/pdcurses/beep.c     |   65 ++
 apps/lib/curses/pdcurses/pdcurses/bkgd.c     |  220 ++++
 apps/lib/curses/pdcurses/pdcurses/border.c   |  408 ++++++++
 apps/lib/curses/pdcurses/pdcurses/clear.c    |  154 +++
 apps/lib/curses/pdcurses/pdcurses/color.c    |  295 ++++++
 apps/lib/curses/pdcurses/pdcurses/curspriv.h |  146 +++
 apps/lib/curses/pdcurses/pdcurses/debug.c    |   81 ++
 apps/lib/curses/pdcurses/pdcurses/delch.c    |   93 ++
 apps/lib/curses/pdcurses/pdcurses/deleteln.c |  208 ++++
 apps/lib/curses/pdcurses/pdcurses/deprec.c   |   29 +
 apps/lib/curses/pdcurses/pdcurses/getch.c    |  410 ++++++++
 apps/lib/curses/pdcurses/pdcurses/getstr.c   |  471 +++++++++
 apps/lib/curses/pdcurses/pdcurses/getyx.c    |  143 +++
 apps/lib/curses/pdcurses/pdcurses/inch.c     |  125 +++
 apps/lib/curses/pdcurses/pdcurses/inchstr.c  |  211 ++++
 apps/lib/curses/pdcurses/pdcurses/initscr.c  |  339 +++++++
 apps/lib/curses/pdcurses/pdcurses/inopts.c   |  321 ++++++
 apps/lib/curses/pdcurses/pdcurses/insch.c    |  268 +++++
 apps/lib/curses/pdcurses/pdcurses/insstr.c   |  261 +++++
 apps/lib/curses/pdcurses/pdcurses/instr.c    |  243 +++++
 apps/lib/curses/pdcurses/pdcurses/kernel.c   |  256 +++++
 apps/lib/curses/pdcurses/pdcurses/keyname.c  |  125 +++
 apps/lib/curses/pdcurses/pdcurses/mouse.c    |  429 ++++++++
 apps/lib/curses/pdcurses/pdcurses/move.c     |   54 +
 apps/lib/curses/pdcurses/pdcurses/outopts.c  |  156 +++
 apps/lib/curses/pdcurses/pdcurses/overlay.c  |  256 +++++
 apps/lib/curses/pdcurses/pdcurses/pad.c      |  259 +++++
 apps/lib/curses/pdcurses/pdcurses/panel.c    |  630 ++++++++++++
 apps/lib/curses/pdcurses/pdcurses/printw.c   |  123 +++
 apps/lib/curses/pdcurses/pdcurses/refresh.c  |  276 ++++++
 apps/lib/curses/pdcurses/pdcurses/scanw.c    |  575 +++++++++++
 apps/lib/curses/pdcurses/pdcurses/scr_dump.c |  210 ++++
 apps/lib/curses/pdcurses/pdcurses/scroll.c   |   98 ++
 apps/lib/curses/pdcurses/pdcurses/slk.c      |  643 ++++++++++++
 apps/lib/curses/pdcurses/pdcurses/term.h     |   57 ++
 apps/lib/curses/pdcurses/pdcurses/termattr.c |  176 ++++
 apps/lib/curses/pdcurses/pdcurses/terminfo.c |  215 ++++
 apps/lib/curses/pdcurses/pdcurses/touch.c    |  160 +++
 apps/lib/curses/pdcurses/pdcurses/util.c     |  309 ++++++
 apps/lib/curses/pdcurses/pdcurses/window.c   |  562 +++++++++++
 62 files changed, 13596 insertions(+)
 create mode 100644 apps/lib/curses/pdcurses/Makefile
 create mode 100644 apps/lib/curses/pdcurses/Makefile.include
 create mode 100644 apps/lib/curses/pdcurses/backend/Makefile
 create mode 100644 apps/lib/curses/pdcurses/backend/barebox.h
 create mode 100644 apps/lib/curses/pdcurses/backend/config.h
 create mode 100644 apps/lib/curses/pdcurses/backend/pdcdisp.c
 create mode 100644 apps/lib/curses/pdcurses/backend/pdcgetsc.c
 create mode 100644 apps/lib/curses/pdcurses/backend/pdckbd.c
 create mode 100644 apps/lib/curses/pdcurses/backend/pdcscrn.c
 create mode 100644 apps/lib/curses/pdcurses/backend/pdcsetsc.c
 create mode 100644 apps/lib/curses/pdcurses/backend/pdcutil.c
 create mode 100644 apps/lib/curses/pdcurses/include/curses.h
 create mode 100644 apps/lib/curses/pdcurses/include/panel.h
 create mode 100644 apps/lib/curses/pdcurses/pdcurses/Makefile
 create mode 100644 apps/lib/curses/pdcurses/pdcurses/README
 create mode 100644 apps/lib/curses/pdcurses/pdcurses/addch.c
 create mode 100644 apps/lib/curses/pdcurses/pdcurses/addchstr.c
 create mode 100644 apps/lib/curses/pdcurses/pdcurses/addstr.c
 create mode 100644 apps/lib/curses/pdcurses/pdcurses/attr.c
 create mode 100644 apps/lib/curses/pdcurses/pdcurses/beep.c
 create mode 100644 apps/lib/curses/pdcurses/pdcurses/bkgd.c
 create mode 100644 apps/lib/curses/pdcurses/pdcurses/border.c
 create mode 100644 apps/lib/curses/pdcurses/pdcurses/clear.c
 create mode 100644 apps/lib/curses/pdcurses/pdcurses/color.c
 create mode 100644 apps/lib/curses/pdcurses/pdcurses/curspriv.h
 create mode 100644 apps/lib/curses/pdcurses/pdcurses/debug.c
 create mode 100644 apps/lib/curses/pdcurses/pdcurses/delch.c
 create mode 100644 apps/lib/curses/pdcurses/pdcurses/deleteln.c
 create mode 100644 apps/lib/curses/pdcurses/pdcurses/deprec.c
 create mode 100644 apps/lib/curses/pdcurses/pdcurses/getch.c
 create mode 100644 apps/lib/curses/pdcurses/pdcurses/getstr.c
 create mode 100644 apps/lib/curses/pdcurses/pdcurses/getyx.c
 create mode 100644 apps/lib/curses/pdcurses/pdcurses/inch.c
 create mode 100644 apps/lib/curses/pdcurses/pdcurses/inchstr.c
 create mode 100644 apps/lib/curses/pdcurses/pdcurses/initscr.c
 create mode 100644 apps/lib/curses/pdcurses/pdcurses/inopts.c
 create mode 100644 apps/lib/curses/pdcurses/pdcurses/insch.c
 create mode 100644 apps/lib/curses/pdcurses/pdcurses/insstr.c
 create mode 100644 apps/lib/curses/pdcurses/pdcurses/instr.c
 create mode 100644 apps/lib/curses/pdcurses/pdcurses/kernel.c
 create mode 100644 apps/lib/curses/pdcurses/pdcurses/keyname.c
 create mode 100644 apps/lib/curses/pdcurses/pdcurses/mouse.c
 create mode 100644 apps/lib/curses/pdcurses/pdcurses/move.c
 create mode 100644 apps/lib/curses/pdcurses/pdcurses/outopts.c
 create mode 100644 apps/lib/curses/pdcurses/pdcurses/overlay.c
 create mode 100644 apps/lib/curses/pdcurses/pdcurses/pad.c
 create mode 100644 apps/lib/curses/pdcurses/pdcurses/panel.c
 create mode 100644 apps/lib/curses/pdcurses/pdcurses/printw.c
 create mode 100644 apps/lib/curses/pdcurses/pdcurses/refresh.c
 create mode 100644 apps/lib/curses/pdcurses/pdcurses/scanw.c
 create mode 100644 apps/lib/curses/pdcurses/pdcurses/scr_dump.c
 create mode 100644 apps/lib/curses/pdcurses/pdcurses/scroll.c
 create mode 100644 apps/lib/curses/pdcurses/pdcurses/slk.c
 create mode 100644 apps/lib/curses/pdcurses/pdcurses/term.h
 create mode 100644 apps/lib/curses/pdcurses/pdcurses/termattr.c
 create mode 100644 apps/lib/curses/pdcurses/pdcurses/terminfo.c
 create mode 100644 apps/lib/curses/pdcurses/pdcurses/touch.c
 create mode 100644 apps/lib/curses/pdcurses/pdcurses/util.c
 create mode 100644 apps/lib/curses/pdcurses/pdcurses/window.c

diff --git a/apps/lib/curses/Kconfig b/apps/lib/curses/Kconfig
index c6bc573..7852afb 100644
--- a/apps/lib/curses/Kconfig
+++ b/apps/lib/curses/Kconfig
@@ -6,9 +6,16 @@ if APP_LIB_CURSES
 choice
 	prompt "curses implementation"
 
+config APP_LIB_PDCURSES
+	bool "pdcurses"
+
 config APP_LIB_TINYCURSES
 	bool "tiny"
 
 endchoice
 
+config APP_LIB_PANEL
+	bool "panel"
+	depends on APP_LIB_PDCURSES
+
 endif
diff --git a/apps/lib/curses/Makefile b/apps/lib/curses/Makefile
index aeebdd5..ca094a0 100644
--- a/apps/lib/curses/Makefile
+++ b/apps/lib/curses/Makefile
@@ -1 +1,2 @@
 obj-$(CONFIG_APP_LIB_TINYCURSES) += tinycurses/
+obj-$(CONFIG_APP_LIB_PDCURSES) += pdcurses/
diff --git a/apps/lib/curses/Makefile.include b/apps/lib/curses/Makefile.include
index 8cf9d52..a694fe1 100644
--- a/apps/lib/curses/Makefile.include
+++ b/apps/lib/curses/Makefile.include
@@ -1,3 +1,4 @@
+inc-$(CONFIG_APP_LIB_PDCURSES) += $(srctree)/apps/lib/curses/pdcurses/Makefile.include
 inc-$(CONFIG_APP_LIB_TINYCURSES) += $(srctree)/apps/lib/curses/tinycurses/Makefile.include
 
 include $(inc-y)
diff --git a/apps/lib/curses/pdcurses/Makefile b/apps/lib/curses/pdcurses/Makefile
new file mode 100644
index 0000000..3707947
--- /dev/null
+++ b/apps/lib/curses/pdcurses/Makefile
@@ -0,0 +1,89 @@
+#ifeq (y,y)
+#INCLUDES += -D_LP64=0 -Icurses/PDCurses-3.4 -Icurses/pdcurses-backend -Icurses/menu -Icurses/form
+#endif
+
+
+obj-y += pdcurses/
+obj-y += backend/
+
+includes-y += pdcurses-backend/nc_alloc.h
+includes-y += pdcurses-backend/ncurses_cfg.h
+includes-y += PDCurses-3.4/curses.h
+includes-y += PDCurses-3.4/term.h
+includes-y += PDCurses-3.4/panel.h
+includes-y += menu/eti.h
+includes-y += menu/menu.h
+includes-y += menu/mf_common.h
+includes-y += form/form.h
+
+libpanel-y += PDCurses-3.4/pdcurses/panel.o
+
+libmenu-y += menu/m_req_name.o
+libmenu-y += menu/m_item_nam.o
+libmenu-y += menu/m_pad.o
+libmenu-y += menu/m_cursor.o
+libmenu-y += menu/m_item_new.o
+libmenu-y += menu/m_attribs.o
+libmenu-y += menu/m_item_opt.o
+libmenu-y += menu/m_format.o
+libmenu-y += menu/m_post.o
+libmenu-y += menu/m_userptr.o
+libmenu-y += menu/m_item_cur.o
+libmenu-y += menu/m_driver.o
+libmenu-y += menu/m_sub.o
+libmenu-y += menu/m_win.o
+libmenu-y += menu/m_global.o
+libmenu-y += menu/m_item_vis.o
+libmenu-y += menu/m_new.o
+libmenu-y += menu/m_scale.o
+libmenu-y += menu/m_spacing.o
+libmenu-y += menu/m_opts.o
+libmenu-y += menu/m_pattern.o
+libmenu-y += menu/m_item_val.o
+libmenu-y += menu/m_hook.o
+libmenu-y += menu/m_item_use.o
+libmenu-y += menu/m_items.o
+libmenu-y += menu/m_item_top.o
+libform-y += form/frm_page.o
+libform-y += form/frm_opts.o
+libform-y += form/frm_def.o
+libform-y += form/frm_req_name.o
+libform-y += form/fty_alpha.o
+libform-y += form/frm_driver.o
+libform-y += form/fld_user.o
+libform-y += form/frm_win.o
+libform-y += form/fld_newftyp.o
+#libform-y += form/fty_regex.o
+libform-y += form/fld_stat.o
+libform-y += form/fld_pad.o
+libform-y += form/fld_current.o
+libform-y += form/frm_post.o
+#libform-y += form/f_trace.o
+libform-y += form/fty_generic.o
+libform-y += form/fld_page.o
+libform-y += form/frm_hook.o
+libform-y += form/frm_scale.o
+libform-y += form/fty_int.o
+libform-y += form/fty_alnum.o
+libform-y += form/frm_cursor.o
+#libform-y += form/fty_ipv4.o
+libform-y += form/fld_link.o
+libform-y += form/fld_arg.o
+libform-y += form/fld_move.o
+libform-y += form/fld_def.o
+libform-y += form/fld_type.o
+libform-y += form/fld_max.o
+libform-y += form/fld_ftlink.o
+libform-y += form/fld_ftchoice.o
+libform-y += form/fld_info.o
+libform-y += form/frm_user.o
+#libform-y += form/fty_num.o
+libform-y += form/frm_sub.o
+libform-y += form/fty_enum.o
+libform-y += form/frm_data.o
+libform-y += form/fld_opts.o
+libform-y += form/fld_attr.o
+libform-y += form/fld_dup.o
+libform-y += form/fld_just.o
+
+app-y += $(curses-y)
diff --git a/apps/lib/curses/pdcurses/Makefile.include b/apps/lib/curses/pdcurses/Makefile.include
new file mode 100644
index 0000000..822f12f
--- /dev/null
+++ b/apps/lib/curses/pdcurses/Makefile.include
@@ -0,0 +1 @@
+APP_CPPFLAGS-y += -I$(srctree)/apps/lib/curses/pdcurses/include/ -D_LP64=0
diff --git a/apps/lib/curses/pdcurses/backend/Makefile b/apps/lib/curses/pdcurses/backend/Makefile
new file mode 100644
index 0000000..cf6eb3f
--- /dev/null
+++ b/apps/lib/curses/pdcurses/backend/Makefile
@@ -0,0 +1,6 @@
+app-y += pdcdisp.o
+app-y += pdcgetsc.o
+app-y += pdckbd.o
+app-y += pdcscrn.o
+app-y += pdcsetsc.o
+app-y += pdcutil.o
diff --git a/apps/lib/curses/pdcurses/backend/barebox.h b/apps/lib/curses/pdcurses/backend/barebox.h
new file mode 100644
index 0000000..2a16c7e
--- /dev/null
+++ b/apps/lib/curses/pdcurses/backend/barebox.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2013 Jean-Christophe PLAGNIOL-VILLARD <plagnio@jcrosoft.com>
+ *
+ * Under BSD
+ */
+
+#include <curses.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <string.h>
+#include "../pdcurses/curspriv.h"
+
+extern unsigned char *pdc_atrtab;
+extern short curstoreal[16], realtocurs[16];
+
+#ifdef DEBUG
+#define debug(fmt, arg...) printf(fmt, ## arg)
+#else
+#define debug(fmt, arg...)
+#endif
diff --git a/apps/lib/curses/pdcurses/backend/config.h b/apps/lib/curses/pdcurses/backend/config.h
new file mode 100644
index 0000000..e08c710
--- /dev/null
+++ b/apps/lib/curses/pdcurses/backend/config.h
@@ -0,0 +1,136 @@
+/* config.h.  Generated from config.h.in by configure.  */
+/* config.h.in.  Generated from configure.ac by autoheader.  */
+
+#define PDC_RGB
+
+/* Define if you have the <DECkeySym.h> header file */
+/* #undef HAVE_DECKEYSYM_H */
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+/* #undef HAVE_DLFCN_H */
+
+/* Define to 1 if you have the <dl.h> header file. */
+/* #undef HAVE_DL_H */
+
+/* Define to 1 if you have the <fcntl.h> header file. */
+/* #undef HAVE_FCNTL_H */
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+/* #undef HAVE_INTTYPES_H */
+
+/* Define to 1 if you have the <memory.h> header file. */
+/* #undef HAVE_MEMORY_H */
+
+/* Define to 1 if you have the `poll' function. */
+/* #undef HAVE_POLL */
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+/* #undef HAVE_STRINGS_H */
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define if you have the <Sunkeysym.h> header file */
+/* #undef HAVE_SUNKEYSYM_H */
+
+/* Define to 1 if you have the <sys/select.h> header file. */
+/* #undef HAVE_SYS_SELECT_H */
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+/* #undef HAVE_SYS_STAT_H */
+
+/* Define to 1 if you have the <sys/time.h> header file. */
+/* #undef HAVE_SYS_TIME_H */
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define to 1 if you have the `usleep' function. */
+#define HAVE_USLEEP 1
+
+/* Define to 1 if you have the `vsnprintf' function. */
+#define HAVE_VSNPRINTF 1
+
+/* Define to 1 if you have the `vsscanf' function. */
+/* #undef HAVE_VSSCANF */
+
+/* Define if you have this defined in <keysym.h> */
+/* #undef HAVE_XK_KP_BEGIN */
+
+/* Define if you have this defined in <keysym.h> */
+/* #undef HAVE_XK_KP_DELETE */
+
+/* Define if you have this defined in <keysym.h> */
+/* #undef HAVE_XK_KP_DOWN */
+
+/* Define if you have this defined in <keysym.h> */
+/* #undef HAVE_XK_KP_END */
+
+/* Define if you have this defined in <keysym.h> */
+/* #undef HAVE_XK_KP_HOME */
+
+/* Define if you have this defined in <keysym.h> */
+/* #undef HAVE_XK_KP_INSERT */
+
+/* Define if you have this defined in <keysym.h> */
+/* #undef HAVE_XK_KP_LEFT */
+
+/* Define if you have this defined in <keysym.h> */
+/* #undef HAVE_XK_KP_NEXT */
+
+/* Define if you have this defined in <keysym.h> */
+/* #undef HAVE_XK_KP_PRIOR */
+
+/* Define if you have this defined in <keysym.h> */
+/* #undef HAVE_XK_KP_RIGHT */
+
+/* Define if you have this defined in <keysym.h> */
+/* #undef HAVE_XK_KP_UP */
+
+/* Define if you have the <xpm.h> header file */
+/* #undef HAVE_XPM_H */
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT "barebox@@lists.infradead.org"
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "PDCurses"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "PDCurses 3.4"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "PDCurses"
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "3.4"
+
+/* Define as the system defined limit for number of signals */
+#define PDC_MAX_SIGNALS NSIG
+
+/* Define as the return type of signal handlers (`int' or `void'). */
+#define RETSIGTYPE void
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
+//#define TIME_WITH_SYS_TIME 1
+
+/* Define if you want to use neXtaw library */
+/* #undef USE_NEXTAW */
+
+/* Define if you want to use Xaw3d library */
+/* #undef USE_XAW3D */
+
+/* Define XPointer is typedefed in X11/Xlib.h */
+/* #undef XPOINTER_TYPEDEFED */
diff --git a/apps/lib/curses/pdcurses/backend/pdcdisp.c b/apps/lib/curses/pdcurses/backend/pdcdisp.c
new file mode 100644
index 0000000..9d629d0
--- /dev/null
+++ b/apps/lib/curses/pdcurses/backend/pdcdisp.c
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2013 Jean-Christophe PLAGNIOL-VILLARD <plagnio@jcrosoft.com>
+ *
+ * Under BSD
+ */
+
+#include "barebox.h"
+#include <utils/ansi.h>
+
+chtype acs_map[128] =
+	{
+	' ',	' ',	' ',	' ',	' ',	' ',	' ',	' ',
+	' ',	' ',	' ',	' ',	' ',	' ',	' ',	' ',
+	' ',	' ',	' ',	' ',	' ',	' ',	' ',	' ',
+	' ',	' ',	' ',	' ',	' ',	' ',	' ',	' ',
+	' ',	' ',	' ',	' ',	' ',	' ',	' ',	' ',
+	' ',	' ',	' ',	'>',	'<',	'^',	'v',	' ',
+	'#',	' ',	' ',	' ',	' ',	' ',	' ',	' ',
+	' ',	' ',	' ',	' ',	' ',	' ',	' ',	' ',
+	' ',	' ',	' ',	' ',	' ',	' ',	' ',	' ',
+	' ',	' ',	' ',	' ',	' ',	' ',	' ',	' ',
+	' ',	' ',	' ',	' ',	' ',	' ',	' ',	' ',
+	' ',	' ',	' ',	' ',	' ',	' ',	' ',	' ',
+	'+',	':',	' ',	' ',	' ',	' ',	'\\',   '#',
+	'#',	'#',	'+',	'+',	'+',	'+',	'+',	'~',
+	'-',	'-',	'-',	'_',	'+',	'+',	'+',	'+',
+	'|',	'<',	'>',	'*',	'!',	'f',	'o',	' ',
+	};
+
+/* position hardware cursor at (y, x) */
+void PDC_gotoyx(int row, int col)
+{
+	PDC_LOG(("PDC_gotoyx() - called: row %d col %d\n", row, col));
+
+	ansi_set_cursor(row, col);
+}
+
+struct ansi_set {
+	bool is_bold;
+	bool is_blink;
+	short cur_pair;
+};
+
+static void set_attr(chtype attr, struct ansi_set *s)
+{
+	short fg;
+	short bg;
+	short cur_pair = PAIR_NUMBER(attr);
+	bool is_bold = attr & A_BOLD;
+	bool is_reverse = FALSE;
+	bool is_blink = attr & A_BLINK;
+
+	if (s->cur_pair != cur_pair) {
+		PDC_pair_content(cur_pair, &fg, &bg );
+		ansi_set_color(fg + 30, bg + 40);
+		s->cur_pair = cur_pair;
+	}
+
+	/* Reverse flag = highlighted selection XOR A_REVERSE set */
+	is_reverse ^= !!(attr & A_REVERSE);
+
+	if (s->is_bold != is_bold) {
+		ansi_bold(is_bold);
+		s->is_bold = is_bold;
+	}
+
+	if (s->is_blink != is_blink) {
+		ansi_blink(is_blink);
+		s->is_blink = is_blink;
+	}
+
+	/* always set it ansi issue with bold */
+	ansi_reverse(is_reverse);
+}
+/* update the given physical line to look like the corresponding line in
+   curscr */
+
+void PDC_transform_line(int lineno, int x, int len, const chtype *srcp)
+{
+	int j, ch;
+	chtype attr = srcp[0] & A_ATTRIBUTES;
+	chtype prev_attr = attr;
+	struct ansi_set s;
+
+	/* ensure different */
+	s.cur_pair = PAIR_NUMBER(attr) + 1;
+
+	PDC_LOG(("PDC_transform_line() - called: line %d, len %d\n", lineno, len));
+
+	ansi_set_cursor(lineno, x);
+	set_attr(attr, &s);
+
+	for (j = 0; j < len; j++) {
+		ch = srcp[j];
+		attr = ch & A_ATTRIBUTES;
+
+		if (attr != prev_attr) {
+			set_attr(attr, &s);
+			prev_attr = attr;
+		}
+
+		if (ch & A_ALTCHARSET && !(ch & 0xff80))
+			ch = acs_map[ch & 0x7f];
+
+		putchar(ch & A_CHARTEXT);
+	}
+}
diff --git a/apps/lib/curses/pdcurses/backend/pdcgetsc.c b/apps/lib/curses/pdcurses/backend/pdcgetsc.c
new file mode 100644
index 0000000..e09a268
--- /dev/null
+++ b/apps/lib/curses/pdcurses/backend/pdcgetsc.c
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2013 Jean-Christophe PLAGNIOL-VILLARD <plagnio@jcrosoft.com>
+ *
+ * Under BSD
+ */
+
+#include "barebox.h"
+#include <utils/termcap.h>
+
+/* return width of screen/viewport */
+int PDC_get_columns(void)
+{
+	int cols = 80;
+	int rows;
+
+	PDC_LOG(("PDC_get_columns() - called\n"));
+
+	term_get_size(&rows, &cols);
+
+	PDC_LOG(("PDC_get_columns() - returned: cols %d\n", cols));
+
+	return cols;
+}
+
+/* get the cursor size/shape */
+int PDC_get_cursor_mode(void)
+{
+	PDC_LOG(("PDC_get_cursor_mode() - called\n"));
+
+	/* only have one cursor type */
+	return SP->visibility;
+}
+
+/* return number of screen rows */
+int PDC_get_rows(void)
+{
+	int cols;
+	int rows = 25;
+
+	PDC_LOG(("PDC_get_rows() - called\n"));
+
+	term_get_size(&rows, &cols);
+
+	PDC_LOG(("PDC_get_rows() - returned: rows %d\n", rows));
+
+	return rows;
+}
diff --git a/apps/lib/curses/pdcurses/backend/pdckbd.c b/apps/lib/curses/pdcurses/backend/pdckbd.c
new file mode 100644
index 0000000..b9030a2
--- /dev/null
+++ b/apps/lib/curses/pdcurses/backend/pdckbd.c
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2013 Jean-Christophe PLAGNIOL-VILLARD <plagnio@jcrosoft.com>
+ *
+ * Under BSD
+ */
+
+#include "barebox.h"
+#include <utils/getchar.h>
+
+unsigned long pdc_key_modifiers = 0L;
+
+static struct {
+	const char *seq;
+	int val;
+} escape_codes[] = {
+	{ "OA", KEY_UP },
+	{ "OB", KEY_DOWN },
+	{ "OC", KEY_RIGHT },
+	{ "OD", KEY_LEFT },
+	{ "[A", KEY_UP },
+	{ "[B", KEY_DOWN },
+	{ "[C", KEY_RIGHT },
+	{ "[D", KEY_LEFT },
+	{ "[F", KEY_END },
+	{ "[H", KEY_HOME },
+	{ "[1~", KEY_HOME },
+	{ "[2~", KEY_IC },
+	{ "[3~", KEY_DC },
+	{ "[5~", KEY_PPAGE },
+	{ "[6~", KEY_NPAGE },
+	{ "OP", KEY_F(1) },
+	{ "OQ", KEY_F(2) },
+	{ "OR", KEY_F(3) },
+	{ "OS", KEY_F(4) },
+	{ "[15~", KEY_F(5) },
+	{ "[17~", KEY_F(6) },
+	{ "[18~", KEY_F(7) },
+	{ "[19~", KEY_F(8) },
+	{ "[20~", KEY_F(9) },
+	{ "[21~", KEY_F(10) },
+	{ "[23~", KEY_F(11) },
+	{ "[24~", KEY_F(12) },
+	{ NULL },
+};
+
+#define ARRAY_SIZE(arr)                (sizeof(arr) / sizeof((arr)[0]))
+
+static int read_escape(void)
+{
+	char buf[6];
+	int i = 0;
+
+	buf[i++] = getchar_timeout(10);
+	buf[i++] = getchar_timeout(10);
+
+	if (isdigit(buf[1])) {
+		for (; i < ARRAY_SIZE(buf); i++) {
+			buf[i] = getchar_timeout(10);
+			if (buf[i] < 0)
+				break;
+		}
+
+		if (i == ARRAY_SIZE(buf))
+			goto err;
+	}
+
+	buf[i] = 0;
+	debug("buf = ");
+	for (i = 0; i < ARRAY_SIZE(buf); i++)
+		debug("%02x", buf[i]);
+	debug("\n");
+
+	for (i = 0; i < ARRAY_SIZE(escape_codes); i++) {
+		if (!strcmp(buf, escape_codes[i].seq)) {
+			debug("found 0x%x\n", escape_codes[i].val);
+			return escape_codes[i].val;
+		}
+	}
+
+err:
+	debug("buf = ");
+	for (i = 0; i < ARRAY_SIZE(buf); i++)
+		debug("%02x ", buf[i]);
+	debug("\n");
+
+	return 0;
+}
+
+static int readkey(void)
+{
+	int ch = getchar();
+
+	debug("buf = %x\n", ch);
+	switch(ch) {
+	case '\r':
+		return KEY_ENTER;
+	case '\n':
+		return KEY_ENTER;
+	case 8:
+		return KEY_BACKSPACE;
+	case 27:
+		return read_escape();
+
+	default:
+		return ch;
+	}
+}
+
+void PDC_set_keyboard_binary(bool on)
+{
+	PDC_LOG(("PDC_set_keyboard_binary() - called\n"));
+}
+
+/* check if a key event is waiting */
+
+bool PDC_check_key(void)
+{
+	if (tstc())
+		return TRUE;
+
+	return FALSE;
+}
+
+/* return the next available key event */
+
+int PDC_get_key(void)
+{
+	int c = 0;
+
+	if (tstc())
+		c = readkey();
+
+	if (c == 0)
+		c = ERR;
+
+	SP->key_code = c >= KEY_MIN;
+
+	debug("key buf = 0x%x\n", c);
+
+	return c;
+}
+
+/* discard any pending keyboard input -- this is the core
+   routine for flushinp() */
+
+void PDC_flushinp(void)
+{
+	PDC_LOG(("PDC_flushinp() - called\n"));
+
+	while (PDC_check_key()) PDC_get_key();
+}
+
+int PDC_mouse_set(void)
+{
+	return ERR;
+}
+
+int PDC_modifiers_set(void)
+{
+	return OK;
+}
diff --git a/apps/lib/curses/pdcurses/backend/pdcscrn.c b/apps/lib/curses/pdcurses/backend/pdcscrn.c
new file mode 100644
index 0000000..904d573
--- /dev/null
+++ b/apps/lib/curses/pdcurses/backend/pdcscrn.c
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2013 Jean-Christophe PLAGNIOL-VILLARD <plagnio@jcrosoft.com>
+ *
+ * Under BSD
+ */
+
+#include <utils/termcap.h>
+#include <utils/ansi.h>
+#include "barebox.h"
+
+#ifdef CHTYPE_LONG
+# define PDC_OFFSET 32
+#else
+# define PDC_OFFSET  8
+#endif
+
+/* COLOR_PAIR to attribute encoding table. */
+
+unsigned char *pdc_atrtab = (unsigned char *)NULL;
+
+short curstoreal[16], realtocurs[16] =
+{
+    COLOR_BLACK, COLOR_BLUE, COLOR_GREEN, COLOR_CYAN, COLOR_RED,
+    COLOR_MAGENTA, COLOR_YELLOW, COLOR_WHITE, COLOR_BLACK + 8,
+    COLOR_BLUE + 8, COLOR_GREEN + 8, COLOR_CYAN + 8, COLOR_RED + 8,
+    COLOR_MAGENTA + 8, COLOR_YELLOW + 8, COLOR_WHITE + 8
+};
+
+/* close the physical screen -- may restore the screen to its state
+   before PDC_scr_open(); miscellaneous cleanup */
+
+void PDC_scr_close(void)
+{
+	PDC_LOG(("PDC_scr_close() - called\n"));
+
+	reset_shell_mode();
+
+	if (SP->visibility != 1)
+		curs_set(1);
+
+	ansi_set_cursor(0, 0);
+	ansi_set_color(39, 49);
+	ansi_clear();
+}
+
+void PDC_scr_free(void)
+{
+	free(SP);
+	free(pdc_atrtab);
+	pdc_atrtab = (unsigned char *)NULL;
+}
+
+/* open the physical screen -- allocate SP, miscellaneous intialization,
+   and may save the existing screen for later restoration */
+
+int PDC_scr_open(int argc, char **argv)
+{
+	int i;
+	int cols = 80;
+	int rows = 25;
+
+	PDC_LOG(("PDC_scr_open() - called\n"));
+
+
+	SP = calloc(1, sizeof(SCREEN));
+	pdc_atrtab = calloc(PDC_COLOR_PAIRS * PDC_OFFSET, 1);
+
+	if (!SP || !pdc_atrtab)
+	return ERR;
+
+	for (i = 0; i < 16; i++)
+		curstoreal[realtocurs[i]] = i;
+
+	SP->orig_attr = FALSE;
+
+	term_get_size(&rows, &cols);
+	SP->lines = rows;
+	SP->cols = cols;
+
+	ansi_clear();
+
+	return OK;
+}
+
+/* the core of resize_term() */
+
+int PDC_resize_screen(int nlines, int ncols)
+{
+	PDC_LOG(("PDC_resize_screen() - called. Lines: %d Cols: %d\n",
+	     nlines, ncols));
+
+	return ERR;
+}
+
+void PDC_reset_prog_mode(void)
+{
+        PDC_LOG(("PDC_reset_prog_mode() - called.\n"));
+}
+
+void PDC_reset_shell_mode(void)
+{
+        PDC_LOG(("PDC_reset_shell_mode() - called.\n"));
+}
+
+void PDC_restore_screen_mode(int i)
+{
+}
+
+void PDC_save_screen_mode(int i)
+{
+}
+
+void PDC_init_pair(short pair, short fg, short bg)
+{
+	unsigned char att, temp_bg;
+	chtype i;
+
+	fg = curstoreal[fg];
+	bg = curstoreal[bg];
+
+	for (i = 0; i < PDC_OFFSET; i++) {
+		att = fg | (bg << 4);
+
+		if (i & (A_REVERSE >> PDC_ATTR_SHIFT))
+			att = bg | (fg << 4);
+		if (i & (A_UNDERLINE >> PDC_ATTR_SHIFT))
+			att = 1;
+		if (i & (A_INVIS >> PDC_ATTR_SHIFT)) {
+			temp_bg = att >> 4;
+			att = temp_bg << 4 | temp_bg;
+		}
+		if (i & (A_BOLD >> PDC_ATTR_SHIFT))
+			att |= 8;
+		if (i & (A_BLINK >> PDC_ATTR_SHIFT))
+			att |= 128;
+
+		pdc_atrtab[pair * PDC_OFFSET + i] = att;
+	}
+}
+
+int PDC_pair_content(short pair, short *fg, short *bg)
+{
+	*fg = realtocurs[pdc_atrtab[pair * PDC_OFFSET] & 0x0F];
+	*bg = realtocurs[(pdc_atrtab[pair * PDC_OFFSET] & 0xF0) >> 4];
+
+	return OK;
+}
+
+bool PDC_can_change_color(void)
+{
+	return FALSE;
+}
+
+int PDC_color_content(short color, short *red, short *green, short *blue)
+{
+	return ERR;
+}
+
+int PDC_init_color(short color, short red, short green, short blue)
+{
+	return ERR;
+}
diff --git a/apps/lib/curses/pdcurses/backend/pdcsetsc.c b/apps/lib/curses/pdcurses/backend/pdcsetsc.c
new file mode 100644
index 0000000..79db8fb
--- /dev/null
+++ b/apps/lib/curses/pdcurses/backend/pdcsetsc.c
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2013 Jean-Christophe PLAGNIOL-VILLARD <plagnio@jcrosoft.com>
+ *
+ * Under BSD
+ */
+
+#include <utils/ansi.h>
+#include "barebox.h"
+
+int PDC_curs_set(int visibility)
+{
+	int ret_vis;
+
+	PDC_LOG(("PDC_curs_set() - called: visibility=%d\n", visibility));
+
+	ret_vis = SP->visibility;
+	SP->visibility = visibility;
+
+	ansi_cursor_enable(visibility);
+
+	return ret_vis;
+}
+
+int PDC_set_blink(bool blinkon)
+{
+	if (pdc_color_started)
+		COLORS = 16;
+
+	return ERR;
+}
+
+void PDC_set_title(const char *title)
+{
+	  printf("\033]0;%s", title);
+}
diff --git a/apps/lib/curses/pdcurses/backend/pdcutil.c b/apps/lib/curses/pdcurses/backend/pdcutil.c
new file mode 100644
index 0000000..d171c01
--- /dev/null
+++ b/apps/lib/curses/pdcurses/backend/pdcutil.c
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2013 Jean-Christophe PLAGNIOL-VILLARD <plagnio@jcrosoft.com>
+ *
+ * Under BSD
+ */
+
+#include "barebox.h"
+
+void PDC_beep(void)
+{
+	PDC_LOG(("PDC_beep() - called\n"));
+
+	printf("\a");
+}
+
+void PDC_napms(int ms)
+{
+	PDC_LOG(("PDC_napms() - called: ms=%d\n", ms));
+
+	usleep(ms * 1000);
+}
+
+const char *PDC_sysname(void)
+{
+	return "barebox";
+}
diff --git a/apps/lib/curses/pdcurses/include/curses.h b/apps/lib/curses/pdcurses/include/curses.h
new file mode 100644
index 0000000..234c5fe
--- /dev/null
+++ b/apps/lib/curses/pdcurses/include/curses.h
@@ -0,0 +1,1378 @@
+/* Public Domain Curses */
+
+/* $Id: curses.h,v 1.295 2008/07/15 17:13:25 wmcbrine Exp $ */
+
+/*----------------------------------------------------------------------*
+ *                              PDCurses                                *
+ *----------------------------------------------------------------------*/
+
+#ifndef __PDCURSES__
+#define __PDCURSES__ 1
+
+/*man-start**************************************************************
+
+PDCurses definitions list:  (Only define those needed)
+
+    XCURSES         True if compiling for X11.
+    PDC_RGB         True if you want to use RGB color definitions
+                    (Red = 1, Green = 2, Blue = 4) instead of BGR.
+    PDC_WIDE        True if building wide-character support.
+    PDC_DLL_BUILD   True if building a Win32 DLL.
+    NCURSES_MOUSE_VERSION   Use the ncurses mouse API instead
+                            of PDCurses' traditional mouse API.
+
+PDCurses portable platform definitions list:
+
+    PDC_BUILD       Defines API build version.
+    PDCURSES        Enables access to PDCurses-only routines.
+    XOPEN           Always true.
+    SYSVcurses      True if you are compiling for SYSV portability.
+    BSDcurses       True if you are compiling for BSD portability.
+
+**man-end****************************************************************/
+
+#define PDC_BUILD 3401
+#define PDCURSES        1      /* PDCurses-only routines */
+#define XOPEN           1      /* X/Open Curses routines */
+#define SYSVcurses      1      /* System V Curses routines */
+#define BSDcurses       1      /* BSD Curses routines */
+#define CHTYPE_LONG     1      /* size of chtype; long */
+#define PDC_RGB			/* RGB mode ansi terminal */
+
+/*----------------------------------------------------------------------*/
+
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdio.h>             /* Required by X/Open usage below */
+
+#ifdef PDC_WIDE
+# include <wchar.h>
+#endif
+
+#if defined(__cplusplus) || defined(__cplusplus__) || defined(__CPLUSPLUS)
+extern "C"
+{
+# define bool _bool
+#endif
+
+/*----------------------------------------------------------------------
+ *
+ *  PDCurses Manifest Constants
+ *
+ */
+
+#ifndef FALSE
+# define FALSE 0
+#endif
+#ifndef TRUE
+# define TRUE 1
+#endif
+#ifndef NULL
+# define NULL (void *)0
+#endif
+#ifndef ERR
+# define ERR (-1)
+#endif
+#ifndef OK
+# define OK 0
+#endif
+
+/*----------------------------------------------------------------------
+ *
+ *  PDCurses Type Declarations
+ *
+ */
+
+//typedef unsigned char bool;    /* PDCurses Boolean type */
+
+#ifdef CHTYPE_LONG
+# if _LP64
+typedef unsigned int chtype;
+# else
+typedef unsigned long chtype;  /* 16-bit attr + 16-bit char */
+# endif
+#else
+typedef unsigned short chtype; /* 8-bit attr + 8-bit char */
+#endif
+
+#ifdef PDC_WIDE
+typedef chtype cchar_t;
+#endif
+
+typedef chtype attr_t;
+
+/*----------------------------------------------------------------------
+ *
+ *  PDCurses Mouse Interface -- SYSVR4, with extensions
+ *
+ */
+
+typedef struct
+{
+    int x;           /* absolute column, 0 based, measured in characters */
+    int y;           /* absolute row, 0 based, measured in characters */
+    short button[3]; /* state of each button */
+    int changes;     /* flags indicating what has changed with the mouse */
+} MOUSE_STATUS;
+
+#define BUTTON_RELEASED         0x0000
+#define BUTTON_PRESSED          0x0001
+#define BUTTON_CLICKED          0x0002
+#define BUTTON_DOUBLE_CLICKED   0x0003
+#define BUTTON_TRIPLE_CLICKED   0x0004
+#define BUTTON_MOVED            0x0005  /* PDCurses */
+#define WHEEL_SCROLLED          0x0006  /* PDCurses */
+#define BUTTON_ACTION_MASK      0x0007  /* PDCurses */
+
+#define PDC_BUTTON_SHIFT        0x0008  /* PDCurses */
+#define PDC_BUTTON_CONTROL      0x0010  /* PDCurses */
+#define PDC_BUTTON_ALT          0x0020  /* PDCurses */
+#define BUTTON_MODIFIER_MASK    0x0038  /* PDCurses */
+
+#define MOUSE_X_POS             (Mouse_status.x)
+#define MOUSE_Y_POS             (Mouse_status.y)
+
+/*
+ * Bits associated with the .changes field:
+ *   3         2         1         0
+ * 210987654321098765432109876543210
+ *                                 1 <- button 1 has changed
+ *                                10 <- button 2 has changed
+ *                               100 <- button 3 has changed
+ *                              1000 <- mouse has moved
+ *                             10000 <- mouse position report
+ *                            100000 <- mouse wheel up
+ *                           1000000 <- mouse wheel down
+ */
+
+#define PDC_MOUSE_MOVED         0x0008
+#define PDC_MOUSE_POSITION      0x0010
+#define PDC_MOUSE_WHEEL_UP      0x0020
+#define PDC_MOUSE_WHEEL_DOWN    0x0040
+
+#define A_BUTTON_CHANGED        (Mouse_status.changes & 7)
+#define MOUSE_MOVED             (Mouse_status.changes & PDC_MOUSE_MOVED)
+#define MOUSE_POS_REPORT        (Mouse_status.changes & PDC_MOUSE_POSITION)
+#define BUTTON_CHANGED(x)       (Mouse_status.changes & (1 << ((x) - 1)))
+#define BUTTON_STATUS(x)        (Mouse_status.button[(x) - 1])
+#define MOUSE_WHEEL_UP          (Mouse_status.changes & PDC_MOUSE_WHEEL_UP)
+#define MOUSE_WHEEL_DOWN        (Mouse_status.changes & PDC_MOUSE_WHEEL_DOWN)
+
+/* mouse bit-masks */
+
+#define BUTTON1_RELEASED        0x00000001L
+#define BUTTON1_PRESSED         0x00000002L
+#define BUTTON1_CLICKED         0x00000004L
+#define BUTTON1_DOUBLE_CLICKED  0x00000008L
+#define BUTTON1_TRIPLE_CLICKED  0x00000010L
+#define BUTTON1_MOVED           0x00000010L /* PDCurses */
+
+#define BUTTON2_RELEASED        0x00000020L
+#define BUTTON2_PRESSED         0x00000040L
+#define BUTTON2_CLICKED         0x00000080L
+#define BUTTON2_DOUBLE_CLICKED  0x00000100L
+#define BUTTON2_TRIPLE_CLICKED  0x00000200L
+#define BUTTON2_MOVED           0x00000200L /* PDCurses */
+
+#define BUTTON3_RELEASED        0x00000400L
+#define BUTTON3_PRESSED         0x00000800L
+#define BUTTON3_CLICKED         0x00001000L
+#define BUTTON3_DOUBLE_CLICKED  0x00002000L
+#define BUTTON3_TRIPLE_CLICKED  0x00004000L
+#define BUTTON3_MOVED           0x00004000L /* PDCurses */
+
+/* For the ncurses-compatible functions only, BUTTON4_PRESSED and 
+   BUTTON5_PRESSED are returned for mouse scroll wheel up and down; 
+   otherwise PDCurses doesn't support buttons 4 and 5 */
+
+#define BUTTON4_RELEASED        0x00008000L
+#define BUTTON4_PRESSED         0x00010000L
+#define BUTTON4_CLICKED         0x00020000L
+#define BUTTON4_DOUBLE_CLICKED  0x00040000L
+#define BUTTON4_TRIPLE_CLICKED  0x00080000L
+
+#define BUTTON5_RELEASED        0x00100000L
+#define BUTTON5_PRESSED         0x00200000L
+#define BUTTON5_CLICKED         0x00400000L
+#define BUTTON5_DOUBLE_CLICKED  0x00800000L
+#define BUTTON5_TRIPLE_CLICKED  0x01000000L
+
+#define MOUSE_WHEEL_SCROLL      0x02000000L /* PDCurses */
+#define BUTTON_MODIFIER_SHIFT   0x04000000L /* PDCurses */
+#define BUTTON_MODIFIER_CONTROL 0x08000000L /* PDCurses */
+#define BUTTON_MODIFIER_ALT     0x10000000L /* PDCurses */
+
+#define ALL_MOUSE_EVENTS        0x1fffffffL
+#define REPORT_MOUSE_POSITION   0x20000000L
+
+/* ncurses mouse interface */
+
+typedef unsigned long mmask_t;
+
+typedef struct
+{
+        short id;       /* unused, always 0 */
+        int x, y, z;    /* x, y same as MOUSE_STATUS; z unused */
+        mmask_t bstate; /* equivalent to changes + button[], but
+                           in the same format as used for mousemask() */
+} MEVENT;
+
+#ifdef NCURSES_MOUSE_VERSION
+# define BUTTON_SHIFT   BUTTON_MODIFIER_SHIFT
+# define BUTTON_CONTROL BUTTON_MODIFIER_CONTROL
+# define BUTTON_CTRL    BUTTON_MODIFIER_CONTROL
+# define BUTTON_ALT     BUTTON_MODIFIER_ALT
+#else
+# define BUTTON_SHIFT   PDC_BUTTON_SHIFT
+# define BUTTON_CONTROL PDC_BUTTON_CONTROL
+# define BUTTON_ALT     PDC_BUTTON_ALT
+#endif
+
+/*----------------------------------------------------------------------
+ *
+ *  PDCurses Structure Definitions
+ *
+ */
+
+typedef struct _win       /* definition of a window */
+{
+    int   _cury;          /* current pseudo-cursor */
+    int   _curx;
+    int   _maxy;          /* max window coordinates */
+    int   _maxx;
+    int   _begy;          /* origin on screen */
+    int   _begx;
+    int   _flags;         /* window properties */
+    chtype _attrs;        /* standard attributes and colors */
+    chtype _bkgd;         /* background, normally blank */
+    bool  _clear;         /* causes clear at next refresh */
+    bool  _leaveit;       /* leaves cursor where it is */
+    bool  _scroll;        /* allows window scrolling */
+    bool  _nodelay;       /* input character wait flag */
+    bool  _immed;         /* immediate update flag */
+    bool  _sync;          /* synchronise window ancestors */
+    bool  _use_keypad;    /* flags keypad key mode active */
+    chtype **_y;          /* pointer to line pointer array */
+    int   *_firstch;      /* first changed character in line */
+    int   *_lastch;       /* last changed character in line */
+    int   _tmarg;         /* top of scrolling region */
+    int   _bmarg;         /* bottom of scrolling region */
+    int   _delayms;       /* milliseconds of delay for getch() */
+    int   _parx, _pary;   /* coords relative to parent (0,0) */
+    struct _win *_parent; /* subwin's pointer to parent win */
+} WINDOW;
+
+/* Avoid using the SCREEN struct directly -- use the corresponding 
+   functions if possible. This struct may eventually be made private. */
+
+typedef struct
+{
+    bool  alive;          /* if initscr() called, and not endwin() */
+    bool  autocr;         /* if cr -> lf */
+    bool  cbreak;         /* if terminal unbuffered */
+    bool  echo;           /* if terminal echo */
+    bool  raw_inp;        /* raw input mode (v. cooked input) */
+    bool  raw_out;        /* raw output mode (7 v. 8 bits) */
+    bool  audible;        /* FALSE if the bell is visual */
+    bool  mono;           /* TRUE if current screen is mono */
+    bool  resized;        /* TRUE if TERM has been resized */
+    bool  orig_attr;      /* TRUE if we have the original colors */
+    short orig_fore;      /* original screen foreground color */
+    short orig_back;      /* original screen foreground color */
+    int   cursrow;        /* position of physical cursor */
+    int   curscol;        /* position of physical cursor */
+    int   visibility;     /* visibility of cursor */
+    int   orig_cursor;    /* original cursor size */
+    int   lines;          /* new value for LINES */
+    int   cols;           /* new value for COLS */
+    unsigned long _trap_mbe;       /* trap these mouse button events */
+    unsigned long _map_mbe_to_key; /* map mouse buttons to slk */
+    int   mouse_wait;              /* time to wait (in ms) for a
+                                      button release after a press, in 
+                                      order to count it as a click */
+    int   slklines;                /* lines in use by slk_init() */
+    WINDOW *slk_winptr;            /* window for slk */
+    int   linesrippedoff;          /* lines ripped off via ripoffline() */
+    int   linesrippedoffontop;     /* lines ripped off on 
+                                      top via ripoffline() */
+    int   delaytenths;             /* 1/10ths second to wait block
+                                      getch() for */
+    bool  _preserve;               /* TRUE if screen background
+                                      to be preserved */
+    int   _restore;                /* specifies if screen background
+                                      to be restored, and how */
+    bool  save_key_modifiers;      /* TRUE if each key modifiers saved
+                                      with each key press */
+    bool  return_key_modifiers;    /* TRUE if modifier keys are
+                                      returned as "real" keys */
+    bool  key_code;                /* TRUE if last key is a special key;
+                                      used internally by get_wch() */
+#ifdef XCURSES
+    int   XcurscrSize;    /* size of Xcurscr shared memory block */
+    bool  sb_on;
+    int   sb_viewport_y;
+    int   sb_viewport_x;
+    int   sb_total_y;
+    int   sb_total_x;
+    int   sb_cur_y;
+    int   sb_cur_x;
+#endif
+    short line_color;     /* color of line attributes - default -1 */
+} SCREEN;
+
+/*----------------------------------------------------------------------
+ *
+ *  PDCurses External Variables
+ *
+ */
+
+#ifdef PDC_DLL_BUILD
+# ifdef CURSES_LIBRARY
+#  define PDCEX __declspec(dllexport) extern
+# else
+#  define PDCEX __declspec(dllimport)
+# endif
+#else
+# define PDCEX extern
+#endif
+
+PDCEX  int          LINES;        /* terminal height */
+PDCEX  int          COLS;         /* terminal width */
+PDCEX  WINDOW       *stdscr;      /* the default screen window */
+PDCEX  WINDOW       *curscr;      /* the current screen image */
+PDCEX  SCREEN       *SP;          /* curses variables */
+PDCEX  MOUSE_STATUS Mouse_status;
+PDCEX  int          COLORS;
+PDCEX  int          COLOR_PAIRS;
+PDCEX  int          TABSIZE;
+PDCEX  chtype       acs_map[];    /* alternate character set map */
+PDCEX  char         ttytype[];    /* terminal name/description */
+
+/*man-start**************************************************************
+
+PDCurses Text Attributes
+========================
+
+Originally, PDCurses used a short (16 bits) for its chtype. To include 
+color, a number of things had to be sacrificed from the strict Unix and 
+System V support. The main problem was fitting all character attributes 
+and color into an unsigned char (all 8 bits!).
+
+Today, PDCurses by default uses a long (32 bits) for its chtype, as in 
+System V. The short chtype is still available, by undefining CHTYPE_LONG 
+and rebuilding the library.
+
+The following is the structure of a win->_attrs chtype:
+
+short form:
+
+-------------------------------------------------
+|15|14|13|12|11|10| 9| 8| 7| 6| 5| 4| 3| 2| 1| 0|
+-------------------------------------------------
+  color number |  attrs |   character eg 'a'
+
+The available non-color attributes are bold, reverse and blink. Others 
+have no effect. The high order char is an index into an array of 
+physical colors (defined in color.c) -- 32 foreground/background color 
+pairs (5 bits) plus 3 bits for other attributes.
+
+long form:
+
+----------------------------------------------------------------------------
+|31|30|29|28|27|26|25|24|23|22|21|20|19|18|17|16|15|14|13|12|..| 3| 2| 1| 0|
+----------------------------------------------------------------------------
+      color number      |     modifiers         |      character eg 'a'
+
+The available non-color attributes are bold, underline, invisible, 
+right-line, left-line, protect, reverse and blink. 256 color pairs (8 
+bits), 8 bits for other attributes, and 16 bits for character data.
+
+**man-end****************************************************************/
+
+/*** Video attribute macros ***/
+
+#define A_NORMAL      (chtype)0
+
+#ifdef CHTYPE_LONG
+# define A_ALTCHARSET (chtype)0x00010000
+# define A_RIGHTLINE  (chtype)0x00020000
+# define A_LEFTLINE   (chtype)0x00040000
+# define A_INVIS      (chtype)0x00080000
+# define A_UNDERLINE  (chtype)0x00100000
+# define A_REVERSE    (chtype)0x00200000
+# define A_BLINK      (chtype)0x00400000
+# define A_BOLD       (chtype)0x00800000
+
+# define A_ATTRIBUTES (chtype)0xffff0000
+# define A_CHARTEXT   (chtype)0x0000ffff
+# define A_COLOR      (chtype)0xff000000
+
+# define A_ITALIC     A_INVIS
+# define A_PROTECT    (A_UNDERLINE | A_LEFTLINE | A_RIGHTLINE)
+
+# define PDC_ATTR_SHIFT  19
+# define PDC_COLOR_SHIFT 24
+#else
+# define A_BOLD       (chtype)0x0100  /* X/Open */
+# define A_REVERSE    (chtype)0x0200  /* X/Open */
+# define A_BLINK      (chtype)0x0400  /* X/Open */
+
+# define A_ATTRIBUTES (chtype)0xff00  /* X/Open */
+# define A_CHARTEXT   (chtype)0x00ff  /* X/Open */
+# define A_COLOR      (chtype)0xf800  /* System V */
+
+# define A_ALTCHARSET A_NORMAL        /* X/Open */
+# define A_PROTECT    A_NORMAL        /* X/Open */
+# define A_UNDERLINE  A_NORMAL        /* X/Open */
+
+# define A_LEFTLINE   A_NORMAL
+# define A_RIGHTLINE  A_NORMAL
+# define A_ITALIC     A_NORMAL
+# define A_INVIS      A_NORMAL
+
+# define PDC_ATTR_SHIFT   8
+# define PDC_COLOR_SHIFT 11
+#endif
+
+#define A_STANDOUT    (A_REVERSE | A_BOLD) /* X/Open */
+#define A_DIM         A_NORMAL
+
+#define CHR_MSK       A_CHARTEXT           /* Obsolete */
+#define ATR_MSK       A_ATTRIBUTES         /* Obsolete */
+#define ATR_NRM       A_NORMAL             /* Obsolete */
+
+/* For use with attr_t -- X/Open says, "these shall be distinct", so 
+   this is a non-conforming implementation. */
+
+#define WA_ALTCHARSET A_ALTCHARSET
+#define WA_BLINK      A_BLINK
+#define WA_BOLD       A_BOLD
+#define WA_DIM        A_DIM
+#define WA_INVIS      A_INVIS
+#define WA_LEFT       A_LEFTLINE
+#define WA_PROTECT    A_PROTECT
+#define WA_REVERSE    A_REVERSE
+#define WA_RIGHT      A_RIGHTLINE
+#define WA_STANDOUT   A_STANDOUT
+#define WA_UNDERLINE  A_UNDERLINE
+
+#define WA_HORIZONTAL A_NORMAL
+#define WA_LOW        A_NORMAL
+#define WA_TOP        A_NORMAL
+#define WA_VERTICAL   A_NORMAL
+
+/*** Alternate character set macros ***/
+
+/* 'w' = 32-bit chtype; acs_map[] index | A_ALTCHARSET
+   'n' = 16-bit chtype; it gets the fallback set because no bit is 
+         available for A_ALTCHARSET */
+
+#ifdef CHTYPE_LONG
+# define ACS_PICK(w, n) ((chtype)w | A_ALTCHARSET)
+#else
+# define ACS_PICK(w, n) ((chtype)n)
+#endif
+
+/* VT100-compatible symbols -- box chars */
+
+#define ACS_ULCORNER  ACS_PICK('l', '+')
+#define ACS_LLCORNER  ACS_PICK('m', '+')
+#define ACS_URCORNER  ACS_PICK('k', '+')
+#define ACS_LRCORNER  ACS_PICK('j', '+')
+#define ACS_RTEE      ACS_PICK('u', '+')
+#define ACS_LTEE      ACS_PICK('t', '+')
+#define ACS_BTEE      ACS_PICK('v', '+')
+#define ACS_TTEE      ACS_PICK('w', '+')
+#define ACS_HLINE     ACS_PICK('q', '-')
+#define ACS_VLINE     ACS_PICK('x', '|')
+#define ACS_PLUS      ACS_PICK('n', '+')
+
+/* VT100-compatible symbols -- other */
+
+#define ACS_S1        ACS_PICK('o', '-')
+#define ACS_S9        ACS_PICK('s', '_')
+#define ACS_DIAMOND   ACS_PICK('`', '+')
+#define ACS_CKBOARD   ACS_PICK('a', ':')
+#define ACS_DEGREE    ACS_PICK('f', '\'')
+#define ACS_PLMINUS   ACS_PICK('g', '#')
+#define ACS_BULLET    ACS_PICK('~', 'o')
+
+/* Teletype 5410v1 symbols -- these are defined in SysV curses, but
+   are not well-supported by most terminals. Stick to VT100 characters
+   for optimum portability. */
+
+#define ACS_LARROW    ACS_PICK(',', '<')
+#define ACS_RARROW    ACS_PICK('+', '>')
+#define ACS_DARROW    ACS_PICK('.', 'v')
+#define ACS_UARROW    ACS_PICK('-', '^')
+#define ACS_BOARD     ACS_PICK('h', '#')
+#define ACS_LANTERN   ACS_PICK('i', '*')
+#define ACS_BLOCK     ACS_PICK('0', '#')
+
+/* That goes double for these -- undocumented SysV symbols. Don't use
+   them. */
+
+#define ACS_S3        ACS_PICK('p', '-')
+#define ACS_S7        ACS_PICK('r', '-')
+#define ACS_LEQUAL    ACS_PICK('y', '<')
+#define ACS_GEQUAL    ACS_PICK('z', '>')
+#define ACS_PI        ACS_PICK('{', 'n')
+#define ACS_NEQUAL    ACS_PICK('|', '+')
+#define ACS_STERLING  ACS_PICK('}', 'L')
+
+/* Box char aliases */
+
+#define ACS_BSSB      ACS_ULCORNER
+#define ACS_SSBB      ACS_LLCORNER
+#define ACS_BBSS      ACS_URCORNER
+#define ACS_SBBS      ACS_LRCORNER
+#define ACS_SBSS      ACS_RTEE
+#define ACS_SSSB      ACS_LTEE
+#define ACS_SSBS      ACS_BTEE
+#define ACS_BSSS      ACS_TTEE
+#define ACS_BSBS      ACS_HLINE
+#define ACS_SBSB      ACS_VLINE
+#define ACS_SSSS      ACS_PLUS
+
+/* cchar_t aliases */
+
+#ifdef PDC_WIDE
+# define WACS_ULCORNER (&(acs_map['l']))
+# define WACS_LLCORNER (&(acs_map['m']))
+# define WACS_URCORNER (&(acs_map['k']))
+# define WACS_LRCORNER (&(acs_map['j']))
+# define WACS_RTEE     (&(acs_map['u']))
+# define WACS_LTEE     (&(acs_map['t']))
+# define WACS_BTEE     (&(acs_map['v']))
+# define WACS_TTEE     (&(acs_map['w']))
+# define WACS_HLINE    (&(acs_map['q']))
+# define WACS_VLINE    (&(acs_map['x']))
+# define WACS_PLUS     (&(acs_map['n']))
+
+# define WACS_S1       (&(acs_map['o']))
+# define WACS_S9       (&(acs_map['s']))
+# define WACS_DIAMOND  (&(acs_map['`']))
+# define WACS_CKBOARD  (&(acs_map['a']))
+# define WACS_DEGREE   (&(acs_map['f']))
+# define WACS_PLMINUS  (&(acs_map['g']))
+# define WACS_BULLET   (&(acs_map['~']))
+
+# define WACS_LARROW   (&(acs_map[',']))
+# define WACS_RARROW   (&(acs_map['+']))
+# define WACS_DARROW   (&(acs_map['.']))
+# define WACS_UARROW   (&(acs_map['-']))
+# define WACS_BOARD    (&(acs_map['h']))
+# define WACS_LANTERN  (&(acs_map['i']))
+# define WACS_BLOCK    (&(acs_map['0']))
+
+# define WACS_S3       (&(acs_map['p']))
+# define WACS_S7       (&(acs_map['r']))
+# define WACS_LEQUAL   (&(acs_map['y']))
+# define WACS_GEQUAL   (&(acs_map['z']))
+# define WACS_PI       (&(acs_map['{']))
+# define WACS_NEQUAL   (&(acs_map['|']))
+# define WACS_STERLING (&(acs_map['}']))
+
+# define WACS_BSSB     WACS_ULCORNER
+# define WACS_SSBB     WACS_LLCORNER
+# define WACS_BBSS     WACS_URCORNER
+# define WACS_SBBS     WACS_LRCORNER
+# define WACS_SBSS     WACS_RTEE
+# define WACS_SSSB     WACS_LTEE
+# define WACS_SSBS     WACS_BTEE
+# define WACS_BSSS     WACS_TTEE
+# define WACS_BSBS     WACS_HLINE
+# define WACS_SBSB     WACS_VLINE
+# define WACS_SSSS     WACS_PLUS
+#endif
+
+/*** Color macros ***/
+
+#define COLOR_BLACK   0
+
+#ifdef PDC_RGB        /* RGB */
+# define COLOR_RED    1
+# define COLOR_GREEN  2
+# define COLOR_BLUE   4
+#else                 /* BGR */
+# define COLOR_BLUE   1
+# define COLOR_GREEN  2
+# define COLOR_RED    4
+#endif
+
+#define COLOR_CYAN    (COLOR_BLUE | COLOR_GREEN)
+#define COLOR_MAGENTA (COLOR_RED | COLOR_BLUE)
+#define COLOR_YELLOW  (COLOR_RED | COLOR_GREEN)
+
+#define COLOR_WHITE   7
+
+/*----------------------------------------------------------------------
+ *
+ *  Function and Keypad Key Definitions.
+ *  Many are just for compatibility.
+ *
+ */
+
+#define KEY_CODE_YES  0x100  /* If get_wch() gives a key code */
+
+#define KEY_BREAK     0x101  /* Not on PC KBD */
+#define KEY_DOWN      0x102  /* Down arrow key */
+#define KEY_UP        0x103  /* Up arrow key */
+#define KEY_LEFT      0x104  /* Left arrow key */
+#define KEY_RIGHT     0x105  /* Right arrow key */
+#define KEY_HOME      0x106  /* home key */
+#define KEY_BACKSPACE 0x107  /* not on pc */
+#define KEY_F0        0x108  /* function keys; 64 reserved */
+
+#define KEY_DL        0x148  /* delete line */
+#define KEY_IL        0x149  /* insert line */
+#define KEY_DC        0x14a  /* delete character */
+#define KEY_IC        0x14b  /* insert char or enter ins mode */
+#define KEY_EIC       0x14c  /* exit insert char mode */
+#define KEY_CLEAR     0x14d  /* clear screen */
+#define KEY_EOS       0x14e  /* clear to end of screen */
+#define KEY_EOL       0x14f  /* clear to end of line */
+#define KEY_SF        0x150  /* scroll 1 line forward */
+#define KEY_SR        0x151  /* scroll 1 line back (reverse) */
+#define KEY_NPAGE     0x152  /* next page */
+#define KEY_PPAGE     0x153  /* previous page */
+#define KEY_STAB      0x154  /* set tab */
+#define KEY_CTAB      0x155  /* clear tab */
+#define KEY_CATAB     0x156  /* clear all tabs */
+#define KEY_ENTER     0x157  /* enter or send (unreliable) */
+#define KEY_SRESET    0x158  /* soft/reset (partial/unreliable) */
+#define KEY_RESET     0x159  /* reset/hard reset (unreliable) */
+#define KEY_PRINT     0x15a  /* print/copy */
+#define KEY_LL        0x15b  /* home down/bottom (lower left) */
+#define KEY_ABORT     0x15c  /* abort/terminate key (any) */
+#define KEY_SHELP     0x15d  /* short help */
+#define KEY_LHELP     0x15e  /* long help */
+#define KEY_BTAB      0x15f  /* Back tab key */
+#define KEY_BEG       0x160  /* beg(inning) key */
+#define KEY_CANCEL    0x161  /* cancel key */
+#define KEY_CLOSE     0x162  /* close key */
+#define KEY_COMMAND   0x163  /* cmd (command) key */
+#define KEY_COPY      0x164  /* copy key */
+#define KEY_CREATE    0x165  /* create key */
+#define KEY_END       0x166  /* end key */
+#define KEY_EXIT      0x167  /* exit key */
+#define KEY_FIND      0x168  /* find key */
+#define KEY_HELP      0x169  /* help key */
+#define KEY_MARK      0x16a  /* mark key */
+#define KEY_MESSAGE   0x16b  /* message key */
+#define KEY_MOVE      0x16c  /* move key */
+#define KEY_NEXT      0x16d  /* next object key */
+#define KEY_OPEN      0x16e  /* open key */
+#define KEY_OPTIONS   0x16f  /* options key */
+#define KEY_PREVIOUS  0x170  /* previous object key */
+#define KEY_REDO      0x171  /* redo key */
+#define KEY_REFERENCE 0x172  /* ref(erence) key */
+#define KEY_REFRESH   0x173  /* refresh key */
+#define KEY_REPLACE   0x174  /* replace key */
+#define KEY_RESTART   0x175  /* restart key */
+#define KEY_RESUME    0x176  /* resume key */
+#define KEY_SAVE      0x177  /* save key */
+#define KEY_SBEG      0x178  /* shifted beginning key */
+#define KEY_SCANCEL   0x179  /* shifted cancel key */
+#define KEY_SCOMMAND  0x17a  /* shifted command key */
+#define KEY_SCOPY     0x17b  /* shifted copy key */
+#define KEY_SCREATE   0x17c  /* shifted create key */
+#define KEY_SDC       0x17d  /* shifted delete char key */
+#define KEY_SDL       0x17e  /* shifted delete line key */
+#define KEY_SELECT    0x17f  /* select key */
+#define KEY_SEND      0x180  /* shifted end key */
+#define KEY_SEOL      0x181  /* shifted clear line key */
+#define KEY_SEXIT     0x182  /* shifted exit key */
+#define KEY_SFIND     0x183  /* shifted find key */
+#define KEY_SHOME     0x184  /* shifted home key */
+#define KEY_SIC       0x185  /* shifted input key */
+
+#define KEY_SLEFT     0x187  /* shifted left arrow key */
+#define KEY_SMESSAGE  0x188  /* shifted message key */
+#define KEY_SMOVE     0x189  /* shifted move key */
+#define KEY_SNEXT     0x18a  /* shifted next key */
+#define KEY_SOPTIONS  0x18b  /* shifted options key */
+#define KEY_SPREVIOUS 0x18c  /* shifted prev key */
+#define KEY_SPRINT    0x18d  /* shifted print key */
+#define KEY_SREDO     0x18e  /* shifted redo key */
+#define KEY_SREPLACE  0x18f  /* shifted replace key */
+#define KEY_SRIGHT    0x190  /* shifted right arrow */
+#define KEY_SRSUME    0x191  /* shifted resume key */
+#define KEY_SSAVE     0x192  /* shifted save key */
+#define KEY_SSUSPEND  0x193  /* shifted suspend key */
+#define KEY_SUNDO     0x194  /* shifted undo key */
+#define KEY_SUSPEND   0x195  /* suspend key */
+#define KEY_UNDO      0x196  /* undo key */
+
+/* PDCurses-specific key definitions -- PC only */
+
+#define ALT_0         0x197
+#define ALT_1         0x198
+#define ALT_2         0x199
+#define ALT_3         0x19a
+#define ALT_4         0x19b
+#define ALT_5         0x19c
+#define ALT_6         0x19d
+#define ALT_7         0x19e
+#define ALT_8         0x19f
+#define ALT_9         0x1a0
+#define ALT_A         0x1a1
+#define ALT_B         0x1a2
+#define ALT_C         0x1a3
+#define ALT_D         0x1a4
+#define ALT_E         0x1a5
+#define ALT_F         0x1a6
+#define ALT_G         0x1a7
+#define ALT_H         0x1a8
+#define ALT_I         0x1a9
+#define ALT_J         0x1aa
+#define ALT_K         0x1ab
+#define ALT_L         0x1ac
+#define ALT_M         0x1ad
+#define ALT_N         0x1ae
+#define ALT_O         0x1af
+#define ALT_P         0x1b0
+#define ALT_Q         0x1b1
+#define ALT_R         0x1b2
+#define ALT_S         0x1b3
+#define ALT_T         0x1b4
+#define ALT_U         0x1b5
+#define ALT_V         0x1b6
+#define ALT_W         0x1b7
+#define ALT_X         0x1b8
+#define ALT_Y         0x1b9
+#define ALT_Z         0x1ba
+
+#define CTL_LEFT      0x1bb  /* Control-Left-Arrow */
+#define CTL_RIGHT     0x1bc
+#define CTL_PGUP      0x1bd
+#define CTL_PGDN      0x1be
+#define CTL_HOME      0x1bf
+#define CTL_END       0x1c0
+
+#define KEY_A1        0x1c1  /* upper left on Virtual keypad */
+#define KEY_A2        0x1c2  /* upper middle on Virt. keypad */
+#define KEY_A3        0x1c3  /* upper right on Vir. keypad */
+#define KEY_B1        0x1c4  /* middle left on Virt. keypad */
+#define KEY_B2        0x1c5  /* center on Virt. keypad */
+#define KEY_B3        0x1c6  /* middle right on Vir. keypad */
+#define KEY_C1        0x1c7  /* lower left on Virt. keypad */
+#define KEY_C2        0x1c8  /* lower middle on Virt. keypad */
+#define KEY_C3        0x1c9  /* lower right on Vir. keypad */
+
+#define PADSLASH      0x1ca  /* slash on keypad */
+#define PADENTER      0x1cb  /* enter on keypad */
+#define CTL_PADENTER  0x1cc  /* ctl-enter on keypad */
+#define ALT_PADENTER  0x1cd  /* alt-enter on keypad */
+#define PADSTOP       0x1ce  /* stop on keypad */
+#define PADSTAR       0x1cf  /* star on keypad */
+#define PADMINUS      0x1d0  /* minus on keypad */
+#define PADPLUS       0x1d1  /* plus on keypad */
+#define CTL_PADSTOP   0x1d2  /* ctl-stop on keypad */
+#define CTL_PADCENTER 0x1d3  /* ctl-enter on keypad */
+#define CTL_PADPLUS   0x1d4  /* ctl-plus on keypad */
+#define CTL_PADMINUS  0x1d5  /* ctl-minus on keypad */
+#define CTL_PADSLASH  0x1d6  /* ctl-slash on keypad */
+#define CTL_PADSTAR   0x1d7  /* ctl-star on keypad */
+#define ALT_PADPLUS   0x1d8  /* alt-plus on keypad */
+#define ALT_PADMINUS  0x1d9  /* alt-minus on keypad */
+#define ALT_PADSLASH  0x1da  /* alt-slash on keypad */
+#define ALT_PADSTAR   0x1db  /* alt-star on keypad */
+#define ALT_PADSTOP   0x1dc  /* alt-stop on keypad */
+#define CTL_INS       0x1dd  /* ctl-insert */
+#define ALT_DEL       0x1de  /* alt-delete */
+#define ALT_INS       0x1df  /* alt-insert */
+#define CTL_UP        0x1e0  /* ctl-up arrow */
+#define CTL_DOWN      0x1e1  /* ctl-down arrow */
+#define CTL_TAB       0x1e2  /* ctl-tab */
+#define ALT_TAB       0x1e3
+#define ALT_MINUS     0x1e4
+#define ALT_EQUAL     0x1e5
+#define ALT_HOME      0x1e6
+#define ALT_PGUP      0x1e7
+#define ALT_PGDN      0x1e8
+#define ALT_END       0x1e9
+#define ALT_UP        0x1ea  /* alt-up arrow */
+#define ALT_DOWN      0x1eb  /* alt-down arrow */
+#define ALT_RIGHT     0x1ec  /* alt-right arrow */
+#define ALT_LEFT      0x1ed  /* alt-left arrow */
+#define ALT_ENTER     0x1ee  /* alt-enter */
+#define ALT_ESC       0x1ef  /* alt-escape */
+#define ALT_BQUOTE    0x1f0  /* alt-back quote */
+#define ALT_LBRACKET  0x1f1  /* alt-left bracket */
+#define ALT_RBRACKET  0x1f2  /* alt-right bracket */
+#define ALT_SEMICOLON 0x1f3  /* alt-semi-colon */
+#define ALT_FQUOTE    0x1f4  /* alt-forward quote */
+#define ALT_COMMA     0x1f5  /* alt-comma */
+#define ALT_STOP      0x1f6  /* alt-stop */
+#define ALT_FSLASH    0x1f7  /* alt-forward slash */
+#define ALT_BKSP      0x1f8  /* alt-backspace */
+#define CTL_BKSP      0x1f9  /* ctl-backspace */
+#define PAD0          0x1fa  /* keypad 0 */
+
+#define CTL_PAD0      0x1fb  /* ctl-keypad 0 */
+#define CTL_PAD1      0x1fc
+#define CTL_PAD2      0x1fd
+#define CTL_PAD3      0x1fe
+#define CTL_PAD4      0x1ff
+#define CTL_PAD5      0x200
+#define CTL_PAD6      0x201
+#define CTL_PAD7      0x202
+#define CTL_PAD8      0x203
+#define CTL_PAD9      0x204
+
+#define ALT_PAD0      0x205  /* alt-keypad 0 */
+#define ALT_PAD1      0x206
+#define ALT_PAD2      0x207
+#define ALT_PAD3      0x208
+#define ALT_PAD4      0x209
+#define ALT_PAD5      0x20a
+#define ALT_PAD6      0x20b
+#define ALT_PAD7      0x20c
+#define ALT_PAD8      0x20d
+#define ALT_PAD9      0x20e
+
+#define CTL_DEL       0x20f  /* clt-delete */
+#define ALT_BSLASH    0x210  /* alt-back slash */
+#define CTL_ENTER     0x211  /* ctl-enter */
+
+#define SHF_PADENTER  0x212  /* shift-enter on keypad */
+#define SHF_PADSLASH  0x213  /* shift-slash on keypad */
+#define SHF_PADSTAR   0x214  /* shift-star  on keypad */
+#define SHF_PADPLUS   0x215  /* shift-plus  on keypad */
+#define SHF_PADMINUS  0x216  /* shift-minus on keypad */
+#define SHF_UP        0x217  /* shift-up on keypad */
+#define SHF_DOWN      0x218  /* shift-down on keypad */
+#define SHF_IC        0x219  /* shift-insert on keypad */
+#define SHF_DC        0x21a  /* shift-delete on keypad */
+
+#define KEY_MOUSE     0x21b  /* "mouse" key */
+#define KEY_SHIFT_L   0x21c  /* Left-shift */
+#define KEY_SHIFT_R   0x21d  /* Right-shift */
+#define KEY_CONTROL_L 0x21e  /* Left-control */
+#define KEY_CONTROL_R 0x21f  /* Right-control */
+#define KEY_ALT_L     0x220  /* Left-alt */
+#define KEY_ALT_R     0x221  /* Right-alt */
+#define KEY_RESIZE    0x222  /* Window resize */
+#define KEY_SUP       0x223  /* Shifted up arrow */
+#define KEY_SDOWN     0x224  /* Shifted down arrow */
+
+#define KEY_MIN       KEY_BREAK      /* Minimum curses key value */
+#define KEY_MAX       KEY_SDOWN      /* Maximum curses key */
+
+#define KEY_F(n)      (KEY_F0 + (n))
+
+/*----------------------------------------------------------------------
+ *
+ *  PDCurses Function Declarations
+ *
+ */
+
+/* Standard */
+
+int     addch(const chtype);
+int     addchnstr(const chtype *, int);
+int     addchstr(const chtype *);
+int     addnstr(const char *, int);
+int     addstr(const char *);
+int     attroff(chtype);
+int     attron(chtype);
+int     attrset(chtype);
+int     attr_get(attr_t *, short *, void *);
+int     attr_off(attr_t, void *);
+int     attr_on(attr_t, void *);
+int     attr_set(attr_t, short, void *);
+int     baudrate(void);
+int     beep(void);
+int     bkgd(chtype);
+void    bkgdset(chtype);
+int     border(chtype, chtype, chtype, chtype, chtype, chtype, chtype, chtype);
+int     box(WINDOW *, chtype, chtype);
+bool    can_change_color(void);
+int     cbreak(void); 
+int     chgat(int, attr_t, short, const void *);
+int     clearok(WINDOW *, bool);
+int     clear(void);
+int     clrtobot(void);
+int     clrtoeol(void);
+int     color_content(short, short *, short *, short *);
+int     color_set(short, void *);
+int     copywin(const WINDOW *, WINDOW *, int, int, int, int, int, int, int);
+int     curs_set(int);
+int     def_prog_mode(void);
+int     def_shell_mode(void);
+int     delay_output(int);
+int     delch(void);
+int     deleteln(void);
+void    delscreen(SCREEN *); 
+int     delwin(WINDOW *);
+WINDOW *derwin(WINDOW *, int, int, int, int);
+int     doupdate(void);
+WINDOW *dupwin(WINDOW *);
+int     echochar(const chtype);
+int     echo(void);
+int     endwin(void);
+char    erasechar(void);
+int     erase(void);
+void    filter(void);
+int     flash(void);
+int     flushinp(void);
+chtype  getbkgd(WINDOW *);
+int     getnstr(char *, int);
+int     getstr(char *);
+WINDOW *getwin(FILE *);
+int     halfdelay(int);
+bool    has_colors(void);
+bool    has_ic(void);
+bool    has_il(void);
+int     hline(chtype, int);
+void    idcok(WINDOW *, bool);
+int     idlok(WINDOW *, bool);
+void    immedok(WINDOW *, bool);
+int     inchnstr(chtype *, int);
+int     inchstr(chtype *);
+chtype  inch(void);
+int     init_color(short, short, short, short);
+int     init_pair(short, short, short);
+WINDOW *initscr(void);
+int     innstr(char *, int);
+int     insch(chtype);
+int     insdelln(int);
+int     insertln(void);
+int     insnstr(const char *, int);
+int     insstr(const char *);
+int     instr(char *);
+int     intrflush(WINDOW *, bool);
+bool    isendwin(void);
+bool    is_linetouched(WINDOW *, int);
+bool    is_wintouched(WINDOW *);
+char   *keyname(int);
+int     keypad(WINDOW *, bool);
+char    killchar(void);
+int     leaveok(WINDOW *, bool);
+char   *longname(void);
+int     meta(WINDOW *, bool);
+int     move(int, int);
+int     mvaddch(int, int, const chtype);
+int     mvaddchnstr(int, int, const chtype *, int);
+int     mvaddchstr(int, int, const chtype *);
+int     mvaddnstr(int, int, const char *, int);
+int     mvaddstr(int, int, const char *);
+int     mvchgat(int, int, int, attr_t, short, const void *);
+int     mvcur(int, int, int, int);
+int     mvdelch(int, int);
+int     mvderwin(WINDOW *, int, int);
+int     mvgetch(int, int);
+int     mvgetnstr(int, int, char *, int);
+int     mvgetstr(int, int, char *);
+int     mvhline(int, int, chtype, int);
+chtype  mvinch(int, int);
+int     mvinchnstr(int, int, chtype *, int);
+int     mvinchstr(int, int, chtype *);
+int     mvinnstr(int, int, char *, int);
+int     mvinsch(int, int, chtype);
+int     mvinsnstr(int, int, const char *, int);
+int     mvinsstr(int, int, const char *);
+int     mvinstr(int, int, char *);
+int     mvprintw(int, int, const char *, ...);
+int     mvscanw(int, int, const char *, ...);
+int     mvvline(int, int, chtype, int);
+int     mvwaddchnstr(WINDOW *, int, int, const chtype *, int);
+int     mvwaddchstr(WINDOW *, int, int, const chtype *);
+int     mvwaddch(WINDOW *, int, int, const chtype);
+int     mvwaddnstr(WINDOW *, int, int, const char *, int);
+int     mvwaddstr(WINDOW *, int, int, const char *);
+int     mvwchgat(WINDOW *, int, int, int, attr_t, short, const void *);
+int     mvwdelch(WINDOW *, int, int);
+int     mvwgetch(WINDOW *, int, int);
+int     mvwgetnstr(WINDOW *, int, int, char *, int);
+int     mvwgetstr(WINDOW *, int, int, char *);
+int     mvwhline(WINDOW *, int, int, chtype, int);
+int     mvwinchnstr(WINDOW *, int, int, chtype *, int);
+int     mvwinchstr(WINDOW *, int, int, chtype *);
+chtype  mvwinch(WINDOW *, int, int);
+int     mvwinnstr(WINDOW *, int, int, char *, int);
+int     mvwinsch(WINDOW *, int, int, chtype);
+int     mvwinsnstr(WINDOW *, int, int, const char *, int);
+int     mvwinsstr(WINDOW *, int, int, const char *);
+int     mvwinstr(WINDOW *, int, int, char *);
+int     mvwin(WINDOW *, int, int);
+int     mvwprintw(WINDOW *, int, int, const char *, ...);
+int     mvwscanw(WINDOW *, int, int, const char *, ...);
+int     mvwvline(WINDOW *, int, int, chtype, int);
+int     napms(int);
+WINDOW *newpad(int, int);
+SCREEN *newterm(const char *, FILE *, FILE *);
+WINDOW *newwin(int, int, int, int);
+int     nl(void);
+int     nocbreak(void);
+int     nodelay(WINDOW *, bool);
+int     noecho(void);
+int     nonl(void);
+void    noqiflush(void);
+int     noraw(void);
+int     notimeout(WINDOW *, bool);
+int     overlay(const WINDOW *, WINDOW *);
+int     overwrite(const WINDOW *, WINDOW *);
+int     pair_content(short, short *, short *);
+int     pechochar(WINDOW *, chtype);
+int     pnoutrefresh(WINDOW *, int, int, int, int, int, int);
+int     prefresh(WINDOW *, int, int, int, int, int, int);
+int     printw(const char *, ...);
+int     putwin(WINDOW *, FILE *);
+void    qiflush(void);
+int     raw(void);
+int     redrawwin(WINDOW *);
+int     refresh(void);
+int     reset_prog_mode(void);
+int     reset_shell_mode(void);
+int     resetty(void);
+int     ripoffline(int, int (*)(WINDOW *, int));
+int     savetty(void);
+int     scanw(const char *, ...);
+int     scr_dump(const char *);
+int     scr_init(const char *);
+int     scr_restore(const char *);
+int     scr_set(const char *);
+int     scrl(int);
+int     scroll(WINDOW *);
+int     scrollok(WINDOW *, bool);
+SCREEN *set_term(SCREEN *);
+int     setscrreg(int, int);
+int     slk_attroff(const chtype);
+int     slk_attr_off(const attr_t, void *);
+int     slk_attron(const chtype);
+int     slk_attr_on(const attr_t, void *);
+int     slk_attrset(const chtype);
+int     slk_attr_set(const attr_t, short, void *);
+int     slk_clear(void);
+int     slk_color(short);
+int     slk_init(int);
+char   *slk_label(int);
+int     slk_noutrefresh(void);
+int     slk_refresh(void);
+int     slk_restore(void);
+int     slk_set(int, const char *, int);
+int     slk_touch(void);
+int     standend(void);
+int     standout(void);
+int     start_color(void);
+WINDOW *subpad(WINDOW *, int, int, int, int);
+WINDOW *subwin(WINDOW *, int, int, int, int);
+int     syncok(WINDOW *, bool);
+chtype  termattrs(void);
+attr_t  term_attrs(void);
+char   *termname(void);
+void    timeout(int);
+int     touchline(WINDOW *, int, int);
+int     touchwin(WINDOW *);
+int     typeahead(int);
+int     untouchwin(WINDOW *);
+void    use_env(bool);
+int     vidattr(chtype);
+int     vid_attr(attr_t, short, void *);
+int     vidputs(chtype, int (*)(int));
+int     vid_puts(attr_t, short, void *, int (*)(int));
+int     vline(chtype, int);
+int     vw_printw(WINDOW *, const char *, va_list);
+int     vwprintw(WINDOW *, const char *, va_list);
+int     vw_scanw(WINDOW *, const char *, va_list);
+int     vwscanw(WINDOW *, const char *, va_list);
+int     waddchnstr(WINDOW *, const chtype *, int);
+int     waddchstr(WINDOW *, const chtype *);
+int     waddch(WINDOW *, const chtype);
+int     waddnstr(WINDOW *, const char *, int);
+int     waddstr(WINDOW *, const char *);
+int     wattroff(WINDOW *, chtype);
+int     wattron(WINDOW *, chtype);
+int     wattrset(WINDOW *, chtype);
+int     wattr_get(WINDOW *, attr_t *, short *, void *);
+int     wattr_off(WINDOW *, attr_t, void *);
+int     wattr_on(WINDOW *, attr_t, void *);
+int     wattr_set(WINDOW *, attr_t, short, void *);
+void    wbkgdset(WINDOW *, chtype);
+int     wbkgd(WINDOW *, chtype);
+int     wborder(WINDOW *, chtype, chtype, chtype, chtype,
+                chtype, chtype, chtype, chtype);
+int     wchgat(WINDOW *, int, attr_t, short, const void *);
+int     wclear(WINDOW *);
+int     wclrtobot(WINDOW *);
+int     wclrtoeol(WINDOW *);
+int     wcolor_set(WINDOW *, short, void *);
+void    wcursyncup(WINDOW *);
+int     wdelch(WINDOW *);
+int     wdeleteln(WINDOW *);
+int     wechochar(WINDOW *, const chtype);
+int     werase(WINDOW *);
+int     wgetch(WINDOW *);
+int     wgetnstr(WINDOW *, char *, int);
+int     wgetstr(WINDOW *, char *);
+int     whline(WINDOW *, chtype, int);
+int     winchnstr(WINDOW *, chtype *, int);
+int     winchstr(WINDOW *, chtype *);
+chtype  winch(WINDOW *);
+int     winnstr(WINDOW *, char *, int);
+int     winsch(WINDOW *, chtype);
+int     winsdelln(WINDOW *, int);
+int     winsertln(WINDOW *);
+int     winsnstr(WINDOW *, const char *, int);
+int     winsstr(WINDOW *, const char *);
+int     winstr(WINDOW *, char *);
+int     wmove(WINDOW *, int, int);
+int     wnoutrefresh(WINDOW *);
+int     wprintw(WINDOW *, const char *, ...);
+int     wredrawln(WINDOW *, int, int);
+int     wrefresh(WINDOW *);
+int     wscanw(WINDOW *, const char *, ...);
+int     wscrl(WINDOW *, int);
+int     wsetscrreg(WINDOW *, int, int);
+int     wstandend(WINDOW *);
+int     wstandout(WINDOW *);
+void    wsyncdown(WINDOW *);
+void    wsyncup(WINDOW *);
+void    wtimeout(WINDOW *, int);
+int     wtouchln(WINDOW *, int, int, int);
+int     wvline(WINDOW *, chtype, int);
+
+/* Wide-character functions */
+
+#ifdef PDC_WIDE
+int     addnwstr(const wchar_t *, int);
+int     addwstr(const wchar_t *);
+int     add_wch(const cchar_t *);
+int     add_wchnstr(const cchar_t *, int);
+int     add_wchstr(const cchar_t *);
+int     border_set(const cchar_t *, const cchar_t *, const cchar_t *, 
+                   const cchar_t *, const cchar_t *, const cchar_t *, 
+                   const cchar_t *, const cchar_t *);
+int     box_set(WINDOW *, const cchar_t *, const cchar_t *);
+int     echo_wchar(const cchar_t *);
+int     erasewchar(wchar_t *);
+int     getbkgrnd(cchar_t *);
+int     getcchar(const cchar_t *, wchar_t *, attr_t *, short *, void *);
+int     getn_wstr(wint_t *, int);
+int     get_wch(wint_t *);
+int     get_wstr(wint_t *);
+int     hline_set(const cchar_t *, int);
+int     innwstr(wchar_t *, int);
+int     ins_nwstr(const wchar_t *, int);
+int     ins_wch(const cchar_t *);
+int     ins_wstr(const wchar_t *);
+int     inwstr(wchar_t *);
+int     in_wch(cchar_t *);
+int     in_wchnstr(cchar_t *, int);
+int     in_wchstr(cchar_t *);
+char   *key_name(wchar_t);
+int     killwchar(wchar_t *);
+int     mvaddnwstr(int, int, const wchar_t *, int);
+int     mvaddwstr(int, int, const wchar_t *);
+int     mvadd_wch(int, int, const cchar_t *);
+int     mvadd_wchnstr(int, int, const cchar_t *, int);
+int     mvadd_wchstr(int, int, const cchar_t *);
+int     mvgetn_wstr(int, int, wint_t *, int);
+int     mvget_wch(int, int, wint_t *);
+int     mvget_wstr(int, int, wint_t *);
+int     mvhline_set(int, int, const cchar_t *, int);
+int     mvinnwstr(int, int, wchar_t *, int);
+int     mvins_nwstr(int, int, const wchar_t *, int);
+int     mvins_wch(int, int, const cchar_t *);
+int     mvins_wstr(int, int, const wchar_t *);
+int     mvinwstr(int, int, wchar_t *);
+int     mvin_wch(int, int, cchar_t *);
+int     mvin_wchnstr(int, int, cchar_t *, int);
+int     mvin_wchstr(int, int, cchar_t *);
+int     mvvline_set(int, int, const cchar_t *, int);
+int     mvwaddnwstr(WINDOW *, int, int, const wchar_t *, int);
+int     mvwaddwstr(WINDOW *, int, int, const wchar_t *);
+int     mvwadd_wch(WINDOW *, int, int, const cchar_t *);
+int     mvwadd_wchnstr(WINDOW *, int, int, const cchar_t *, int);
+int     mvwadd_wchstr(WINDOW *, int, int, const cchar_t *);
+int     mvwgetn_wstr(WINDOW *, int, int, wint_t *, int);
+int     mvwget_wch(WINDOW *, int, int, wint_t *);
+int     mvwget_wstr(WINDOW *, int, int, wint_t *);
+int     mvwhline_set(WINDOW *, int, int, const cchar_t *, int);
+int     mvwinnwstr(WINDOW *, int, int, wchar_t *, int);
+int     mvwins_nwstr(WINDOW *, int, int, const wchar_t *, int);
+int     mvwins_wch(WINDOW *, int, int, const cchar_t *);
+int     mvwins_wstr(WINDOW *, int, int, const wchar_t *);
+int     mvwin_wch(WINDOW *, int, int, cchar_t *);
+int     mvwin_wchnstr(WINDOW *, int, int, cchar_t *, int);
+int     mvwin_wchstr(WINDOW *, int, int, cchar_t *);
+int     mvwinwstr(WINDOW *, int, int, wchar_t *);
+int     mvwvline_set(WINDOW *, int, int, const cchar_t *, int);
+int     pecho_wchar(WINDOW *, const cchar_t*);
+int     setcchar(cchar_t*, const wchar_t*, const attr_t, short, const void*);
+int     slk_wset(int, const wchar_t *, int);
+int     unget_wch(const wchar_t);
+int     vline_set(const cchar_t *, int);
+int     waddnwstr(WINDOW *, const wchar_t *, int);
+int     waddwstr(WINDOW *, const wchar_t *);
+int     wadd_wch(WINDOW *, const cchar_t *);
+int     wadd_wchnstr(WINDOW *, const cchar_t *, int);
+int     wadd_wchstr(WINDOW *, const cchar_t *);
+int     wbkgrnd(WINDOW *, const cchar_t *);
+void    wbkgrndset(WINDOW *, const cchar_t *);
+int     wborder_set(WINDOW *, const cchar_t *, const cchar_t *,
+                    const cchar_t *, const cchar_t *, const cchar_t *, 
+                    const cchar_t *, const cchar_t *, const cchar_t *);
+int     wecho_wchar(WINDOW *, const cchar_t *);
+int     wgetbkgrnd(WINDOW *, cchar_t *);
+int     wgetn_wstr(WINDOW *, wint_t *, int);
+int     wget_wch(WINDOW *, wint_t *);
+int     wget_wstr(WINDOW *, wint_t *);
+int     whline_set(WINDOW *, const cchar_t *, int);
+int     winnwstr(WINDOW *, wchar_t *, int);
+int     wins_nwstr(WINDOW *, const wchar_t *, int);
+int     wins_wch(WINDOW *, const cchar_t *);
+int     wins_wstr(WINDOW *, const wchar_t *);
+int     winwstr(WINDOW *, wchar_t *);
+int     win_wch(WINDOW *, cchar_t *);
+int     win_wchnstr(WINDOW *, cchar_t *, int);
+int     win_wchstr(WINDOW *, cchar_t *);
+wchar_t *wunctrl(cchar_t *);
+int     wvline_set(WINDOW *, const cchar_t *, int);
+#endif
+
+/* Quasi-standard */
+
+chtype  getattrs(WINDOW *);
+int     getbegx(WINDOW *);
+int     getbegy(WINDOW *);
+int     getmaxx(WINDOW *);
+int     getmaxy(WINDOW *);
+int     getparx(WINDOW *);
+int     getpary(WINDOW *);
+int     getcurx(WINDOW *);
+int     getcury(WINDOW *);
+void    traceoff(void);
+void    traceon(void);
+char   *unctrl(chtype);
+
+int     crmode(void);
+int     nocrmode(void);
+int     draino(int);
+int     resetterm(void);
+int     fixterm(void);
+int     saveterm(void);
+int     setsyx(int, int);
+
+int     mouse_set(unsigned long);
+int     mouse_on(unsigned long);
+int     mouse_off(unsigned long);
+int     request_mouse_pos(void);
+int     map_button(unsigned long);
+void    wmouse_position(WINDOW *, int *, int *);
+unsigned long getmouse(void);
+unsigned long getbmap(void);
+
+/* ncurses */
+
+int     assume_default_colors(int, int);
+const char *curses_version(void);
+bool    has_key(int);
+int     use_default_colors(void);
+int     wresize(WINDOW *, int, int);
+
+int     mouseinterval(int);
+mmask_t mousemask(mmask_t, mmask_t *);
+bool    mouse_trafo(int *, int *, bool);
+int     nc_getmouse(MEVENT *);
+int     ungetmouse(MEVENT *);
+bool    wenclose(const WINDOW *, int, int);
+bool    wmouse_trafo(const WINDOW *, int *, int *, bool);
+
+/* PDCurses */
+
+int     addrawch(chtype);
+int     insrawch(chtype);
+bool    is_termresized(void);
+int     mvaddrawch(int, int, chtype);
+int     mvdeleteln(int, int);
+int     mvinsertln(int, int);
+int     mvinsrawch(int, int, chtype);
+int     mvwaddrawch(WINDOW *, int, int, chtype);
+int     mvwdeleteln(WINDOW *, int, int);
+int     mvwinsertln(WINDOW *, int, int);
+int     mvwinsrawch(WINDOW *, int, int, chtype);
+int     raw_output(bool);
+int     resize_term(int, int);
+WINDOW *resize_window(WINDOW *, int, int);
+int     waddrawch(WINDOW *, chtype);
+int     winsrawch(WINDOW *, chtype);
+char    wordchar(void);
+
+#ifdef PDC_WIDE
+wchar_t *slk_wlabel(int);
+#endif
+
+void    PDC_debug(const char *, ...);
+int     PDC_ungetch(int);
+int     PDC_set_blink(bool);
+int     PDC_set_line_color(short);
+void    PDC_set_title(const char *);
+
+int     PDC_clearclipboard(void);
+int     PDC_freeclipboard(char *);
+int     PDC_getclipboard(char **, long *);
+int     PDC_setclipboard(const char *, long);
+
+unsigned long PDC_get_input_fd(void);
+unsigned long PDC_get_key_modifiers(void);
+int     PDC_return_key_modifiers(bool);
+int     PDC_save_key_modifiers(bool);
+
+#ifdef XCURSES
+WINDOW *Xinitscr(int, char **);
+void    XCursesExit(void);
+int     sb_init(void);
+int     sb_set_horz(int, int, int);
+int     sb_set_vert(int, int, int);
+int     sb_get_horz(int *, int *, int *);
+int     sb_get_vert(int *, int *, int *);
+int     sb_refresh(void);
+#endif
+
+/*** Functions defined as macros ***/
+
+/* getch() and ungetch() conflict with some DOS libraries */
+
+#define getch()            wgetch(stdscr)
+#define ungetch(ch)        PDC_ungetch(ch)
+
+#define COLOR_PAIR(n)      (((chtype)(n) << PDC_COLOR_SHIFT) & A_COLOR)
+#define PAIR_NUMBER(n)     (((n) & A_COLOR) >> PDC_COLOR_SHIFT)
+
+/* These will _only_ work as macros */
+
+#define getbegyx(w, y, x)  (y = getbegy(w), x = getbegx(w))
+#define getmaxyx(w, y, x)  (y = getmaxy(w), x = getmaxx(w))
+#define getparyx(w, y, x)  (y = getpary(w), x = getparx(w))
+#define getyx(w, y, x)     (y = getcury(w), x = getcurx(w))
+
+#define getsyx(y, x)       { if (curscr->_leaveit) (y)=(x)=-1; \
+                             else getyx(curscr,(y),(x)); }
+
+#ifdef NCURSES_MOUSE_VERSION
+# define getmouse(x) nc_getmouse(x)
+#endif
+
+/* return codes from PDC_getclipboard() and PDC_setclipboard() calls */
+
+#define PDC_CLIP_SUCCESS         0
+#define PDC_CLIP_ACCESS_ERROR    1
+#define PDC_CLIP_EMPTY           2
+#define PDC_CLIP_MEMORY_ERROR    3
+
+/* PDCurses key modifier masks */
+
+#define PDC_KEY_MODIFIER_SHIFT   1
+#define PDC_KEY_MODIFIER_CONTROL 2
+#define PDC_KEY_MODIFIER_ALT     4
+#define PDC_KEY_MODIFIER_NUMLOCK 8
+
+#if defined(__cplusplus) || defined(__cplusplus__) || defined(__CPLUSPLUS)
+# undef bool
+}
+#endif
+
+#endif  /* __PDCURSES__ */
diff --git a/apps/lib/curses/pdcurses/include/panel.h b/apps/lib/curses/pdcurses/include/panel.h
new file mode 100644
index 0000000..1d7cace
--- /dev/null
+++ b/apps/lib/curses/pdcurses/include/panel.h
@@ -0,0 +1,58 @@
+/* Public Domain Curses */
+
+/* $Id: panel.h,v 1.19 2008/07/13 16:08:16 wmcbrine Exp $ */
+
+/*----------------------------------------------------------------------*
+ *                         Panels for PDCurses                          *
+ *----------------------------------------------------------------------*/
+
+#ifndef __PDCURSES_PANEL_H__
+#define __PDCURSES_PANEL_H__ 1
+
+#include <curses.h>
+
+#if defined(__cplusplus) || defined(__cplusplus__) || defined(__CPLUSPLUS)
+extern "C"
+{
+#endif
+
+typedef struct panelobs
+{
+    struct panelobs *above;
+    struct panel *pan;
+} PANELOBS;
+
+typedef struct panel
+{
+    WINDOW *win;
+    int wstarty;
+    int wendy;
+    int wstartx;
+    int wendx;
+    struct panel *below;
+    struct panel *above;
+    const void *user;
+    struct panelobs *obscure;
+} PANEL;
+
+int     bottom_panel(PANEL *pan);
+int     del_panel(PANEL *pan);
+int     hide_panel(PANEL *pan);
+int     move_panel(PANEL *pan, int starty, int startx);
+PANEL  *new_panel(WINDOW *win);
+PANEL  *panel_above(const PANEL *pan);
+PANEL  *panel_below(const PANEL *pan);
+int     panel_hidden(const PANEL *pan);
+const void *panel_userptr(const PANEL *pan);
+WINDOW *panel_window(const PANEL *pan);
+int     replace_panel(PANEL *pan, WINDOW *win);
+int     set_panel_userptr(PANEL *pan, const void *uptr);
+int     show_panel(PANEL *pan);
+int     top_panel(PANEL *pan);
+void    update_panels(void);
+
+#if defined(__cplusplus) || defined(__cplusplus__) || defined(__CPLUSPLUS)
+}
+#endif
+
+#endif /* __PDCURSES_PANEL_H__ */
diff --git a/apps/lib/curses/pdcurses/pdcurses/Makefile b/apps/lib/curses/pdcurses/pdcurses/Makefile
new file mode 100644
index 0000000..5bae5c6
--- /dev/null
+++ b/apps/lib/curses/pdcurses/pdcurses/Makefile
@@ -0,0 +1,39 @@
+app-$(CONFIG_APP_LIB_PANEL) += panel.o
+app-y += addch.o
+app-y += move.o
+app-y += overlay.o
+app-y += refresh.o
+app-y += terminfo.o
+app-y += window.o
+app-y += util.o
+app-y += inopts.o
+app-y += addstr.o
+app-y += keyname.o
+app-y += instr.o
+app-y += clear.o
+app-y += addchstr.o
+app-y += kernel.o
+app-y += pad.o
+app-y += insstr.o
+app-y += border.o
+app-y += getyx.o
+app-y += getstr.o
+app-y += getch.o
+app-y += termattr.o
+app-y += outopts.o
+app-y += color.o
+app-y += deleteln.o
+app-y += initscr.o
+app-y += slk.o
+app-y += delch.o
+app-y += touch.o
+app-y += mouse.o
+app-y += scanw.o
+app-y += scroll.o
+app-y += printw.o
+app-y += bkgd.o
+app-y += inch.o
+app-y += attr.o
+app-y += insch.o
+app-y += inchstr.o
+app-y += beep.o
diff --git a/apps/lib/curses/pdcurses/pdcurses/README b/apps/lib/curses/pdcurses/pdcurses/README
new file mode 100644
index 0000000..bef1c4c
--- /dev/null
+++ b/apps/lib/curses/pdcurses/pdcurses/README
@@ -0,0 +1,25 @@
+PDCurses Portable Core
+======================
+
+This directory contains core PDCurses source code files common to all 
+platforms.
+
+
+Building
+--------
+
+These modules are built by the platform-specific makefiles, in the 
+platform directories.
+
+
+Distribution Status
+-------------------
+
+The files in this directory are released to the Public Domain.
+
+
+Acknowledgements
+----------------
+
+The panel library was originally provided by
+Warren Tucker <wht@n4hgf.mt-park.ga.us>
diff --git a/apps/lib/curses/pdcurses/pdcurses/addch.c b/apps/lib/curses/pdcurses/pdcurses/addch.c
new file mode 100644
index 0000000..586d1a7
--- /dev/null
+++ b/apps/lib/curses/pdcurses/pdcurses/addch.c
@@ -0,0 +1,408 @@
+/* Public Domain Curses */
+
+#include <curspriv.h>
+
+RCSID("$Id: addch.c,v 1.54 2008/07/13 16:08:17 wmcbrine Exp $")
+
+/*man-start**************************************************************
+
+  Name:                                                         addch
+
+  Synopsis:
+        int addch(const chtype ch);
+        int waddch(WINDOW *win, const chtype ch);
+        int mvaddch(int y, int x, const chtype ch);
+        int mvwaddch(WINDOW *win, int y, int x, const chtype ch);
+        int echochar(const chtype ch);
+        int wechochar(WINDOW *win, const chtype ch);
+
+        int addrawch(chtype ch);
+        int waddrawch(WINDOW *win, chtype ch);
+        int mvaddrawch(int y, int x, chtype ch);
+        int mvwaddrawch(WINDOW *win, int y, int x, chtype ch);
+
+        int add_wch(const cchar_t *wch);
+        int wadd_wch(WINDOW *win, const cchar_t *wch);
+        int mvadd_wch(int y, int x, const cchar_t *wch);
+        int mvwadd_wch(WINDOW *win, int y, int x, const cchar_t *wch);
+        int echo_wchar(const cchar_t *wch);
+        int wecho_wchar(WINDOW *win, const cchar_t *wch);
+
+  Description:
+        addch() adds the chtype ch to the default window (stdscr) at the
+        current cursor position, and advances the cursor. Note that
+        chtypes can convey both text (a single character) and
+        attributes, including a color pair. add_wch() is the wide-
+        character version of this function, taking a pointer to a
+        cchar_t instead of a chtype.
+
+        waddch() is like addch(), but also lets you specify the window.
+        (This is in fact the core output routine.) wadd_wch() is the
+        wide version.
+
+        mvaddch() moves the cursor to the specified (y, x) position, and
+        adds ch to stdscr. mvadd_wch() is the wide version.
+
+        mvwaddch() moves the cursor to the specified position and adds 
+        ch to the specified window. mvwadd_wch() is the wide version.
+
+        echochar() adds ch to stdscr at the current cursor position and 
+        calls refresh(). echo_wchar() is the wide version.
+
+        wechochar() adds ch to the specified window and calls 
+        wrefresh(). wecho_wchar() is the wide version.
+
+        addrawch(), waddrawch(), mvaddrawch() and mvwaddrawch() are
+        PDCurses-specific wrappers for addch() etc. that disable the 
+        translation of control characters.
+
+        The following applies to all these functions:
+
+        If the cursor moves on to the right margin, an automatic newline 
+        is performed.  If scrollok is enabled, and a character is added 
+        to the bottom right corner of the window, the scrolling region 
+        will be scrolled up one line.  If scrolling is not allowed, ERR 
+        will be returned.
+
+        If ch is a tab, newline, or backspace, the cursor will be moved 
+        appropriately within the window.  If ch is a newline, the 
+        clrtoeol routine is called before the cursor is moved to the 
+        beginning of the next line.  If newline mapping is off, the 
+        cursor will be moved to the next line, but the x coordinate will 
+        be unchanged.  If ch is a tab the cursor is moved to the next 
+        tab position within the window.  If ch is another control 
+        character, it will be drawn in the ^X notation.  Calling the 
+        inch() routine after adding a control character returns the 
+        representation of the control character, not the control 
+        character.
+
+        Video attributes can be combined with a character by ORing them 
+        into the parameter. Text, including attributes, can be copied 
+        from one place to another by using inch() and addch().
+
+        Note that in PDCurses, for now, a cchar_t and a chtype are the
+        same. The text field is 16 bits wide, and is treated as Unicode
+        (UCS-2) when PDCurses is built with wide-character support
+        (define PDC_WIDE). So, in functions that take a chtype, like
+        addch(), both the wide and narrow versions will handle Unicode.
+        But for portability, you should use the wide functions.
+
+  Return Value:
+        All functions return OK on success and ERR on error.
+
+  Portability                                X/Open    BSD    SYS V
+        addch                                   Y       Y       Y
+        waddch                                  Y       Y       Y
+        mvaddch                                 Y       Y       Y
+        mvwaddch                                Y       Y       Y
+        echochar                                Y       -      3.0
+        wechochar                               Y       -      3.0
+        addrawch                                -       -       -
+        waddrawch                               -       -       -
+        mvaddrawch                              -       -       -
+        mvwaddrawch                             -       -       -
+        add_wch                                 Y
+        wadd_wch                                Y
+        mvadd_wch                               Y
+        mvwadd_wch                              Y
+        echo_wchar                              Y
+        wecho_wchar                             Y
+
+**man-end****************************************************************/
+
+int waddch(WINDOW *win, const chtype ch)
+{
+    int x, y;
+    chtype text, attr;
+    bool xlat;
+
+    PDC_LOG(("waddch() - called: win=%p ch=%x (text=%c attr=0x%x)\n",
+             win, ch, ch & A_CHARTEXT, ch & A_ATTRIBUTES));
+
+    if (!win)
+        return ERR;
+
+    x = win->_curx;
+    y = win->_cury;
+
+    if (y > win->_maxy || x > win->_maxx || y < 0 || x < 0)
+        return ERR;
+
+    xlat = !SP->raw_out && !(ch & A_ALTCHARSET);
+    text = ch & A_CHARTEXT;
+    attr = ch & A_ATTRIBUTES;
+
+    if (xlat && (text < ' ' || text == 0x7f))
+    {
+        int x2;
+
+        switch (text)
+        {
+        case '\t':
+            for (x2 = ((x / TABSIZE) + 1) * TABSIZE; x < x2; x++)
+            {
+                if (waddch(win, attr | ' ') == ERR)
+                    return ERR;
+
+                /* if tab to next line, exit the loop */
+
+                if (!win->_curx)
+                    break;
+            }
+            return OK;
+
+        case '\n':
+            /* if lf -> crlf */
+
+            if (!SP->raw_out)
+                x = 0;
+
+            wclrtoeol(win);
+
+            if (++y > win->_bmarg)
+            {
+                y--;
+
+                if (wscrl(win, 1) == ERR)
+                    return ERR;
+            }
+
+            break;
+
+        case '\b':
+            /* don't back over left margin */
+
+            if (--x < 0)
+        case '\r':
+                x = 0;
+
+            break;
+
+        case 0x7f:
+            if (waddch(win, attr | '^') == ERR)
+                return ERR;
+
+            return waddch(win, attr | '?');
+
+        default:
+            /* handle control chars */
+
+            if (waddch(win, attr | '^') == ERR)
+                return ERR;
+
+            return waddch(win, ch + '@');
+        }
+    }
+    else
+    {
+        /* If the incoming character doesn't have its own attribute,
+           then use the current attributes for the window. If it has
+           attributes but not a color component, OR the attributes to
+           the current attributes for the window. If it has a color
+           component, use the attributes solely from the incoming
+           character. */
+
+        if (!(attr & A_COLOR))
+            attr |= win->_attrs;
+
+        /* wrs (4/10/93): Apply the same sort of logic for the window 
+           background, in that it only takes precedence if other color 
+           attributes are not there and that the background character 
+           will only print if the printing character is blank. */
+
+        if (!(attr & A_COLOR))
+            attr |= win->_bkgd & A_ATTRIBUTES;
+        else
+            attr |= win->_bkgd & (A_ATTRIBUTES ^ A_COLOR);
+
+        if (text == ' ')
+            text = win->_bkgd & A_CHARTEXT;
+
+        /* Add the attribute back into the character. */
+
+        text |= attr;
+
+        /* Only change _firstch/_lastch if the character to be added is
+           different from the character/attribute that is already in
+           that position in the window. */
+
+        if (win->_y[y][x] != text)
+        {
+            if (win->_firstch[y] == _NO_CHANGE)
+                win->_firstch[y] = win->_lastch[y] = x;
+            else
+                if (x < win->_firstch[y])
+                    win->_firstch[y] = x;
+                else
+                    if (x > win->_lastch[y])
+                        win->_lastch[y] = x;
+
+            win->_y[y][x] = text;
+        }
+
+        if (++x >= win->_maxx)
+        {
+            /* wrap around test */
+
+            x = 0;
+
+            if (++y > win->_bmarg)
+            {
+                y--;
+
+                if (wscrl(win, 1) == ERR)
+                {
+                    PDC_sync(win);
+                    return ERR;
+                }
+            }
+        }
+    }
+
+    win->_curx = x;
+    win->_cury = y;
+
+    if (win->_immed)
+        wrefresh(win);
+    if (win->_sync)
+        wsyncup(win);
+
+    return OK;
+}
+
+int addch(const chtype ch)
+{
+    PDC_LOG(("addch() - called: ch=%x\n", ch));
+
+    return waddch(stdscr, ch);
+}
+
+int mvaddch(int y, int x, const chtype ch)
+{
+    PDC_LOG(("mvaddch() - called: y=%d x=%d ch=%x\n", y, x, ch));
+
+    if (move(y,x) == ERR)
+        return ERR;
+
+    return waddch(stdscr, ch);
+}
+
+int mvwaddch(WINDOW *win, int y, int x, const chtype ch)
+{
+    PDC_LOG(("mvwaddch() - called: win=%p y=%d x=%d ch=%d\n", win, y, x, ch));
+
+    if (wmove(win, y, x) == ERR)
+        return ERR;
+
+    return waddch(win, ch);
+}
+
+int echochar(const chtype ch)
+{
+    PDC_LOG(("echochar() - called: ch=%x\n", ch));
+
+    return wechochar(stdscr, ch);
+}
+
+int wechochar(WINDOW *win, const chtype ch)
+{
+    PDC_LOG(("wechochar() - called: win=%p ch=%x\n", win, ch));
+
+    if (waddch(win, ch) == ERR)
+        return ERR;
+
+    return wrefresh(win);
+}
+
+int waddrawch(WINDOW *win, chtype ch)
+{
+    PDC_LOG(("waddrawch() - called: win=%p ch=%x (text=%c attr=0x%x)\n",
+             win, ch, ch & A_CHARTEXT, ch & A_ATTRIBUTES));
+
+    if ((ch & A_CHARTEXT) < ' ' || (ch & A_CHARTEXT) == 0x7f)
+        ch |= A_ALTCHARSET;
+
+    return waddch(win, ch);
+}
+
+int addrawch(chtype ch)
+{
+    PDC_LOG(("addrawch() - called: ch=%x\n", ch));
+
+    return waddrawch(stdscr, ch);
+}
+
+int mvaddrawch(int y, int x, chtype ch)
+{
+    PDC_LOG(("mvaddrawch() - called: y=%d x=%d ch=%d\n", y, x, ch));
+
+    if (move(y, x) == ERR)
+        return ERR;
+
+    return waddrawch(stdscr, ch);
+}
+
+int mvwaddrawch(WINDOW *win, int y, int x, chtype ch)
+{
+    PDC_LOG(("mvwaddrawch() - called: win=%p y=%d x=%d ch=%d\n",
+             win, y, x, ch));
+
+    if (wmove(win, y, x) == ERR)
+        return ERR;
+
+    return waddrawch(win, ch);
+}
+
+#ifdef PDC_WIDE
+int wadd_wch(WINDOW *win, const cchar_t *wch)
+{
+    PDC_LOG(("wadd_wch() - called: win=%p wch=%x\n", win, *wch));
+
+    return wch ? waddch(win, *wch) : ERR;
+}
+
+int add_wch(const cchar_t *wch)
+{
+    PDC_LOG(("add_wch() - called: wch=%x\n", *wch));
+
+    return wadd_wch(stdscr, wch);
+}
+
+int mvadd_wch(int y, int x, const cchar_t *wch)
+{
+    PDC_LOG(("mvaddch() - called: y=%d x=%d wch=%x\n", y, x, *wch));
+
+    if (move(y,x) == ERR)
+        return ERR;
+
+    return wadd_wch(stdscr, wch);
+}
+
+int mvwadd_wch(WINDOW *win, int y, int x, const cchar_t *wch)
+{
+    PDC_LOG(("mvwaddch() - called: win=%p y=%d x=%d wch=%d\n",
+             win, y, x, *wch));
+
+    if (wmove(win, y, x) == ERR)
+        return ERR;
+
+    return wadd_wch(win, wch);
+}
+
+int echo_wchar(const cchar_t *wch)
+{
+    PDC_LOG(("echo_wchar() - called: wch=%x\n", *wch));
+
+    return wecho_wchar(stdscr, wch);
+}
+
+int wecho_wchar(WINDOW *win, const cchar_t *wch)
+{
+    PDC_LOG(("wecho_wchar() - called: win=%p wch=%x\n", win, *wch));
+
+    if (!wch || (wadd_wch(win, wch) == ERR))
+        return ERR;
+
+    return wrefresh(win);
+}
+#endif
diff --git a/apps/lib/curses/pdcurses/pdcurses/addchstr.c b/apps/lib/curses/pdcurses/pdcurses/addchstr.c
new file mode 100644
index 0000000..0eea85a
--- /dev/null
+++ b/apps/lib/curses/pdcurses/pdcurses/addchstr.c
@@ -0,0 +1,242 @@
+/* Public Domain Curses */
+
+#include <curspriv.h>
+
+RCSID("$Id: addchstr.c,v 1.43 2008/07/13 16:08:17 wmcbrine Exp $")
+
+/*man-start**************************************************************
+
+  Name:                                                         addchstr
+
+  Synopsis:
+        int addchstr(const chtype *ch);
+        int addchnstr(const chtype *ch, int n);
+        int waddchstr(WINDOW *win, const chtype *ch);
+        int waddchnstr(WINDOW *win, const chtype *ch, int n);
+        int mvaddchstr(int y, int x, const chtype *ch);
+        int mvaddchnstr(int y, int x, const chtype *ch, int n);
+        int mvwaddchstr(WINDOW *, int y, int x, const chtype *ch);
+        int mvwaddchnstr(WINDOW *, int y, int x, const chtype *ch, int n);
+
+        int add_wchstr(const cchar_t *wch);
+        int add_wchnstr(const cchar_t *wch, int n);
+        int wadd_wchstr(WINDOW *win, const cchar_t *wch);
+        int wadd_wchnstr(WINDOW *win, const cchar_t *wch, int n);
+        int mvadd_wchstr(int y, int x, const cchar_t *wch);
+        int mvadd_wchnstr(int y, int x, const cchar_t *wch, int n);
+        int mvwadd_wchstr(WINDOW *win, int y, int x, const cchar_t *wch);
+        int mvwadd_wchnstr(WINDOW *win, int y, int x, const cchar_t *wch,
+                int n);
+
+  Description:
+        These routines write a chtype or cchar_t string directly into 
+        the window structure, starting at the current or specified 
+        position. The four routines with n as the last argument copy at 
+        most n elements, but no more than will fit on the line. If n = 
+        -1 then the whole string is copied, up to the maximum number 
+        that will fit on the line.
+
+        The cursor position is not advanced. These routines do not check 
+        for newline or other special characters, nor does any line 
+        wrapping occur.
+
+  Return Value:
+        All functions return OK or ERR.
+
+  Portability                                X/Open    BSD    SYS V
+        addchstr                                Y       -      4.0
+        waddchstr                               Y       -      4.0
+        mvaddchstr                              Y       -      4.0
+        mvwaddchstr                             Y       -      4.0
+        addchnstr                               Y       -      4.0
+        waddchnstr                              Y       -      4.0
+        mvaddchnstr                             Y       -      4.0
+        mvwaddchnstr                            Y       -      4.0
+        add_wchstr                              Y
+        wadd_wchstr                             Y
+        mvadd_wchstr                            Y
+        mvwadd_wchstr                           Y
+        add_wchnstr                             Y
+        wadd_wchnstr                            Y
+        mvadd_wchnstr                           Y
+        mvwadd_wchnstr                          Y
+
+**man-end****************************************************************/
+
+#include <string.h>
+
+int waddchnstr(WINDOW *win, const chtype *ch, int n)
+{
+    int y, x, maxx, minx;
+    chtype *ptr;
+
+    PDC_LOG(("waddchnstr() - called: win=%p n=%d\n", win, n));
+
+    if (!win || !ch || !n || n < -1)
+        return ERR;
+
+    x = win->_curx;
+    y = win->_cury;
+    ptr = &(win->_y[y][x]);
+
+    if (n == -1 || n > win->_maxx - x)
+        n = win->_maxx - x;
+
+    minx = win->_firstch[y];
+    maxx = win->_lastch[y];
+
+    for (; n && *ch; n--, x++, ptr++, ch++)
+    {
+        if (*ptr != *ch)
+        {
+            if (x < minx || minx == _NO_CHANGE)
+                minx = x;
+
+            if (x > maxx)
+                maxx = x;
+
+            PDC_LOG(("y %d x %d minx %d maxx %d *ptr %x *ch"
+                     " %x firstch: %d lastch: %d\n",
+                     y, x, minx, maxx, *ptr, *ch, 
+                     win->_firstch[y], win->_lastch[y]));
+
+            *ptr = *ch;
+        }
+    }
+
+    win->_firstch[y] = minx;
+    win->_lastch[y] = maxx;
+
+    return OK;
+}
+
+int addchstr(const chtype *ch)
+{
+    PDC_LOG(("addchstr() - called\n"));
+
+    return waddchnstr(stdscr, ch, -1);
+}
+
+int addchnstr(const chtype *ch, int n)
+{
+    PDC_LOG(("addchnstr() - called\n"));
+
+    return waddchnstr(stdscr, ch, n);
+}
+
+int waddchstr(WINDOW *win, const chtype *ch)
+{
+    PDC_LOG(("waddchstr() - called: win=%p\n", win));
+
+    return waddchnstr(win, ch, -1);
+}
+
+int mvaddchstr(int y, int x, const chtype *ch)
+{
+    PDC_LOG(("mvaddchstr() - called: y %d x %d\n", y, x));
+
+    if (move(y, x) == ERR)
+        return ERR;
+
+    return waddchnstr(stdscr, ch, -1);
+}
+
+int mvaddchnstr(int y, int x, const chtype *ch, int n)
+{
+    PDC_LOG(("mvaddchnstr() - called: y %d x %d n %d\n", y, x, n));
+
+    if (move(y, x) == ERR)
+        return ERR;
+
+    return waddchnstr(stdscr, ch, n);
+}
+
+int mvwaddchstr(WINDOW *win, int y, int x, const chtype *ch)
+{
+    PDC_LOG(("mvwaddchstr() - called:\n"));
+
+    if (wmove(win, y, x) == ERR)
+        return ERR;
+
+    return waddchnstr(win, ch, -1);
+}
+
+int mvwaddchnstr(WINDOW *win, int y, int x, const chtype *ch, int n)
+{
+    PDC_LOG(("mvwaddchnstr() - called: y %d x %d n %d \n", y, x, n));
+
+    if (wmove(win, y, x) == ERR)
+        return ERR;
+
+    return waddchnstr(win, ch, n);
+}
+
+#ifdef PDC_WIDE
+int wadd_wchnstr(WINDOW *win, const cchar_t *wch, int n)
+{
+    PDC_LOG(("wadd_wchnstr() - called: win=%p n=%d\n", win, n));
+
+    return waddchnstr(win, wch, n);
+}
+
+int add_wchstr(const cchar_t *wch)
+{
+    PDC_LOG(("add_wchstr() - called\n"));
+
+    return wadd_wchnstr(stdscr, wch, -1);
+}
+
+int add_wchnstr(const cchar_t *wch, int n)
+{
+    PDC_LOG(("add_wchnstr() - called\n"));
+
+    return wadd_wchnstr(stdscr, wch, n);
+}
+
+int wadd_wchstr(WINDOW *win, const cchar_t *wch)
+{
+    PDC_LOG(("wadd_wchstr() - called: win=%p\n", win));
+
+    return wadd_wchnstr(win, wch, -1);
+}
+
+int mvadd_wchstr(int y, int x, const cchar_t *wch)
+{
+    PDC_LOG(("mvadd_wchstr() - called: y %d x %d\n", y, x));
+
+    if (move(y, x) == ERR)
+        return ERR;
+
+    return wadd_wchnstr(stdscr, wch, -1);
+}
+
+int mvadd_wchnstr(int y, int x, const cchar_t *wch, int n)
+{
+    PDC_LOG(("mvadd_wchnstr() - called: y %d x %d n %d\n", y, x, n));
+
+    if (move(y, x) == ERR)
+        return ERR;
+
+    return wadd_wchnstr(stdscr, wch, n);
+}
+
+int mvwadd_wchstr(WINDOW *win, int y, int x, const cchar_t *wch)
+{
+    PDC_LOG(("mvwadd_wchstr() - called:\n"));
+
+    if (wmove(win, y, x) == ERR)
+        return ERR;
+
+    return wadd_wchnstr(win, wch, -1);
+}
+
+int mvwadd_wchnstr(WINDOW *win, int y, int x, const cchar_t *wch, int n)
+{
+    PDC_LOG(("mvwadd_wchnstr() - called: y %d x %d n %d \n", y, x, n));
+
+    if (wmove(win, y, x) == ERR)
+        return ERR;
+
+    return wadd_wchnstr(win, wch, n);
+}
+#endif
diff --git a/apps/lib/curses/pdcurses/pdcurses/addstr.c b/apps/lib/curses/pdcurses/pdcurses/addstr.c
new file mode 100644
index 0000000..ca19fd0
--- /dev/null
+++ b/apps/lib/curses/pdcurses/pdcurses/addstr.c
@@ -0,0 +1,237 @@
+/* Public Domain Curses */
+
+#include <curspriv.h>
+
+RCSID("$Id: addstr.c,v 1.44 2008/07/13 16:08:17 wmcbrine Exp $")
+
+/*man-start**************************************************************
+
+  Name:                                                         addstr
+
+  Synopsis:
+        int addstr(const char *str);
+        int addnstr(const char *str, int n);
+        int waddstr(WINDOW *win, const char *str);
+        int waddnstr(WINDOW *win, const char *str, int n);
+        int mvaddstr(int y, int x, const char *str);
+        int mvaddnstr(int y, int x, const char *str, int n);
+        int mvwaddstr(WINDOW *win, int y, int x, const char *str);
+        int mvwaddnstr(WINDOW *win, int y, int x, const char *str, int n);
+
+        int addwstr(const wchar_t *wstr);
+        int addnwstr(const wchar_t *wstr, int n);
+        int waddwstr(WINDOW *win, const wchar_t *wstr);
+        int waddnwstr(WINDOW *win, const wchar_t *wstr, int n);
+        int mvaddwstr(int y, int x, const wchar_t *wstr);
+        int mvaddnwstr(int y, int x, const wchar_t *wstr, int n);
+        int mvwaddwstr(WINDOW *win, int y, int x, const wchar_t *wstr);
+        int mvwaddnwstr(WINDOW *win, int y, int x, const wchar_t *wstr, int n);
+
+  Description:
+        These routines write all the characters of the null-terminated
+        string str or wide-character string wstr to the given window.
+        The functionality is similar to calling waddch() once for each
+        character in the string; except that, when PDCurses is built
+        with wide-character support enabled, the narrow-character
+        functions treat the string as a multibyte string in the current
+        locale, and convert it. The routines with n as the last
+        argument write at most n characters; if n is negative, then the
+        entire string will be added.
+
+  Return Value:
+        All functions return OK or ERR.
+
+  Portability                                X/Open    BSD    SYS V
+        addstr                                  Y       Y       Y
+        waddstr                                 Y       Y       Y
+        mvaddstr                                Y       Y       Y
+        mvwaddstr                               Y       Y       Y
+        addnstr                                 Y       -      4.0
+        waddnstr                                Y       -      4.0
+        mvaddnstr                               Y       -      4.0
+        mvwaddnstr                              Y       -      4.0
+        addwstr                                 Y
+        waddwstr                                Y
+        mvaddwstr                               Y
+        mvwaddwstr                              Y
+        addnwstr                                Y
+        waddnwstr                               Y
+        mvaddnwstr                              Y
+        mvwaddnwstr                             Y
+
+**man-end****************************************************************/
+
+int waddnstr(WINDOW *win, const char *str, int n)
+{
+    int i = 0;
+
+    PDC_LOG(("waddnstr() - called: string=\"%s\" n %d \n", str, n));
+
+    if (!win || !str)
+        return ERR;
+
+    while (str[i] && (i < n || n < 0))
+    {
+#ifdef PDC_WIDE
+        wchar_t wch;
+        int retval = PDC_mbtowc(&wch, str + i, n >= 0 ? n - i : 6);
+
+        if (retval <= 0)
+            return OK;
+
+        i += retval;
+#else
+        chtype wch = (unsigned char)(str[i++]);
+#endif
+        if (waddch(win, wch) == ERR)
+            return ERR;
+    }
+
+    return OK;
+}
+
+int addstr(const char *str)
+{
+    PDC_LOG(("addstr() - called: string=\"%s\"\n", str));
+
+    return waddnstr(stdscr, str, -1);
+}
+
+int addnstr(const char *str, int n)
+{
+    PDC_LOG(("addnstr() - called: string=\"%s\" n %d \n", str, n));
+
+    return waddnstr(stdscr, str, n);
+}
+
+int waddstr(WINDOW *win, const char *str)
+{
+    PDC_LOG(("waddstr() - called: string=\"%s\"\n", str));
+
+    return waddnstr(win, str, -1);
+}
+
+int mvaddstr(int y, int x, const char *str)
+{
+    PDC_LOG(("mvaddstr() - called: y %d x %d string=\"%s\"\n", y, x, str));
+
+    if (move(y, x) == ERR)
+        return ERR;
+
+    return waddnstr(stdscr, str, -1);
+}
+
+int mvaddnstr(int y, int x, const char *str, int n)
+{
+    PDC_LOG(("mvaddnstr() - called: y %d x %d string=\"%s\" n %d \n",
+             y, x, str, n));
+
+    if (move(y, x) == ERR)
+        return ERR;
+
+    return waddnstr(stdscr, str, n);
+}
+
+int mvwaddstr(WINDOW *win, int y, int x, const char *str)
+{
+    PDC_LOG(("mvwaddstr() - called: string=\"%s\"\n", str));
+
+    if (wmove(win, y, x) == ERR)
+        return ERR;
+
+    return waddnstr(win, str, -1);
+}
+
+int mvwaddnstr(WINDOW *win, int y, int x, const char *str, int n)
+{
+    PDC_LOG(("mvwaddnstr() - called: y %d x %d string=\"%s\" n %d \n",
+             y, x, str, n));
+
+    if (wmove(win, y, x) == ERR)
+        return ERR;
+
+    return waddnstr(win, str, n);
+}
+
+#ifdef PDC_WIDE
+int waddnwstr(WINDOW *win, const wchar_t *wstr, int n)
+{
+    int i = 0;
+
+    PDC_LOG(("waddnwstr() - called\n"));
+
+    if (!win || !wstr)
+        return ERR;
+
+    while (wstr[i] && (i < n || n < 0))
+    {
+        chtype wch = wstr[i++];
+
+        if (waddch(win, wch) == ERR)
+            return ERR;
+    }
+
+    return OK;
+}
+
+int addwstr(const wchar_t *wstr)
+{
+    PDC_LOG(("addwstr() - called\n"));
+
+    return waddnwstr(stdscr, wstr, -1);
+}
+
+int addnwstr(const wchar_t *wstr, int n)
+{
+    PDC_LOG(("addnwstr() - called\n"));
+
+    return waddnwstr(stdscr, wstr, n);
+}
+
+int waddwstr(WINDOW *win, const wchar_t *wstr)
+{
+    PDC_LOG(("waddwstr() - called\n"));
+
+    return waddnwstr(win, wstr, -1);
+}
+
+int mvaddwstr(int y, int x, const wchar_t *wstr)
+{
+    PDC_LOG(("mvaddstr() - called\n"));
+
+    if (move(y, x) == ERR)
+        return ERR;
+
+    return waddnwstr(stdscr, wstr, -1);
+}
+
+int mvaddnwstr(int y, int x, const wchar_t *wstr, int n)
+{
+    PDC_LOG(("mvaddnstr() - called\n"));
+
+    if (move(y, x) == ERR)
+        return ERR;
+
+    return waddnwstr(stdscr, wstr, n);
+}
+
+int mvwaddwstr(WINDOW *win, int y, int x, const wchar_t *wstr)
+{
+    PDC_LOG(("mvwaddstr() - called\n"));
+
+    if (wmove(win, y, x) == ERR)
+        return ERR;
+
+    return waddnwstr(win, wstr, -1);
+}
+
+int mvwaddnwstr(WINDOW *win, int y, int x, const wchar_t *wstr, int n)
+{
+    PDC_LOG(("mvwaddnstr() - called\n"));
+
+    if (wmove(win, y, x) == ERR)
+        return ERR;
+
+    return waddnwstr(win, wstr, n);
+}
+#endif
diff --git a/apps/lib/curses/pdcurses/pdcurses/attr.c b/apps/lib/curses/pdcurses/pdcurses/attr.c
new file mode 100644
index 0000000..532384b
--- /dev/null
+++ b/apps/lib/curses/pdcurses/pdcurses/attr.c
@@ -0,0 +1,349 @@
+/* Public Domain Curses */
+
+#include <curspriv.h>
+
+RCSID("$Id: attr.c,v 1.41 2008/07/13 16:08:17 wmcbrine Exp $")
+
+/*man-start**************************************************************
+
+  Name:                                                         attr
+
+  Synopsis:
+        int attroff(chtype attrs);
+        int wattroff(WINDOW *win, chtype attrs);
+        int attron(chtype attrs);
+        int wattron(WINDOW *win, chtype attrs);
+        int attrset(chtype attrs);
+        int wattrset(WINDOW *win, chtype attrs);
+        int standend(void);
+        int wstandend(WINDOW *win);
+        int standout(void);
+        int wstandout(WINDOW *win);
+
+        int color_set(short color_pair, void *opts);
+        int wcolor_set(WINDOW *win, short color_pair, void *opts);
+
+        int attr_get(attr_t *attrs, short *color_pair, void *opts);
+        int attr_off(attr_t attrs, void *opts);
+        int attr_on(attr_t attrs, void *opts);
+        int attr_set(attr_t attrs, short color_pair, void *opts);
+        int wattr_get(WINDOW *win, attr_t *attrs, short *color_pair,
+                void *opts);
+        int wattr_off(WINDOW *win, attr_t attrs, void *opts);
+        int wattr_on(WINDOW *win, attr_t attrs, void *opts);
+        int wattr_set(WINDOW *win, attr_t attrs, short color_pair,
+                void *opts);
+
+        int chgat(int n, attr_t attr, short color, const void *opts);
+        int mvchgat(int y, int x, int n, attr_t attr, short color,
+                const void *opts);
+        int mvwchgat(WINDOW *win, int y, int x, int n, attr_t attr,
+                short color, const void *opts);
+        int wchgat(WINDOW *win, int n, attr_t attr, short color,
+                const void *opts);
+
+        chtype getattrs(WINDOW *win);
+
+  Description:
+        These functions manipulate the current attributes and/or colors 
+        of the named window.  These attributes can be any combination 
+        of A_STANDOUT, A_REVERSE, A_BOLD, A_DIM, A_BLINK, A_UNDERLINE.
+
+        These constants are defined in <curses.h> and can be combined
+        with the bitwise-OR operator (|).
+
+        The current attributes of a window are applied to all chtypes 
+        that are written into the window with waddch(). Attributes are 
+        a property of the chtype, and move with the character through 
+        any scrolling or insert/delete operations.
+
+        attrset() sets the current attributes of the given window to 
+        attrs. attroff() turns off the named attributes without 
+        affecting any other attributes; attron() turns them on. 
+        color_set() sets the window color to the value of color_pair.
+
+        standout() is the same as attron(A_STANDOUT). standend() is the 
+        same as attrset(A_NORMAL); that is, it turns off all attributes.
+
+  Return Value:
+        All functions return OK on success and ERR on error.
+
+  Portability                                X/Open    BSD    SYS V
+        attroff                                 Y       Y       Y
+        wattroff                                Y       Y       Y
+        attron                                  Y       Y       Y
+        wattron                                 Y       Y       Y
+        attrset                                 Y       Y       Y
+        wattrset                                Y       Y       Y
+        standend                                Y       Y       Y
+        wstandend                               Y       Y       Y
+        standout                                Y       Y       Y
+        wstandout                               Y       Y       Y
+        color_set                               Y
+        wcolor_set                              Y
+        attr_get                                Y
+        wattr_get                               Y
+        attr_on                                 Y
+        wattr_on                                Y
+        attr_off                                Y
+        wattr_off                               Y
+        attr_set                                Y
+        wattr_set                               Y
+        chgat                                   Y
+        wchgat                                  Y
+        mvchgat                                 Y
+        mvwchgat                                Y
+        getattrs                                -
+
+**man-end****************************************************************/
+
+int wattroff(WINDOW *win, chtype attrs)
+{
+    PDC_LOG(("wattroff() - called\n"));
+
+    if (!win)
+        return ERR;
+
+    win->_attrs &= (~attrs & A_ATTRIBUTES);
+
+    return OK;
+}
+
+int attroff(chtype attrs)
+{
+    PDC_LOG(("attroff() - called\n"));
+
+    return wattroff(stdscr, attrs);
+}
+
+int wattron(WINDOW *win, chtype attrs)
+{
+    chtype newcolr, oldcolr, newattr, oldattr;
+
+    PDC_LOG(("wattron() - called\n"));
+
+    if (!win)
+        return ERR;
+
+    if ((win->_attrs & A_COLOR) && (attrs & A_COLOR)) 
+    {
+        oldcolr = win->_attrs & A_COLOR;
+        oldattr = win->_attrs ^ oldcolr;
+        newcolr = attrs & A_COLOR;
+        newattr = (attrs & A_ATTRIBUTES) ^ newcolr;
+        newattr |= oldattr;
+        win->_attrs = newattr | newcolr;
+    }
+    else
+        win->_attrs |= (attrs & A_ATTRIBUTES);
+
+    return OK;
+}
+
+int attron(chtype attrs)
+{
+    PDC_LOG(("attron() - called\n"));
+
+    return wattron(stdscr, attrs);
+}
+
+int wattrset(WINDOW *win, chtype attrs)
+{
+    PDC_LOG(("wattrset() - called\n"));
+
+    if (!win)
+        return ERR;
+
+    win->_attrs = attrs & A_ATTRIBUTES;
+
+    return OK;
+}
+
+int attrset(chtype attrs)
+{
+    PDC_LOG(("attrset() - called\n"));
+
+    return wattrset(stdscr, attrs);
+}
+
+int standend(void)
+{
+    PDC_LOG(("standend() - called\n"));
+
+    return wattrset(stdscr, A_NORMAL);
+}
+
+int standout(void)
+{
+    PDC_LOG(("standout() - called\n"));
+
+    return wattrset(stdscr, A_STANDOUT);
+}
+
+int wstandend(WINDOW *win)
+{
+    PDC_LOG(("wstandend() - called\n"));
+
+    return wattrset(win, A_NORMAL);
+}
+
+int wstandout(WINDOW *win)
+{
+    PDC_LOG(("wstandout() - called\n"));
+
+    return wattrset(win, A_STANDOUT);
+}
+
+chtype getattrs(WINDOW *win)
+{
+    return win ? win->_attrs : 0;
+}
+
+int wcolor_set(WINDOW *win, short color_pair, void *opts)
+{
+    PDC_LOG(("wcolor_set() - called\n"));
+
+    if (!win)
+        return ERR;
+
+    win->_attrs = (win->_attrs & ~A_COLOR) | COLOR_PAIR(color_pair);
+
+    return OK;
+}
+
+int color_set(short color_pair, void *opts)
+{
+    PDC_LOG(("color_set() - called\n"));
+
+    return wcolor_set(stdscr, color_pair, opts);
+}
+
+int wattr_get(WINDOW *win, attr_t *attrs, short *color_pair, void *opts)
+{
+    PDC_LOG(("wattr_get() - called\n"));
+
+    if (!win)
+        return ERR;
+
+    if (attrs)
+        *attrs = win->_attrs & (A_ATTRIBUTES & ~A_COLOR);
+
+    if (color_pair)
+        *color_pair = PAIR_NUMBER(win->_attrs);
+
+    return OK;
+}
+
+int attr_get(attr_t *attrs, short *color_pair, void *opts)
+{
+    PDC_LOG(("attr_get() - called\n"));
+
+    return wattr_get(stdscr, attrs, color_pair, opts);
+}
+
+int wattr_off(WINDOW *win, attr_t attrs, void *opts)
+{
+    PDC_LOG(("wattr_off() - called\n"));
+
+    return wattroff(win, attrs);
+}
+
+int attr_off(attr_t attrs, void *opts)
+{
+    PDC_LOG(("attr_off() - called\n"));
+
+    return wattroff(stdscr, attrs);
+}
+
+int wattr_on(WINDOW *win, attr_t attrs, void *opts)
+{
+    PDC_LOG(("wattr_off() - called\n"));
+
+    return wattron(win, attrs);
+}
+
+int attr_on(attr_t attrs, void *opts)
+{
+    PDC_LOG(("attr_on() - called\n"));
+
+    return wattron(stdscr, attrs);
+}
+
+int wattr_set(WINDOW *win, attr_t attrs, short color_pair, void *opts)
+{
+    PDC_LOG(("wattr_set() - called\n"));
+
+    if (!win)
+        return ERR;
+
+    win->_attrs = (attrs & (A_ATTRIBUTES & ~A_COLOR)) | COLOR_PAIR(color_pair);
+
+    return OK;
+}
+
+int attr_set(attr_t attrs, short color_pair, void *opts)
+{
+    PDC_LOG(("attr_get() - called\n"));
+
+    return wattr_set(stdscr, attrs, color_pair, opts);
+}
+
+int wchgat(WINDOW *win, int n, attr_t attr, short color, const void *opts)
+{
+    chtype *dest, newattr;
+    int startpos, endpos;
+
+    PDC_LOG(("wchgat() - called\n"));
+
+    if (!win)
+        return ERR;
+
+    newattr = (attr & A_ATTRIBUTES) | COLOR_PAIR(color);
+
+    startpos = win->_curx;
+    endpos = ((n < 0) ? win->_maxx : min(startpos + n, win->_maxx)) - 1;
+    dest = win->_y[win->_cury];
+
+    for (n = startpos; n <= endpos; n++)
+        dest[n] = (dest[n] & A_CHARTEXT) | newattr;
+
+    n = win->_cury;
+
+    if (startpos < win->_firstch[n] || win->_firstch[n] == _NO_CHANGE)
+        win->_firstch[n] = startpos;
+
+    if (endpos > win->_lastch[n])
+        win->_lastch[n] = endpos;
+
+    PDC_sync(win);
+
+    return OK;
+}
+
+int chgat(int n, attr_t attr, short color, const void *opts)
+{
+    PDC_LOG(("chgat() - called\n"));
+
+    return wchgat(stdscr, n, attr, color, opts);
+}
+
+int mvchgat(int y, int x, int n, attr_t attr, short color, const void *opts)
+{
+    PDC_LOG(("mvchgat() - called\n"));
+
+    if (move(y, x) == ERR)
+        return ERR;
+
+    return wchgat(stdscr, n, attr, color, opts);
+}
+
+int mvwchgat(WINDOW *win, int y, int x, int n, attr_t attr, short color,
+             const void *opts)
+{
+    PDC_LOG(("mvwchgat() - called\n"));
+
+    if (wmove(win, y, x) == ERR)
+        return ERR;
+
+    return wchgat(win, n, attr, color, opts);
+}
diff --git a/apps/lib/curses/pdcurses/pdcurses/beep.c b/apps/lib/curses/pdcurses/pdcurses/beep.c
new file mode 100644
index 0000000..9e92f45
--- /dev/null
+++ b/apps/lib/curses/pdcurses/pdcurses/beep.c
@@ -0,0 +1,65 @@
+/* Public Domain Curses */
+
+#include <curspriv.h>
+
+RCSID("$Id: beep.c,v 1.34 2008/07/13 16:08:17 wmcbrine Exp $")
+
+/*man-start**************************************************************
+
+  Name:                                                         beep
+
+  Synopsis:
+        int beep(void);
+        int flash(void);
+
+  Description:
+        beep() sounds the audible bell on the terminal, if possible;
+        if not, it calls flash().
+
+        flash() "flashes" the screen, by inverting the foreground and
+        background of every cell, pausing, and then restoring the
+        original attributes.
+
+  Return Value:
+        These functions return OK.
+
+  Portability                                X/Open    BSD    SYS V
+        beep                                    Y       Y       Y
+        flash                                   Y       Y       Y
+
+**man-end****************************************************************/
+
+int beep(void)
+{
+    PDC_LOG(("beep() - called\n"));
+
+    if (SP->audible)
+        PDC_beep();
+    else
+        flash();
+
+    return OK;
+}
+
+int flash(void)
+{
+    int z, y, x;
+
+    PDC_LOG(("flash() - called\n"));
+
+    /* Reverse each cell; wait; restore the screen */
+
+    for (z = 0; z < 2; z++)
+    {
+        for (y = 0; y < LINES; y++)
+            for (x = 0; x < COLS; x++)
+                curscr->_y[y][x] ^= A_REVERSE;
+
+        wrefresh(curscr);
+
+        if (!z)
+            napms(50);
+    }
+
+    return OK;
+}
diff --git a/apps/lib/curses/pdcurses/pdcurses/bkgd.c b/apps/lib/curses/pdcurses/pdcurses/bkgd.c
new file mode 100644
index 0000000..083239e
--- /dev/null
+++ b/apps/lib/curses/pdcurses/pdcurses/bkgd.c
@@ -0,0 +1,220 @@
+/* Public Domain Curses */
+
+#include <curspriv.h>
+
+RCSID("$Id: bkgd.c,v 1.39 2008/07/13 16:08:18 wmcbrine Exp $")
+
+/*man-start**************************************************************
+
+  Name:                                                         bkgd
+
+  Synopsis:
+        int bkgd(chtype ch);
+        void bkgdset(chtype ch);
+        chtype getbkgd(WINDOW *win);
+        int wbkgd(WINDOW *win, chtype ch);
+        void wbkgdset(WINDOW *win, chtype ch);
+
+        int bkgrnd(const cchar_t *wch);
+        void bkgrndset(const cchar_t *wch);
+        int getbkgrnd(cchar_t *wch);
+        int wbkgrnd(WINDOW *win, const cchar_t *wch);
+        void wbkgrndset(WINDOW *win, const cchar_t *wch);
+        int wgetbkgrnd(WINDOW *win, cchar_t *wch);
+
+  Description:
+        bkgdset() and wbkgdset() manipulate the background of a window.
+        The background is a chtype consisting of any combination of
+        attributes and a character; it is combined with each chtype
+        added or inserted to the window by waddch() or winsch(). Only
+        the attribute part is used to set the background of non-blank
+        characters, while both character and attributes are used for
+        blank positions.
+
+        bkgd() and wbkgd() not only change the background, but apply it
+        immediately to every cell in the window.
+
+        The attributes that are defined with the attrset()/attron() set
+        of functions take precedence over the background attributes if
+        there is a conflict (e.g., different color pairs).
+
+  Return Value:
+        bkgd() and wbkgd() return OK, unless the window is NULL, in 
+        which case they return ERR.
+
+  Portability                                X/Open    BSD    SYS V
+        bkgd                                    Y       -      4.0
+        bkgdset                                 Y       -      4.0
+        getbkgd                                 Y
+        wbkgd                                   Y       -      4.0
+        wbkgdset                                Y       -      4.0
+        bkgrnd                                  Y
+        bkgrndset                               Y
+        getbkgrnd                               Y
+        wbkgrnd                                 Y
+        wbkgrndset                              Y
+        wgetbkgrnd                              Y
+
+**man-end****************************************************************/
+
+int wbkgd(WINDOW *win, chtype ch)
+{
+    int x, y;
+    chtype oldcolr, oldch, newcolr, newch, colr, attr;
+    chtype oldattr = 0, newattr = 0;
+    chtype *winptr;
+
+    PDC_LOG(("wbkgd() - called\n"));
+
+    if (!win)
+        return ERR;
+
+    if (win->_bkgd == ch)
+        return OK;
+
+    oldcolr = win->_bkgd & A_COLOR;
+    if (oldcolr)
+        oldattr = (win->_bkgd & A_ATTRIBUTES) ^ oldcolr;
+
+    oldch = win->_bkgd & A_CHARTEXT;
+
+    wbkgdset(win, ch);
+
+    newcolr = win->_bkgd & A_COLOR;
+    if (newcolr)
+        newattr = (win->_bkgd & A_ATTRIBUTES) ^ newcolr;
+
+    newch = win->_bkgd & A_CHARTEXT;
+
+    /* what follows is what seems to occur in the System V 
+       implementation of this routine */
+
+    for (y = 0; y < win->_maxy; y++)
+    {
+        for (x = 0; x < win->_maxx; x++)
+        {
+            winptr = win->_y[y] + x;
+
+            ch = *winptr;
+
+            /* determine the colors and attributes of the character read 
+               from the window */
+
+            colr = ch & A_COLOR;
+            attr = ch & (A_ATTRIBUTES ^ A_COLOR);
+
+            /* if the color is the same as the old background color, 
+               then make it the new background color, otherwise leave it */
+
+            if (colr == oldcolr)
+                colr = newcolr;
+
+            /* remove any attributes (non color) from the character that 
+               were part of the old background, then combine the 
+               remaining ones with the new background */
+
+            attr ^= oldattr;
+            attr |= newattr;
+
+            /* change character if it is there because it was the old 
+               background character */
+
+            ch &= A_CHARTEXT;
+            if (ch == oldch)
+                ch = newch;
+
+            ch |= (attr | colr);
+
+            *winptr = ch;
+
+        }
+    }
+
+    touchwin(win);
+    PDC_sync(win);
+    return OK;
+}
+
+int bkgd(chtype ch)
+{
+    PDC_LOG(("bkgd() - called\n"));
+
+    return wbkgd(stdscr, ch);
+}
+
+void wbkgdset(WINDOW *win, chtype ch)
+{
+    PDC_LOG(("wbkgdset() - called\n"));
+
+    if (win)
+    {
+        if (!(ch & A_CHARTEXT))
+            ch |= ' ';
+
+        win->_bkgd = ch;
+    }
+}
+
+void bkgdset(chtype ch)
+{
+    PDC_LOG(("bkgdset() - called\n"));
+
+    wbkgdset(stdscr, ch);
+}
+
+chtype getbkgd(WINDOW *win)
+{
+    PDC_LOG(("getbkgd() - called\n"));
+
+    return win ? win->_bkgd : (chtype)ERR;
+}
+
+#ifdef PDC_WIDE
+int wbkgrnd(WINDOW *win, const cchar_t *wch)
+{
+    PDC_LOG(("wbkgrnd() - called\n"));
+
+    return wch ? wbkgd(win, *wch) : ERR;
+}
+
+int bkgrnd(const cchar_t *wch)
+{
+    PDC_LOG(("bkgrnd() - called\n"));
+
+    return wbkgrnd(stdscr, wch);
+}
+
+void wbkgrndset(WINDOW *win, const cchar_t *wch)
+{
+    PDC_LOG(("wbkgdset() - called\n"));
+
+    if (wch)
+        wbkgdset(win, *wch);
+}
+
+void bkgrndset(const cchar_t *wch)
+{
+    PDC_LOG(("bkgrndset() - called\n"));
+
+    wbkgrndset(stdscr, wch);
+}
+
+int wgetbkgrnd(WINDOW *win, cchar_t *wch)
+{
+    PDC_LOG(("wgetbkgrnd() - called\n"));
+
+    if (!win || !wch)
+        return ERR;
+
+    *wch = win->_bkgd;
+
+    return OK;
+}
+
+int getbkgrnd(cchar_t *wch)
+{
+    PDC_LOG(("getbkgrnd() - called\n"));
+
+    return wgetbkgrnd(stdscr, wch);
+}
+#endif
diff --git a/apps/lib/curses/pdcurses/pdcurses/border.c b/apps/lib/curses/pdcurses/pdcurses/border.c
new file mode 100644
index 0000000..ec86aaf
--- /dev/null
+++ b/apps/lib/curses/pdcurses/pdcurses/border.c
@@ -0,0 +1,408 @@
+/* Public Domain Curses */
+
+#include <curspriv.h>
+
+RCSID("$Id: border.c,v 1.53 2008/07/13 16:08:18 wmcbrine Exp $")
+
+/*man-start**************************************************************
+
+  Name:                                                         border
+
+  Synopsis:
+        int border(chtype ls, chtype rs, chtype ts, chtype bs, chtype tl, 
+                   chtype tr, chtype bl, chtype br);
+        int wborder(WINDOW *win, chtype ls, chtype rs, chtype ts, 
+                    chtype bs, chtype tl, chtype tr, chtype bl, chtype br);
+        int box(WINDOW *win, chtype verch, chtype horch);
+        int hline(chtype ch, int n);
+        int vline(chtype ch, int n);
+        int whline(WINDOW *win, chtype ch, int n);
+        int wvline(WINDOW *win, chtype ch, int n);
+        int mvhline(int y, int x, chtype ch, int n);
+        int mvvline(int y, int x, chtype ch, int n);
+        int mvwhline(WINDOW *win, int y, int x, chtype ch, int n);
+        int mvwvline(WINDOW *win, int y, int x, chtype ch, int n);
+
+        int border_set(const cchar_t *ls, const cchar_t *rs,
+                       const cchar_t *ts, const cchar_t *bs,
+                       const cchar_t *tl, const cchar_t *tr,
+                       const cchar_t *bl, const cchar_t *br);
+        int wborder_set(WINDOW *win, const cchar_t *ls, const cchar_t *rs,
+                        const cchar_t *ts, const cchar_t *bs,
+                        const cchar_t *tl, const cchar_t *tr,
+                        const cchar_t *bl, const cchar_t *br);
+        int box_set(WINDOW *win, const cchar_t *verch, const cchar_t *horch);
+        int hline_set(const cchar_t *wch, int n);
+        int vline_set(const cchar_t *wch, int n);
+        int whline_set(WINDOW *win, const cchar_t *wch, int n);
+        int wvline_set(WINDOW *win, const cchar_t *wch, int n);
+        int mvhline_set(int y, int x, const cchar_t *wch, int n);
+        int mvvline_set(int y, int x, const cchar_t *wch, int n);
+        int mvwhline_set(WINDOW *win, int y, int x, const cchar_t *wch, int n);
+        int mvwvline_set(WINDOW *win, int y, int x, const cchar_t *wch, int n);
+
+  Description:
+        border(), wborder(), and box() draw a border around the edge of 
+        the window. If any argument is zero, an appropriate default is 
+        used:
+
+                ls      left side of border             ACS_VLINE
+                rs      right side of border            ACS_VLINE
+                ts      top side of border              ACS_HLINE
+                bs      bottom side of border           ACS_HLINE
+                tl      top left corner of border       ACS_ULCORNER
+                tr      top right corner of border      ACS_URCORNER
+                bl      bottom left corner of border    ACS_LLCORNER
+                br      bottom right corner of border   ACS_LRCORNER
+
+        hline() and whline() draw a horizontal line, using ch, starting 
+        from the current cursor position. The cursor position does not 
+        change. The line is at most n characters long, or as many as 
+        will fit in the window.
+
+        vline() and wvline() draw a vertical line, using ch, starting 
+        from the current cursor position. The cursor position does not 
+        change. The line is at most n characters long, or as many as 
+        will fit in the window.
+
+  Return Value:
+        These functions return OK on success and ERR on error.
+
+  Portability                                X/Open    BSD    SYS V
+        border                                  Y       -      4.0
+        wborder                                 Y       -      4.0
+        box                                     Y       Y       Y
+        hline                                   Y       -      4.0
+        vline                                   Y       -      4.0
+        whline                                  Y       -      4.0
+        wvline                                  Y       -      4.0
+        mvhline                                 Y
+        mvvline                                 Y
+        mvwhline                                Y
+        mvwvline                                Y
+        border_set                              Y
+        wborder_set                             Y
+        box_set                                 Y
+        hline_set                               Y
+        vline_set                               Y
+        whline_set                              Y
+        wvline_set                              Y
+        mvhline_set                             Y
+        mvvline_set                             Y
+        mvwhline_set                            Y
+        mvwvline_set                            Y
+
+**man-end****************************************************************/
+
+/* _attr_passthru() -- Takes a single chtype 'ch' and checks if the 
+   current attribute of window 'win', as set by wattrset(), and/or the 
+   current background of win, as set by wbkgd(), should by combined with 
+   it. Attributes set explicitly in ch take precedence. */
+
+static chtype _attr_passthru(WINDOW *win, chtype ch)
+{
+    chtype attr;
+
+    /* If the incoming character doesn't have its own attribute, then 
+       use the current attributes for the window. If the incoming 
+       character has attributes, but not a color component, OR the 
+       attributes to the current attributes for the window. If the 
+       incoming character has a color component, use only the attributes 
+       from the incoming character. */
+
+    attr = ch & A_ATTRIBUTES;
+    if (!(attr & A_COLOR))
+        attr |= win->_attrs;
+
+    /* wrs (4/10/93) -- Apply the same sort of logic for the window 
+       background, in that it only takes precedence if other color 
+       attributes are not there. */
+
+    if (!(attr & A_COLOR))
+        attr |= win->_bkgd & A_ATTRIBUTES;
+    else
+        attr |= win->_bkgd & (A_ATTRIBUTES ^ A_COLOR);
+
+    ch = (ch & A_CHARTEXT) | attr;
+
+    return ch;
+}
+
+int wborder(WINDOW *win, chtype ls, chtype rs, chtype ts, chtype bs, 
+            chtype tl, chtype tr, chtype bl, chtype br)
+{
+    int i, ymax, xmax;
+
+    PDC_LOG(("wborder() - called\n"));
+
+    if (!win)
+        return ERR;
+
+    ymax = win->_maxy - 1;
+    xmax = win->_maxx - 1;
+
+    ls = _attr_passthru(win, ls ? ls : ACS_VLINE);
+    rs = _attr_passthru(win, rs ? rs : ACS_VLINE);
+    ts = _attr_passthru(win, ts ? ts : ACS_HLINE);
+    bs = _attr_passthru(win, bs ? bs : ACS_HLINE);
+    tl = _attr_passthru(win, tl ? tl : ACS_ULCORNER);
+    tr = _attr_passthru(win, tr ? tr : ACS_URCORNER);
+    bl = _attr_passthru(win, bl ? bl : ACS_LLCORNER);
+    br = _attr_passthru(win, br ? br : ACS_LRCORNER);
+
+    for (i = 1; i < xmax; i++)
+    {
+        win->_y[0][i] = ts;
+        win->_y[ymax][i] = bs;
+    }
+
+    for (i = 1; i < ymax; i++)
+    {
+        win->_y[i][0] = ls;
+        win->_y[i][xmax] = rs;
+    }
+
+    win->_y[0][0] = tl;
+    win->_y[0][xmax] = tr;
+    win->_y[ymax][0] = bl;
+    win->_y[ymax][xmax] = br;
+
+    for (i = 0; i <= ymax; i++)
+    {
+        win->_firstch[i] = 0;
+        win->_lastch[i] = xmax;
+    }
+
+    PDC_sync(win);
+
+    return OK;
+}
+
+int border(chtype ls, chtype rs, chtype ts, chtype bs, chtype tl,
+           chtype tr, chtype bl, chtype br)
+{
+    PDC_LOG(("border() - called\n"));
+
+    return wborder(stdscr, ls, rs, ts, bs, tl, tr, bl, br);
+}
+
+int box(WINDOW *win, chtype verch, chtype horch)
+{
+    PDC_LOG(("box() - called\n"));
+
+    return wborder(win, verch, verch, horch, horch, 0, 0, 0, 0);
+}
+
+int whline(WINDOW *win, chtype ch, int n)
+{
+    chtype *dest;
+    int startpos, endpos;
+
+    PDC_LOG(("whline() - called\n"));
+
+    if (!win || n < 1)
+        return ERR;
+
+    startpos = win->_curx;
+    endpos = min(startpos + n, win->_maxx) - 1;
+    dest = win->_y[win->_cury];
+    ch = _attr_passthru(win, ch ? ch : ACS_HLINE);
+
+    for (n = startpos; n <= endpos; n++)
+        dest[n] = ch;
+
+    n = win->_cury;
+
+    if (startpos < win->_firstch[n] || win->_firstch[n] == _NO_CHANGE)
+        win->_firstch[n] = startpos;
+
+    if (endpos > win->_lastch[n])
+        win->_lastch[n] = endpos;
+
+    PDC_sync(win);
+
+    return OK;
+}
+
+int hline(chtype ch, int n)
+{
+    PDC_LOG(("hline() - called\n"));
+
+    return whline(stdscr, ch, n);
+}
+
+int mvhline(int y, int x, chtype ch, int n)
+{
+    PDC_LOG(("mvhline() - called\n"));
+
+    if (move(y, x) == ERR)
+        return ERR;
+
+    return whline(stdscr, ch, n);
+}
+
+int mvwhline(WINDOW *win, int y, int x, chtype ch, int n)
+{
+    PDC_LOG(("mvwhline() - called\n"));
+
+    if (wmove(win, y, x) == ERR)
+        return ERR;
+
+    return whline(win, ch, n);
+}
+
+int wvline(WINDOW *win, chtype ch, int n)
+{
+    int endpos, x;
+
+    PDC_LOG(("wvline() - called\n"));
+
+    if (!win || n < 1)
+        return ERR;
+
+    endpos = min(win->_cury + n, win->_maxy);
+    x = win->_curx;
+
+    ch = _attr_passthru(win, ch ? ch : ACS_VLINE);
+
+    for (n = win->_cury; n < endpos; n++)
+    {
+        win->_y[n][x] = ch;
+
+        if (x < win->_firstch[n] || win->_firstch[n] == _NO_CHANGE)
+            win->_firstch[n] = x;
+
+        if (x > win->_lastch[n])
+            win->_lastch[n] = x;
+    }
+
+    PDC_sync(win);
+
+    return OK;
+}
+
+int vline(chtype ch, int n)
+{
+    PDC_LOG(("vline() - called\n"));
+
+    return wvline(stdscr, ch, n);
+}
+
+int mvvline(int y, int x, chtype ch, int n)
+{
+    PDC_LOG(("mvvline() - called\n"));
+
+    if (move(y, x) == ERR)
+        return ERR;
+
+    return wvline(stdscr, ch, n);
+}
+
+int mvwvline(WINDOW *win, int y, int x, chtype ch, int n)
+{
+    PDC_LOG(("mvwvline() - called\n"));
+
+    if (wmove(win, y, x) == ERR)
+        return ERR;
+
+    return wvline(win, ch, n);
+}
+
+#ifdef PDC_WIDE
+int wborder_set(WINDOW *win, const cchar_t *ls, const cchar_t *rs,
+                const cchar_t *ts, const cchar_t *bs, const cchar_t *tl,
+                const cchar_t *tr, const cchar_t *bl, const cchar_t *br)
+{
+    PDC_LOG(("wborder_set() - called\n"));
+
+    return wborder(win, ls ? *ls : 0, rs ? *rs : 0, ts ? *ts : 0,
+                        bs ? *bs : 0, tl ? *tl : 0, tr ? *tr : 0,
+                        bl ? *bl : 0, br ? *br : 0);
+}
+
+int border_set(const cchar_t *ls, const cchar_t *rs, const cchar_t *ts,
+               const cchar_t *bs, const cchar_t *tl, const cchar_t *tr,
+               const cchar_t *bl, const cchar_t *br)
+{
+    PDC_LOG(("border_set() - called\n"));
+
+    return wborder_set(stdscr, ls, rs, ts, bs, tl, tr, bl, br);
+}
+
+int box_set(WINDOW *win, const cchar_t *verch, const cchar_t *horch)
+{
+    PDC_LOG(("box_set() - called\n"));
+
+    return wborder_set(win, verch, verch, horch, horch,
+                       (const cchar_t *)NULL, (const cchar_t *)NULL,
+                       (const cchar_t *)NULL, (const cchar_t *)NULL);
+}
+
+int whline_set(WINDOW *win, const cchar_t *wch, int n)
+{
+    PDC_LOG(("whline_set() - called\n"));
+
+    return wch ? whline(win, *wch, n) : ERR;
+}
+
+int hline_set(const cchar_t *wch, int n)
+{
+    PDC_LOG(("hline_set() - called\n"));
+
+    return whline_set(stdscr, wch, n);
+}
+
+int mvhline_set(int y, int x, const cchar_t *wch, int n)
+{
+    PDC_LOG(("mvhline_set() - called\n"));
+
+    if (move(y, x) == ERR)
+        return ERR;
+
+    return whline_set(stdscr, wch, n);
+}
+
+int mvwhline_set(WINDOW *win, int y, int x, const cchar_t *wch, int n)
+{
+    PDC_LOG(("mvwhline_set() - called\n"));
+
+    if (wmove(win, y, x) == ERR)
+        return ERR;
+
+    return whline_set(win, wch, n);
+}
+
+int wvline_set(WINDOW *win, const cchar_t *wch, int n)
+{
+    PDC_LOG(("wvline_set() - called\n"));
+
+    return wch ? wvline(win, *wch, n) : ERR;
+}
+
+int vline_set(const cchar_t *wch, int n)
+{
+    PDC_LOG(("vline_set() - called\n"));
+
+    return wvline_set(stdscr, wch, n);
+}
+
+int mvvline_set(int y, int x, const cchar_t *wch, int n)
+{
+    PDC_LOG(("mvvline_set() - called\n"));
+
+    if (move(y, x) == ERR)
+        return ERR;
+
+    return wvline_set(stdscr, wch, n);
+}
+
+int mvwvline_set(WINDOW *win, int y, int x, const cchar_t *wch, int n)
+{
+    PDC_LOG(("mvwvline_set() - called\n"));
+
+    if (wmove(win, y, x) == ERR)
+        return ERR;
+
+    return wvline_set(win, wch, n);
+}
+#endif
diff --git a/apps/lib/curses/pdcurses/pdcurses/clear.c b/apps/lib/curses/pdcurses/pdcurses/clear.c
new file mode 100644
index 0000000..eda3385
--- /dev/null
+++ b/apps/lib/curses/pdcurses/pdcurses/clear.c
@@ -0,0 +1,154 @@
+/* Public Domain Curses */
+
+#include <curspriv.h>
+
+RCSID("$Id: clear.c,v 1.35 2008/07/13 16:08:18 wmcbrine Exp $")
+
+/*man-start**************************************************************
+
+  Name:                                                         clear
+
+  Synopsis:
+        int clear(void);
+        int wclear(WINDOW *win);
+        int erase(void);
+        int werase(WINDOW *win);
+        int clrtobot(void);
+        int wclrtobot(WINDOW *win);
+        int clrtoeol(void);
+        int wclrtoeol(WINDOW *win);
+
+  Description:
+        erase() and werase() copy blanks (i.e. the background chtype) to 
+        every cell of the window.
+
+        clear() and wclear() are similar to erase() and werase(), but
+        they also call clearok() to ensure that the the window is 
+        cleared on the next wrefresh().
+
+        clrtobot() and wclrtobot() clear the window from the current 
+        cursor position to the end of the window.
+
+        clrtoeol() and wclrtoeol() clear the window from the current
+        cursor position to the end of the current line.
+
+  Return Value:
+        All functions return OK on success and ERR on error.
+
+  Portability                                X/Open    BSD    SYS V
+        clear                                   Y       Y       Y
+        wclear                                  Y       Y       Y
+        erase                                   Y       Y       Y
+        werase                                  Y       Y       Y
+        clrtobot                                Y       Y       Y
+        wclrtobot                               Y       Y       Y
+        clrtoeol                                Y       Y       Y
+        wclrtoeol                               Y       Y       Y
+
+**man-end****************************************************************/
+
+int wclrtoeol(WINDOW *win)
+{
+    int x, y, minx;
+    chtype blank, *ptr;
+
+    PDC_LOG(("wclrtoeol() - called: Row: %d Col: %d\n",
+             win->_cury, win->_curx));
+
+    if (!win)
+        return ERR;
+
+    y = win->_cury;
+    x = win->_curx;
+
+    /* wrs (4/10/93) account for window background */
+
+    blank = win->_bkgd;
+
+    for (minx = x, ptr = &win->_y[y][x]; minx < win->_maxx; minx++, ptr++)
+        *ptr = blank;
+
+    if (x < win->_firstch[y] || win->_firstch[y] == _NO_CHANGE)
+        win->_firstch[y] = x;
+
+    win->_lastch[y] = win->_maxx - 1;
+
+    PDC_sync(win);
+    return OK;
+}
+
+int clrtoeol(void)
+{
+    PDC_LOG(("clrtoeol() - called\n"));
+
+    return wclrtoeol(stdscr);
+}
+
+int wclrtobot(WINDOW *win)
+{
+    int savey = win->_cury;
+    int savex = win->_curx;
+
+    PDC_LOG(("wclrtobot() - called\n"));
+
+    if (!win)
+        return ERR;
+
+    /* should this involve scrolling region somehow ? */
+
+    if (win->_cury + 1 < win->_maxy)
+    {
+        win->_curx = 0;
+        win->_cury++;
+        for (; win->_maxy > win->_cury; win->_cury++)
+            wclrtoeol(win);
+        win->_cury = savey;
+        win->_curx = savex;
+    }
+    wclrtoeol(win);
+
+    PDC_sync(win);
+    return OK;
+}
+
+int clrtobot(void)
+{
+    PDC_LOG(("clrtobot() - called\n"));
+
+    return wclrtobot(stdscr);
+}
+
+int werase(WINDOW *win)
+{
+    PDC_LOG(("werase() - called\n"));
+
+    if (wmove(win, 0, 0) == ERR)
+        return ERR;
+
+    return wclrtobot(win);
+}
+
+int erase(void)
+{
+    PDC_LOG(("erase() - called\n"));
+
+    return werase(stdscr);
+}
+
+int wclear(WINDOW *win)
+{
+    PDC_LOG(("wclear() - called\n"));
+
+    if (!win)
+        return ERR;
+
+    win->_clear = TRUE;
+    return werase(win);
+}
+
+int clear(void)
+{
+    PDC_LOG(("clear() - called\n"));
+
+    return wclear(stdscr);
+}
diff --git a/apps/lib/curses/pdcurses/pdcurses/color.c b/apps/lib/curses/pdcurses/pdcurses/color.c
new file mode 100644
index 0000000..038f760
--- /dev/null
+++ b/apps/lib/curses/pdcurses/pdcurses/color.c
@@ -0,0 +1,295 @@
+/* Public Domain Curses */
+
+#include <curspriv.h>
+
+RCSID("$Id: color.c,v 1.83 2008/07/13 16:08:18 wmcbrine Exp $")
+
+/*man-start**************************************************************
+
+  Name:                                                         color
+
+  Synopsis:
+        int start_color(void);
+        int init_pair(short pair, short fg, short bg);
+        int init_color(short color, short red, short green, short blue);
+        bool has_colors(void);
+        bool can_change_color(void);
+        int color_content(short color, short *red, short *green, short *blue);
+        int pair_content(short pair, short *fg, short *bg);
+
+        int assume_default_colors(int f, int b);
+        int use_default_colors(void);
+
+        int PDC_set_line_color(short color);
+
+  Description:
+        To use these routines, start_color() must be called, usually
+        immediately after initscr(). Colors are always used in pairs, 
+        referred to as color-pairs. A color-pair consists of a 
+        foreground color and a background color. A color-pair is 
+        initialized via init_pair(). After initialization, COLOR_PAIR(n) 
+        can be used like any other video attribute.
+
+        start_color() initializes eight basic colors (black, red, green,
+        yellow, blue, magenta, cyan, and white), and two global
+        variables; COLORS and COLOR_PAIRS (respectively defining the
+        maximum number of colors and color-pairs the terminal is capable
+        of displaying).
+
+        init_pair() changes the definition of a color-pair. It takes 
+        three arguments: the number of the color-pair to be redefined, 
+        and the new values of the foreground and background colors. The 
+        pair number must be between 0 and COLOR_PAIRS - 1, inclusive. 
+        The foreground and background must be between 0 and COLORS - 1, 
+        inclusive. If the color pair was previously initialized, the 
+        screen is refreshed, and all occurrences of that color-pair are 
+        changed to the new definition.
+
+        has_colors() indicates if the terminal supports, and can 
+        maniplulate color. It returns TRUE or FALSE.
+
+        can_change_color() indicates if the terminal has the capability
+        to change the definition of its colors.
+
+        pair_content() is used to determine what the colors of a given
+        color-pair consist of.
+
+        assume_default_colors() and use_default_colors() emulate the
+        ncurses extensions of the same names. assume_default_colors(f,
+        b) is essentially the same as init_pair(0, f, b) (which isn't
+        allowed); it redefines the default colors. use_default_colors()
+        allows the use of -1 as a foreground or background color with
+        init_pair(), and calls assume_default_colors(-1, -1); -1
+        represents the foreground or background color that the terminal
+        had at startup. If the environment variable PDC_ORIGINAL_COLORS
+        is set at the time start_color() is called, that's equivalent to
+        calling use_default_colors().
+
+        PDC_set_line_color() is used to set the color, globally, for
+        the color of the lines drawn for the attributes: A_UNDERLINE,
+        A_OVERLINE, A_LEFTLINE and A_RIGHTLINE. A value of -1 (the
+        default) indicates that the current foreground color should be
+        used.
+
+        NOTE: COLOR_PAIR() and PAIR_NUMBER() are implemented as macros.
+
+  Return Value:
+        All functions return OK on success and ERR on error, except for
+        has_colors() and can_change_colors(), which return TRUE or FALSE.
+
+  Portability                                X/Open    BSD    SYS V
+        start_color                             Y       -      3.2
+        init_pair                               Y       -      3.2
+        init_color                              Y       -      3.2
+        has_colors                              Y       -      3.2
+        can_change_color                        Y       -      3.2
+        color_content                           Y       -      3.2
+        pair_content                            Y       -      3.2
+        assume_default_colors                   -       -       -
+        use_default_colors                      -       -       -
+        PDC_set_line_color                      -       -       -
+
+**man-end****************************************************************/
+
+#include <stdlib.h>
+#include <string.h>
+
+int COLORS = 0;
+int COLOR_PAIRS = PDC_COLOR_PAIRS;
+
+bool pdc_color_started = FALSE;
+
+/* pair_set[] tracks whether a pair has been set via init_pair() */
+
+static bool pair_set[PDC_COLOR_PAIRS];
+static bool default_colors = FALSE;
+static short first_col = 0;
+
+int start_color(void)
+{
+    PDC_LOG(("start_color() - called\n"));
+
+    if (SP->mono)
+        return ERR;
+
+    pdc_color_started = TRUE;
+
+    PDC_set_blink(FALSE);   /* Also sets COLORS, to 8 or 16 */
+
+    if (!default_colors && SP->orig_attr && getenv("PDC_ORIGINAL_COLORS"))
+        default_colors = TRUE;
+
+    PDC_init_atrtab();
+
+    memset(pair_set, 0, PDC_COLOR_PAIRS);
+
+    return OK;
+}
+
+static void _normalize(short *fg, short *bg)
+{
+    if (*fg == -1)
+        *fg = SP->orig_attr ? SP->orig_fore : COLOR_WHITE;
+
+    if (*bg == -1)
+        *bg = SP->orig_attr ? SP->orig_back : COLOR_BLACK;
+}
+
+int init_pair(short pair, short fg, short bg)
+{
+    PDC_LOG(("init_pair() - called: pair %d fg %d bg %d\n", pair, fg, bg));
+
+    if (!pdc_color_started || pair < 1 || pair >= COLOR_PAIRS ||
+        fg < first_col || fg >= COLORS || bg < first_col || bg >= COLORS)
+        return ERR;
+
+    _normalize(&fg, &bg);
+
+    /* To allow the PDC_PRESERVE_SCREEN option to work, we only reset 
+       curscr if this call to init_pair() alters a color pair created by 
+       the user. */
+
+    if (pair_set[pair])
+    {
+        short oldfg, oldbg;
+
+        PDC_pair_content(pair, &oldfg, &oldbg);
+
+        if (oldfg != fg || oldbg != bg)
+            curscr->_clear = TRUE;
+    }
+
+    PDC_init_pair(pair, fg, bg);
+
+    pair_set[pair] = TRUE;
+
+    return OK;
+}
+
+bool has_colors(void)
+{
+    PDC_LOG(("has_colors() - called\n"));
+
+    return !(SP->mono);
+}
+
+int init_color(short color, short red, short green, short blue)
+{
+    PDC_LOG(("init_color() - called\n"));
+
+    if (color < 0 || color >= COLORS || !PDC_can_change_color() ||
+        red < 0 || red > 1000 || green < 0 || green > 1000 ||
+        blue < 0 || blue > 1000)
+        return ERR;
+
+    return PDC_init_color(color, red, green, blue);
+}
+
+int color_content(short color, short *red, short *green, short *blue)
+{
+    PDC_LOG(("color_content() - called\n"));
+
+    if (color < 0 || color >= COLORS || !red || !green || !blue)
+        return ERR;
+
+    if (PDC_can_change_color())
+        return PDC_color_content(color, red, green, blue);
+    else
+    {
+        /* Simulated values for platforms that don't support palette 
+           changing */
+
+        short maxval = (color & 8) ? 1000 : 680;
+
+        *red = (color & COLOR_RED) ? maxval : 0;
+        *green = (color & COLOR_GREEN) ? maxval : 0;
+        *blue = (color & COLOR_BLUE) ? maxval : 0;
+
+        return OK;
+    }
+}
+
+bool can_change_color(void)
+{
+    PDC_LOG(("can_change_color() - called\n"));
+
+    return PDC_can_change_color();
+}
+
+int pair_content(short pair, short *fg, short *bg)
+{
+    PDC_LOG(("pair_content() - called\n"));
+
+    if (pair < 0 || pair >= COLOR_PAIRS || !fg || !bg)
+        return ERR;
+
+    return PDC_pair_content(pair, fg, bg);
+}
+
+int assume_default_colors(int f, int b)
+{
+    PDC_LOG(("assume_default_colors() - called: f %d b %d\n", f, b));
+
+    if (f < -1 || f >= COLORS || b < -1 || b >= COLORS)
+        return ERR;
+
+    if (pdc_color_started)
+    {
+        short fg, bg, oldfg, oldbg;
+
+        fg = f;
+        bg = b;
+
+        _normalize(&fg, &bg);
+
+        PDC_pair_content(0, &oldfg, &oldbg);
+
+        if (oldfg != fg || oldbg != bg)
+            curscr->_clear = TRUE;
+
+        PDC_init_pair(0, fg, bg);
+    }
+
+    return OK;
+}
+
+int use_default_colors(void)
+{
+    PDC_LOG(("use_default_colors() - called\n"));
+
+    default_colors = TRUE;
+    first_col = -1;
+
+    return assume_default_colors(-1, -1);
+}
+
+int PDC_set_line_color(short color)
+{
+    PDC_LOG(("PDC_set_line_color() - called: %d\n", color));
+
+    if (color < -1 || color >= COLORS)
+        return ERR;
+
+    SP->line_color = color;
+
+    return OK;
+}
+
+void PDC_init_atrtab(void)
+{
+    int i;
+    short fg, bg;
+
+    if (pdc_color_started && !default_colors)
+    {
+        fg = COLOR_WHITE;
+        bg = COLOR_BLACK;
+    }
+    else
+        fg = bg = -1;
+
+    _normalize(&fg, &bg);
+
+    for (i = 0; i < PDC_COLOR_PAIRS; i++)
+        PDC_init_pair(i, fg, bg);
+}
diff --git a/apps/lib/curses/pdcurses/pdcurses/curspriv.h b/apps/lib/curses/pdcurses/pdcurses/curspriv.h
new file mode 100644
index 0000000..734400b
--- /dev/null
+++ b/apps/lib/curses/pdcurses/pdcurses/curspriv.h
@@ -0,0 +1,146 @@
+/* Public Domain Curses */
+
+/* $Id: curspriv.h,v 1.158 2008/07/13 16:08:16 wmcbrine Exp $ */
+
+/* Private definitions and declarations for use within PDCurses.
+   These should generally not be referenced by applications. */
+
+#ifndef __CURSES_INTERNALS__
+#define __CURSES_INTERNALS__ 1
+
+#define HAVE_CONFIG_H
+#ifdef HAVE_CONFIG_H
+# include "../backend/config.h"
+#endif
+
+#include <stdlib.h>
+#include <malloc.h>
+
+#define CURSES_LIBRARY
+#include <curses.h>
+
+#if defined(__TURBOC__) || defined(__EMX__) || defined(__DJGPP__) || \
+    defined(__CYGWIN32__) || defined(__MINGW32__) || \
+    defined(__WATCOMC__) || defined(__PACIFIC__)
+# ifndef HAVE_VSSCANF
+#  define HAVE_VSSCANF       /* have vsscanf() */
+# endif
+#endif
+
+#if defined(__CYGWIN32__) || defined(__MINGW32__) || \
+    defined(__LCC__) || defined(__WATCOMC__)
+# ifndef HAVE_VSNPRINTF
+#  define HAVE_VSNPRINTF     /* have vsnprintf() */
+# endif
+#endif
+
+#if defined(_MSC_VER) && defined(_WIN32) && !defined(_CRT_SECURE_NO_DEPRECATE)
+# define _CRT_SECURE_NO_DEPRECATE 1   /* kill nonsense warnings */
+#endif
+
+/*----------------------------------------------------------------------*/
+
+typedef struct           /* structure for ripped off lines */
+{
+    int line;
+    int (*init)(WINDOW *, int);
+} RIPPEDOFFLINE;
+
+/* Window properties */
+
+#define _SUBWIN    0x01  /* window is a subwindow */
+#define _PAD       0x10  /* X/Open Pad. */
+#define _SUBPAD    0x20  /* X/Open subpad. */
+
+/* Miscellaneous */
+
+#define _NO_CHANGE -1    /* flags line edge unchanged */
+
+#define _ECHAR     0x08  /* Erase char       (^H) */
+#define _DWCHAR    0x17  /* Delete Word char (^W) */
+#define _DLCHAR    0x15  /* Delete Line char (^U) */
+
+extern WINDOW *pdc_lastscr;
+extern bool pdc_trace_on;   /* tracing flag */
+extern bool pdc_color_started;
+extern unsigned long pdc_key_modifiers;
+extern MOUSE_STATUS pdc_mouse_status;
+
+/*----------------------------------------------------------------------*/
+
+/* Platform implementation functions */
+
+void    PDC_beep(void);
+bool    PDC_can_change_color(void);
+int     PDC_color_content(short, short *, short *, short *);
+bool    PDC_check_key(void);
+int     PDC_curs_set(int);
+void    PDC_flushinp(void);
+int     PDC_get_columns(void);
+int     PDC_get_cursor_mode(void);
+int     PDC_get_key(void);
+int     PDC_get_rows(void);
+void    PDC_gotoyx(int, int);
+int     PDC_init_color(short, short, short, short);
+void    PDC_init_pair(short, short, short);
+int     PDC_modifiers_set(void);
+int     PDC_mouse_set(void);
+void    PDC_napms(int);
+int     PDC_pair_content(short, short *, short *);
+void    PDC_reset_prog_mode(void);
+void    PDC_reset_shell_mode(void);
+int     PDC_resize_screen(int, int);
+void    PDC_restore_screen_mode(int);
+void    PDC_save_screen_mode(int);
+void    PDC_scr_close(void);
+void    PDC_scr_free(void);
+int     PDC_scr_open(int, char **);
+void    PDC_set_keyboard_binary(bool);
+void    PDC_transform_line(int, int, int, const chtype *);
+const char *PDC_sysname(void);
+
+/* Internal cross-module functions */
+
+void    PDC_init_atrtab(void);
+WINDOW *PDC_makelines(WINDOW *);
+WINDOW *PDC_makenew(int, int, int, int);
+int     PDC_mouse_in_slk(int, int);
+void    PDC_slk_free(void);
+void    PDC_slk_initialize(void);
+void    PDC_sync(WINDOW *);
+
+#ifdef PDC_WIDE
+int     PDC_mbtowc(wchar_t *, const char *, size_t);
+size_t  PDC_mbstowcs(wchar_t *, const char *, size_t);
+size_t  PDC_wcstombs(char *, const wchar_t *, size_t);
+#endif
+
+#ifdef PDCDEBUG
+# define PDC_LOG(x) if (pdc_trace_on) PDC_debug x
+# define RCSID(x) static const char *rcsid = x;
+#else
+# define PDC_LOG(x)
+# define RCSID(x)
+#endif
+
+/* Internal macros for attributes */
+
+#ifdef CHTYPE_LONG
+# define PDC_COLOR_PAIRS 256
+#else
+# define PDC_COLOR_PAIRS  32
+#endif
+
+#ifndef max
+# define max(a,b) (((a) > (b)) ? (a) : (b))
+#endif
+#ifndef min
+# define min(a,b) (((a) < (b)) ? (a) : (b))
+#endif
+
+#define DIVROUND(num, divisor) ((num) + ((divisor) >> 1)) / (divisor)
+
+#define PDC_CLICK_PERIOD 150  /* time to wait for a click, if
+                                 not set by mouseinterval() */
+
+#endif /* __CURSES_INTERNALS__*/
diff --git a/apps/lib/curses/pdcurses/pdcurses/debug.c b/apps/lib/curses/pdcurses/pdcurses/debug.c
new file mode 100644
index 0000000..5fd9dcc
--- /dev/null
+++ b/apps/lib/curses/pdcurses/pdcurses/debug.c
@@ -0,0 +1,81 @@
+/* Public Domain Curses */
+
+#include <curspriv.h>
+
+RCSID("$Id: debug.c,v 1.7 2008/07/13 16:08:18 wmcbrine Exp $")
+
+/*man-start**************************************************************
+
+  Name:                                                         debug
+
+  Synopsis:
+        void traceon(void);
+        void traceoff(void);
+        void PDC_debug(const char *, ...);
+
+  Description:
+        traceon() and traceoff() toggle the recording of debugging 
+        information to the file "trace". Although not standard, similar 
+        functions are in some other curses implementations.
+
+        PDC_debug() is the function that writes to the file, based on 
+        whether traceon() has been called. It's used from the PDC_LOG() 
+        macro.
+
+  Portability                                X/Open    BSD    SYS V
+        traceon                                 -       -       -
+        traceoff                                -       -       -
+        PDC_debug                               -       -       -
+
+**man-end****************************************************************/
+
+#include <string.h>
+#include <sys/types.h>
+#include <time.h>
+
+bool pdc_trace_on = TRUE;
+
+void PDC_debug(const char *fmt, ...)
+{
+    va_list args;
+    FILE *dbfp;
+    char hms[9];
+    time_t now;
+
+    if (!pdc_trace_on)
+        return; 
+
+    /* open debug log file append */
+
+    dbfp = fopen("trace", "a");
+    if (!dbfp)
+    {
+        fprintf(stderr,
+            "PDC_debug(): Unable to open debug log file\n");
+        return;
+    }
+
+//    time(&now);
+//    strftime(hms, 9, "%H:%M:%S", localtime(&now));
+//    fprintf(dbfp, "At: %8.8ld - %s ", (long) clock(), hms);
+
+    va_start(args, fmt);
+    vfprintf(dbfp, fmt, args);
+    va_end(args);
+
+    fclose(dbfp);
+}
+
+void traceon(void)
+{
+    PDC_LOG(("traceon() - called\n"));
+
+    pdc_trace_on = TRUE;
+}
+
+void traceoff(void)
+{
+    PDC_LOG(("traceoff() - called\n"));
+
+    pdc_trace_on = FALSE;
+}
diff --git a/apps/lib/curses/pdcurses/pdcurses/delch.c b/apps/lib/curses/pdcurses/pdcurses/delch.c
new file mode 100644
index 0000000..9c2416e
--- /dev/null
+++ b/apps/lib/curses/pdcurses/pdcurses/delch.c
@@ -0,0 +1,93 @@
+/* Public Domain Curses */
+
+#include <curspriv.h>
+
+RCSID("$Id: delch.c,v 1.33 2008/07/13 16:08:18 wmcbrine Exp $")
+
+/*man-start**************************************************************
+
+  Name:                                                         delch
+
+  Synopsis:
+        int delch(void);
+        int wdelch(WINDOW *win);
+        int mvdelch(int y, int x);
+        int mvwdelch(WINDOW *win, int y, int x);
+
+  Description:
+        The character under the cursor in the window is deleted.  All
+        characters to the right on the same line are moved to the left
+        one position and the last character on the line is filled with
+        a blank.  The cursor position does not change (after moving to
+        y, x if coordinates are specified).
+
+  Return Value:
+        All functions return OK on success and ERR on error.
+
+  Portability                                X/Open    BSD    SYS V
+        delch                                   Y       Y       Y
+        wdelch                                  Y       Y       Y
+        mvdelch                                 Y       Y       Y
+        mvwdelch                                Y       Y       Y
+
+**man-end****************************************************************/
+
+#include <string.h>
+
+int wdelch(WINDOW *win)
+{
+    int y, x, maxx;
+    chtype *temp1;
+
+    PDC_LOG(("wdelch() - called\n"));
+
+    if (!win)
+        return ERR;
+
+    y = win->_cury;
+    x = win->_curx;
+    maxx = win->_maxx - 1;
+    temp1 = &win->_y[y][x];
+
+    memmove(temp1, temp1 + 1, (maxx - x) * sizeof(chtype));
+
+    /* wrs (4/10/93) account for window background */
+
+    win->_y[y][maxx] = win->_bkgd;
+
+    win->_lastch[y] = maxx;
+
+    if ((win->_firstch[y] == _NO_CHANGE) || (win->_firstch[y] > x))
+        win->_firstch[y] = x;
+
+    PDC_sync(win);
+
+    return OK;
+}
+
+int delch(void)
+{
+    PDC_LOG(("delch() - called\n"));
+
+    return wdelch(stdscr);
+}
+
+int mvdelch(int y, int x)
+{
+    PDC_LOG(("mvdelch() - called\n"));
+
+    if (move(y, x) == ERR)
+        return ERR;
+
+    return wdelch(stdscr);
+}
+
+int mvwdelch(WINDOW *win, int y, int x)
+{
+    PDC_LOG(("mvwdelch() - called\n"));
+
+    if (wmove(win, y, x) == ERR)
+        return ERR;
+
+    return wdelch(win);
+}
diff --git a/apps/lib/curses/pdcurses/pdcurses/deleteln.c b/apps/lib/curses/pdcurses/pdcurses/deleteln.c
new file mode 100644
index 0000000..c856e90
--- /dev/null
+++ b/apps/lib/curses/pdcurses/pdcurses/deleteln.c
@@ -0,0 +1,208 @@
+/* Public Domain Curses */
+
+#include <curspriv.h>
+
+RCSID("$Id: deleteln.c,v 1.35 2008/07/13 16:08:18 wmcbrine Exp $")
+
+/*man-start**************************************************************
+
+  Name:                                                         deleteln
+
+  Synopsis:
+        int deleteln(void);
+        int wdeleteln(WINDOW *win);
+        int insdelln(int n);
+        int winsdelln(WINDOW *win, int n);
+        int insertln(void);
+        int winsertln(WINDOW *win);
+
+        int mvdeleteln(int y, int x);
+        int mvwdeleteln(WINDOW *win, int y, int x);
+        int mvinsertln(int y, int x);
+        int mvwinsertln(WINDOW *win, int y, int x);
+
+  Description:
+        With the deleteln() and wdeleteln() functions, the line under
+        the cursor in the window is deleted.  All lines below the
+        current line are moved up one line.  The bottom line of the
+        window is cleared.  The cursor position does not change.
+
+        With the insertln() and winsertn() functions, a blank line is 
+        inserted above the current line and the bottom line is lost.
+
+        mvdeleteln(), mvwdeleteln(), mvinsertln() and mvwinsertln() 
+        allow moving the cursor and inserting/deleting in one call.
+
+  Return Value:
+        All functions return OK on success and ERR on error.
+
+  Portability                                X/Open    BSD    SYS V
+        deleteln                                Y       Y       Y
+        wdeleteln                               Y       Y       Y
+        mvdeleteln                              -       -       -
+        mvwdeleteln                             -       -       -
+        insdelln                                Y       -      4.0
+        winsdelln                               Y       -      4.0
+        insertln                                Y       Y       Y
+        winsertln                               Y       Y       Y
+        mvinsertln                              -       -       -
+        mvwinsertln                             -       -       -
+
+**man-end****************************************************************/
+
+int wdeleteln(WINDOW *win)
+{
+    chtype blank, *temp, *ptr;
+    int y;
+
+    PDC_LOG(("wdeleteln() - called\n"));
+
+    if (!win)
+        return ERR;
+
+    /* wrs (4/10/93) account for window background */
+
+    blank = win->_bkgd;
+
+    temp = win->_y[win->_cury];
+
+    for (y = win->_cury; y < win->_bmarg; y++)
+    {
+        win->_y[y] = win->_y[y + 1];
+        win->_firstch[y] = 0;
+        win->_lastch[y] = win->_maxx - 1;
+    }
+
+    for (ptr = temp; (ptr - temp < win->_maxx); ptr++)
+        *ptr = blank;           /* make a blank line */
+
+    if (win->_cury <= win->_bmarg) 
+    {
+        win->_firstch[win->_bmarg] = 0;
+        win->_lastch[win->_bmarg] = win->_maxx - 1;
+        win->_y[win->_bmarg] = temp;
+    }
+
+    return OK;
+}
+
+int deleteln(void)
+{
+    PDC_LOG(("deleteln() - called\n"));
+
+    return wdeleteln(stdscr);
+}
+
+int mvdeleteln(int y, int x)
+{
+    PDC_LOG(("mvdeleteln() - called\n"));
+
+    if (move(y, x) == ERR)
+        return ERR;
+
+    return wdeleteln(stdscr);
+}
+
+int mvwdeleteln(WINDOW *win, int y, int x)
+{
+    PDC_LOG(("mvwdeleteln() - called\n"));
+
+    if (wmove(win, y, x) == ERR)
+        return ERR;
+
+    return wdeleteln(win);
+}
+
+int winsdelln(WINDOW *win, int n)
+{
+    int i;
+
+    PDC_LOG(("winsdelln() - called\n"));
+
+    if (!win)
+        return ERR;
+
+    if (n > 0)
+    {
+        for (i = 0; i < n; i++)
+            if (winsertln(win) == ERR)
+                return ERR;
+    }
+    else if (n < 0)
+    {
+        n = -n;
+        for (i = 0; i < n; i++)
+            if (wdeleteln(win) == ERR)
+                return ERR;
+    }
+
+    return OK;
+}
+
+int insdelln(int n)
+{
+    PDC_LOG(("insdelln() - called\n"));
+
+    return winsdelln(stdscr, n);
+}
+
+int winsertln(WINDOW *win)
+{
+    chtype blank, *temp, *end;
+    int y;
+
+    PDC_LOG(("winsertln() - called\n"));
+
+    if (!win)
+        return ERR;
+
+    /* wrs (4/10/93) account for window background */
+
+    blank = win->_bkgd;
+
+    temp = win->_y[win->_maxy - 1];
+
+    for (y = win->_maxy - 1; y > win->_cury; y--)
+    {
+        win->_y[y] = win->_y[y - 1];
+        win->_firstch[y] = 0;
+        win->_lastch[y] = win->_maxx - 1;
+    }
+
+    win->_y[win->_cury] = temp;
+
+    for (end = &temp[win->_maxx - 1]; temp <= end; temp++)
+        *temp = blank;
+
+    win->_firstch[win->_cury] = 0;
+    win->_lastch[win->_cury] = win->_maxx - 1;
+
+    return OK;
+}
+
+int insertln(void)
+{
+    PDC_LOG(("insertln() - called\n"));
+
+    return winsertln(stdscr);
+}
+
+int mvinsertln(int y, int x)
+{
+    PDC_LOG(("mvinsertln() - called\n"));
+
+    if (move(y, x) == ERR)
+        return ERR;
+
+    return winsertln(stdscr);
+}
+
+int mvwinsertln(WINDOW *win, int y, int x)
+{
+    PDC_LOG(("mvwinsertln() - called\n"));
+
+    if (wmove(win, y, x) == ERR)
+        return ERR;
+
+    return winsertln(win);
+}
diff --git a/apps/lib/curses/pdcurses/pdcurses/deprec.c b/apps/lib/curses/pdcurses/pdcurses/deprec.c
new file mode 100644
index 0000000..83e6131
--- /dev/null
+++ b/apps/lib/curses/pdcurses/pdcurses/deprec.c
@@ -0,0 +1,29 @@
+/* Public Domain Curses */
+
+#include <curspriv.h>
+
+RCSID("$Id: deprec.c,v 1.6 2008/07/13 16:08:18 wmcbrine Exp $")
+
+/* Deprecated functions. These should not be used, and will eventually 
+   be removed. They're here solely for the benefit of applications that 
+   linked to them in older versions of PDCurses. */
+
+bool PDC_check_bios_key(void)
+{
+    return PDC_check_key();
+}
+
+int PDC_get_bios_key(void)
+{
+    return PDC_get_key();
+}
+
+bool PDC_get_ctrl_break(void)
+{
+    return !SP->raw_inp;
+}
+
+int PDC_set_ctrl_break(bool setting)
+{
+    return setting ? noraw() : raw();
+}
diff --git a/apps/lib/curses/pdcurses/pdcurses/getch.c b/apps/lib/curses/pdcurses/pdcurses/getch.c
new file mode 100644
index 0000000..87677ba
--- /dev/null
+++ b/apps/lib/curses/pdcurses/pdcurses/getch.c
@@ -0,0 +1,410 @@
+/* Public Domain Curses */
+
+#include <curspriv.h>
+
+RCSID("$Id: getch.c,v 1.72 2008/07/13 16:08:18 wmcbrine Exp $")
+
+/*man-start**************************************************************
+
+  Name:                                                         getch
+
+  Synopsis:
+        int getch(void);
+        int wgetch(WINDOW *win);
+        int mvgetch(int y, int x);
+        int mvwgetch(WINDOW *win, int y, int x);
+        int ungetch(int ch);
+        int flushinp(void);
+
+        int get_wch(wint_t *wch);
+        int wget_wch(WINDOW *win, wint_t *wch);
+        int mvget_wch(int y, int x, wint_t *wch);
+        int mvwget_wch(WINDOW *win, int y, int x, wint_t *wch);
+        int unget_wch(const wchar_t wch);
+
+        unsigned long PDC_get_key_modifiers(void);
+        int PDC_save_key_modifiers(bool flag);
+        int PDC_return_key_modifiers(bool flag);
+
+  Description:
+        With the getch(), wgetch(), mvgetch(), and mvwgetch() functions, 
+        a character is read from the terminal associated with the window. 
+        In nodelay mode, if there is no input waiting, the value ERR is 
+        returned. In delay mode, the program will hang until the system 
+        passes text through to the program. Depending on the setting of 
+        cbreak(), this will be after one character or after the first 
+        newline.  Unless noecho() has been set, the character will also 
+        be echoed into the designated window.
+
+        If keypad() is TRUE, and a function key is pressed, the token for
+        that function key will be returned instead of the raw characters.
+        Possible function keys are defined in <curses.h> with integers
+        beginning with 0401, whose names begin with KEY_.
+
+        If nodelay(win, TRUE) has been called on the window and no input
+        is waiting, the value ERR is returned.
+
+        ungetch() places ch back onto the input queue to be returned by 
+        the next call to wgetch().
+
+        flushinp() throws away any type-ahead that has been typed by the 
+        user and has not yet been read by the program.
+
+        PDC_get_key_modifiers() returns the keyboard modifiers (shift, 
+        control, alt, numlock) effective at the time of the last getch() 
+        call, if PDC_save_key_modifiers(TRUE) has been called before the 
+        getch(). Use the macros PDC_KEY_MODIFIER_* to determine which 
+        modifier(s) were set. PDC_return_key_modifiers() tells getch() 
+        to return modifier keys pressed alone as keystrokes (KEY_ALT_L, 
+        etc.). These may not work on all platforms.
+
+        NOTE: getch() and ungetch() are implemented as macros, to avoid 
+        conflict with many DOS compiler's runtime libraries.
+
+  Return Value:
+        These functions return ERR or the value of the character, meta 
+        character or function key token.
+
+  Portability                                X/Open    BSD    SYS V
+        getch                                   Y       Y       Y
+        wgetch                                  Y       Y       Y
+        mvgetch                                 Y       Y       Y
+        mvwgetch                                Y       Y       Y
+        ungetch                                 Y       Y       Y
+        flushinp                                Y       Y       Y
+        get_wch                                 Y
+        wget_wch                                Y
+        mvget_wch                               Y
+        mvwget_wch                              Y
+        unget_wch                               Y
+        PDC_get_key_modifiers                   -       -       -
+
+**man-end****************************************************************/
+
+#define _INBUFSIZ   512 /* size of terminal input buffer */
+#define NUNGETCH    256 /* max # chars to ungetch() */
+
+static int c_pindex = 0;    /* putter index */
+static int c_gindex = 1;    /* getter index */
+static int c_ungind = 0;    /* ungetch() push index */
+static int c_ungch[NUNGETCH];   /* array of ungotten chars */
+
+static int _mouse_key(WINDOW *win)
+{
+    int i, key = KEY_MOUSE;
+    unsigned long mbe = SP->_trap_mbe;
+
+    /* Filter unwanted mouse events */
+
+    for (i = 0; i < 3; i++)
+    {
+        if (pdc_mouse_status.changes & (1 << i))
+        {
+            int shf = i * 5;
+            short button = pdc_mouse_status.button[i] & BUTTON_ACTION_MASK;
+
+            if (   (!(mbe & (BUTTON1_PRESSED << shf)) &&
+                    (button == BUTTON_PRESSED))
+
+                || (!(mbe & (BUTTON1_CLICKED << shf)) &&
+                    (button == BUTTON_CLICKED))
+
+                || (!(mbe & (BUTTON1_DOUBLE_CLICKED << shf)) &&
+                    (button == BUTTON_DOUBLE_CLICKED))
+
+                || (!(mbe & (BUTTON1_MOVED << shf)) &&
+                    (button == BUTTON_MOVED))
+
+                || (!(mbe & (BUTTON1_RELEASED << shf)) &&
+                    (button == BUTTON_RELEASED))
+            )
+                pdc_mouse_status.changes ^= (1 << i);
+        }
+    }
+
+    if (pdc_mouse_status.changes & PDC_MOUSE_MOVED)
+    {
+        if (!(mbe & (BUTTON1_MOVED|BUTTON2_MOVED|BUTTON3_MOVED)))
+            pdc_mouse_status.changes ^= PDC_MOUSE_MOVED;
+    }
+
+    if (pdc_mouse_status.changes &
+        (PDC_MOUSE_WHEEL_UP|PDC_MOUSE_WHEEL_DOWN))
+    {
+        if (!(mbe & MOUSE_WHEEL_SCROLL))
+            pdc_mouse_status.changes &=
+                ~(PDC_MOUSE_WHEEL_UP|PDC_MOUSE_WHEEL_DOWN);
+    }
+
+    if (!pdc_mouse_status.changes)
+        return -1;
+
+    /* Check for click in slk area */
+
+    i = PDC_mouse_in_slk(pdc_mouse_status.y, pdc_mouse_status.x);
+
+    if (i)
+    {
+        if (pdc_mouse_status.button[0] & (BUTTON_PRESSED|BUTTON_CLICKED))
+            key = KEY_F(i);
+        else
+            key = -1;
+    }
+
+    return key;
+}
+
+int wgetch(WINDOW *win)
+{
+    static int buffer[_INBUFSIZ];   /* character buffer */
+    int key, waitcount;
+
+    PDC_LOG(("wgetch() - called\n"));
+
+    if (!win)
+        return ERR;
+
+    waitcount = 0;
+
+     /* set the number of 1/20th second napms() calls */
+
+    if (SP->delaytenths)
+        waitcount = 2 * SP->delaytenths;
+    else
+        if (win->_delayms)
+        {
+            /* Can't really do millisecond intervals, so delay in 
+               1/20ths of a second (50ms) */
+
+            waitcount = win->_delayms / 50;
+            if (!waitcount)
+                waitcount = 1;
+        }
+
+    /* refresh window when wgetch is called if there have been changes 
+       to it and it is not a pad */
+
+    if (!(win->_flags & _PAD) && ((!win->_leaveit &&
+         (win->_begx + win->_curx != SP->curscol ||
+          win->_begy + win->_cury != SP->cursrow)) || is_wintouched(win)))
+        wrefresh(win);
+
+    /* if ungotten char exists, remove and return it */
+
+    if (c_ungind)
+        return c_ungch[--c_ungind];
+
+    /* if normal and data in buffer */
+
+    if ((!SP->raw_inp && !SP->cbreak) && (c_gindex < c_pindex))
+        return buffer[c_gindex++];
+
+    /* prepare to buffer data */
+
+    c_pindex = 0;
+    c_gindex = 0;
+
+    /* to get here, no keys are buffered. go and get one. */
+
+    for (;;)            /* loop for any buffering */
+    {
+        /* is there a keystroke ready? */
+
+        if (!PDC_check_key())
+        {
+            /* if not, handle timeout() and halfdelay() */
+
+            if (SP->delaytenths || win->_delayms)
+            {
+                if (!waitcount)
+                    return ERR;
+
+                waitcount--;
+            }
+            else
+                if (win->_nodelay)
+                    return ERR;
+
+            napms(50);  /* sleep for 1/20th second */
+            continue;   /* then check again */
+        }
+
+        /* if there is, fetch it */
+
+        key = PDC_get_key();
+
+        if (SP->key_code)
+        {
+            /* filter special keys if not in keypad mode */
+
+            if (!win->_use_keypad)
+                key = -1;
+
+            /* filter mouse events; translate mouse clicks in the slk 
+               area to function keys */
+
+            else if (key == KEY_MOUSE)
+                key = _mouse_key(win);
+        }
+
+        /* unwanted key? loop back */
+
+        if (key == -1)
+            continue;
+
+        /* translate CR */
+
+        if (key == '\r' && SP->autocr && !SP->raw_inp)
+            key = '\n';
+
+        /* if echo is enabled */
+
+        if (SP->echo && !SP->key_code)
+        {
+            waddch(win, key);
+            wrefresh(win);
+        }
+
+        /* if no buffering */
+
+        if (SP->raw_inp || SP->cbreak)
+            return key;
+
+        /* if no overflow, put data in buffer */
+
+        if (key == '\b')
+        {
+            if (c_pindex > c_gindex)
+                c_pindex--;
+        }
+        else
+            if (c_pindex < _INBUFSIZ - 2)
+                buffer[c_pindex++] = key;
+
+        /* if we got a line */
+
+        if (key == '\n' || key == '\r')
+            return buffer[c_gindex++];
+    }
+}
+
+int mvgetch(int y, int x)
+{
+    PDC_LOG(("mvgetch() - called\n"));
+
+    if (move(y, x) == ERR)
+        return ERR;
+
+    return wgetch(stdscr);
+}
+
+int mvwgetch(WINDOW *win, int y, int x)
+{
+    PDC_LOG(("mvwgetch() - called\n"));
+
+    if (wmove(win, y, x) == ERR)
+        return ERR;
+
+    return wgetch(win);
+}
+
+int PDC_ungetch(int ch)
+{
+    PDC_LOG(("ungetch() - called\n"));
+
+    if (c_ungind >= NUNGETCH)   /* pushback stack full */
+        return ERR;
+
+    c_ungch[c_ungind++] = ch;
+
+    return OK;
+}
+
+int flushinp(void)
+{
+    PDC_LOG(("flushinp() - called\n"));
+
+    PDC_flushinp();
+
+    c_gindex = 1;           /* set indices to kill buffer */
+    c_pindex = 0;
+    c_ungind = 0;           /* clear c_ungch array */
+
+    return OK;
+}
+
+unsigned long PDC_get_key_modifiers(void)
+{
+    PDC_LOG(("PDC_get_key_modifiers() - called\n"));
+
+    return pdc_key_modifiers;
+}
+
+int PDC_save_key_modifiers(bool flag)
+{
+    PDC_LOG(("PDC_save_key_modifiers() - called\n"));
+
+    SP->save_key_modifiers = flag;
+    return OK;
+}
+
+int PDC_return_key_modifiers(bool flag)
+{
+    PDC_LOG(("PDC_return_key_modifiers() - called\n"));
+
+    SP->return_key_modifiers = flag;
+    return PDC_modifiers_set();
+}
+
+#ifdef PDC_WIDE
+int wget_wch(WINDOW *win, wint_t *wch)
+{
+    int key;
+
+    PDC_LOG(("wget_wch() - called\n"));
+
+    if (!wch)
+        return ERR;
+
+    key = wgetch(win);
+
+    if (key == ERR)
+        return ERR;
+
+    *wch = key;
+
+    return SP->key_code ? KEY_CODE_YES : OK;
+}
+
+int get_wch(wint_t *wch)
+{
+    PDC_LOG(("get_wch() - called\n"));
+
+    return wget_wch(stdscr, wch);
+}
+
+int mvget_wch(int y, int x, wint_t *wch)
+{
+    PDC_LOG(("mvget_wch() - called\n"));
+
+    if (move(y, x) == ERR)
+        return ERR;
+
+    return wget_wch(stdscr, wch);
+}
+
+int mvwget_wch(WINDOW *win, int y, int x, wint_t *wch)
+{
+    PDC_LOG(("mvwget_wch() - called\n"));
+
+    if (wmove(win, y, x) == ERR)
+        return ERR;
+
+    return wget_wch(win, wch);
+}
+
+int unget_wch(const wchar_t wch)
+{
+    return PDC_ungetch(wch);
+}
+#endif
diff --git a/apps/lib/curses/pdcurses/pdcurses/getstr.c b/apps/lib/curses/pdcurses/pdcurses/getstr.c
new file mode 100644
index 0000000..c6386d3
--- /dev/null
+++ b/apps/lib/curses/pdcurses/pdcurses/getstr.c
@@ -0,0 +1,471 @@
+/* Public Domain Curses */
+
+#include <curspriv.h>
+
+RCSID("$Id: getstr.c,v 1.51 2008/07/14 04:24:51 wmcbrine Exp $")
+
+/*man-start**************************************************************
+
+  Name:                                                         getstr
+
+  Synopsis:
+        int getstr(char *str);
+        int wgetstr(WINDOW *win, char *str);
+        int mvgetstr(int y, int x, char *str);
+        int mvwgetstr(WINDOW *win, int y, int x, char *str);
+        int getnstr(char *str, int n);
+        int wgetnstr(WINDOW *win, char *str, int n);
+        int mvgetnstr(int y, int x, char *str, int n);
+        int mvwgetnstr(WINDOW *win, int y, int x, char *str, int n);
+
+        int get_wstr(wint_t *wstr);
+        int wget_wstr(WINDOW *win, wint_t *wstr);
+        int mvget_wstr(int y, int x, wint_t *wstr);
+        int mvwget_wstr(WINDOW *win, int, int, wint_t *wstr);
+        int getn_wstr(wint_t *wstr, int n);
+        int wgetn_wstr(WINDOW *win, wint_t *wstr, int n);
+        int mvgetn_wstr(int y, int x, wint_t *wstr, int n);
+        int mvwgetn_wstr(WINDOW *win, int y, int x, wint_t *wstr, int n);
+
+  Description:
+        These routines call wgetch() repeatedly to build a string, 
+        interpreting erase and kill characters along the way, until a 
+        newline or carriage return is received. When PDCurses is built 
+        with wide-character support enabled, the narrow-character 
+        functions convert the wgetch()'d values into a multibyte string 
+        in the current locale before returning it. The resulting string 
+        is placed in the area pointed to by *str. The routines with n as 
+        the last argument read at most n characters.
+
+        Note that there's no way to know how long the buffer passed to 
+        wgetstr() is, so use wgetnstr() to avoid buffer overflows.
+
+  Return Value:
+        This functions return ERR on failure or any other value on 
+        success.
+
+  Portability                                X/Open    BSD    SYS V
+        getstr                                  Y       Y       Y
+        wgetstr                                 Y       Y       Y
+        mvgetstr                                Y       Y       Y
+        mvwgetstr                               Y       Y       Y
+        getnstr                                 Y       -      4.0
+        wgetnstr                                Y       -      4.0
+        mvgetnstr                               Y       -       -
+        mvwgetnstr                              Y       -       -
+        get_wstr                                Y
+        wget_wstr                               Y
+        mvget_wstr                              Y
+        mvwget_wstr                             Y
+        getn_wstr                               Y
+        wgetn_wstr                              Y
+        mvgetn_wstr                             Y
+        mvwgetn_wstr                            Y
+
+**man-end****************************************************************/
+
+#define MAXLINE 255
+
+int wgetnstr(WINDOW *win, char *str, int n)
+{
+#ifdef PDC_WIDE
+    wchar_t wstr[MAXLINE + 1];
+
+    if (n < 0 || n > MAXLINE)
+        n = MAXLINE;
+
+    if (wgetn_wstr(win, (wint_t *)wstr, n) == ERR)
+        return ERR;
+
+    return PDC_wcstombs(str, wstr, n);
+#else
+    int ch, i, num, x, chars;
+    char *p;
+    bool stop, oldecho, oldcbreak, oldnodelay;
+
+    PDC_LOG(("wgetnstr() - called\n"));
+
+    if (!win || !str)
+        return ERR;
+
+    chars = 0;
+    p = str;
+    stop = FALSE;
+
+    x = win->_curx;
+
+    oldcbreak = SP->cbreak; /* remember states */
+    oldecho = SP->echo;
+    oldnodelay = win->_nodelay;
+
+    SP->echo = FALSE;       /* we do echo ourselves */
+    cbreak();               /* ensure each key is returned immediately */
+    win->_nodelay = FALSE;  /* don't return -1 */
+
+    wrefresh(win);
+
+    while (!stop)
+    {
+        ch = wgetch(win);
+
+        switch (ch)
+        {
+
+        case '\t':
+            ch = ' ';
+            num = TABSIZE - (win->_curx - x) % TABSIZE;
+            for (i = 0; i < num; i++)
+            {
+                if (chars < n)
+                {
+                    if (oldecho) 
+                        waddch(win, ch);
+                    *p++ = ch;
+                    ++chars;
+                }
+                else
+                    beep();
+            }
+            break;
+
+        case _ECHAR:        /* CTRL-H -- Delete character */
+            if (p > str)
+            {
+                if (oldecho) 
+                    waddstr(win, "\b \b");
+                ch = (unsigned char)(*--p);
+                if ((ch < ' ') && (oldecho))
+                    waddstr(win, "\b \b");
+                chars--;
+            }
+            break;
+
+        case _DLCHAR:       /* CTRL-U -- Delete line */
+            while (p > str)
+            {
+                if (oldecho) 
+                    waddstr(win, "\b \b");
+                ch = (unsigned char)(*--p);
+                if ((ch < ' ') && (oldecho))
+                    waddstr(win, "\b \b");
+            }
+            chars = 0;
+            break;
+
+        case _DWCHAR:       /* CTRL-W -- Delete word */
+
+            while ((p > str) && (*(p - 1) == ' '))
+            {
+                if (oldecho) 
+                    waddstr(win, "\b \b");
+
+                --p;        /* remove space */
+                chars--;
+            }
+            while ((p > str) && (*(p - 1) != ' '))
+            {
+                if (oldecho) 
+                    waddstr(win, "\b \b");
+
+                ch = (unsigned char)(*--p);
+                if ((ch < ' ') && (oldecho))
+                    waddstr(win, "\b \b");
+                chars--;
+            }
+            break;
+
+        case '\n':
+        case '\r':
+            stop = TRUE;
+            if (oldecho) 
+                waddch(win, '\n');
+            break;
+
+        default:
+            if (chars < n)
+            {
+                if (!SP->key_code && ch < 0x100)
+                {
+                    *p++ = ch;
+                    if (oldecho) 
+                        waddch(win, ch);
+                    chars++;
+                }
+            }
+            else
+                beep();
+
+            break;
+      
+        }
+
+        wrefresh(win);
+    }
+
+    *p = '\0';
+
+    SP->echo = oldecho;     /* restore old settings */
+    SP->cbreak = oldcbreak;
+    win->_nodelay = oldnodelay;
+
+    return OK;
+#endif
+}
+
+int getstr(char *str)
+{
+    PDC_LOG(("getstr() - called\n"));
+
+    return wgetnstr(stdscr, str, MAXLINE);
+}
+
+int wgetstr(WINDOW *win, char *str)
+{
+    PDC_LOG(("wgetstr() - called\n"));
+
+    return wgetnstr(win, str, MAXLINE);
+}
+
+int mvgetstr(int y, int x, char *str)
+{
+    PDC_LOG(("mvgetstr() - called\n"));
+
+    if (move(y, x) == ERR)
+        return ERR;
+
+    return wgetnstr(stdscr, str, MAXLINE);
+}
+
+int mvwgetstr(WINDOW *win, int y, int x, char *str)
+{
+    PDC_LOG(("mvwgetstr() - called\n"));
+
+    if (wmove(win, y, x) == ERR)
+        return ERR;
+
+    return wgetnstr(win, str, MAXLINE);
+}
+
+int getnstr(char *str, int n)
+{
+    PDC_LOG(("getnstr() - called\n"));
+
+    return wgetnstr(stdscr, str, n);
+}
+
+int mvgetnstr(int y, int x, char *str, int n)
+{
+    PDC_LOG(("mvgetnstr() - called\n"));
+
+    if (move(y, x) == ERR)
+        return ERR;
+
+    return wgetnstr(stdscr, str, n);
+}
+
+int mvwgetnstr(WINDOW *win, int y, int x, char *str, int n)
+{
+    PDC_LOG(("mvwgetnstr() - called\n"));
+
+    if (wmove(win, y, x) == ERR)
+        return ERR;
+
+    return wgetnstr(win, str, n);
+}
+
+#ifdef PDC_WIDE
+int wgetn_wstr(WINDOW *win, wint_t *wstr, int n)
+{
+    int ch, i, num, x, chars;
+    wint_t *p;
+    bool stop, oldecho, oldcbreak, oldnodelay;
+
+    PDC_LOG(("wgetn_wstr() - called\n"));
+
+    if (!win || !wstr)
+        return ERR;
+
+    chars = 0;
+    p = wstr;
+    stop = FALSE;
+
+    x = win->_curx;
+
+    oldcbreak = SP->cbreak; /* remember states */
+    oldecho = SP->echo;
+    oldnodelay = win->_nodelay;
+
+    SP->echo = FALSE;       /* we do echo ourselves */
+    cbreak();               /* ensure each key is returned immediately */
+    win->_nodelay = FALSE;  /* don't return -1 */
+
+    wrefresh(win);
+
+    while (!stop)
+    {
+        ch = wgetch(win);
+
+        switch (ch)
+        {
+
+        case '\t':
+            ch = ' ';
+            num = TABSIZE - (win->_curx - x) % TABSIZE;
+            for (i = 0; i < num; i++)
+            {
+                if (chars < n)
+                {
+                    if (oldecho) 
+                        waddch(win, ch);
+                    *p++ = ch;
+                    ++chars;
+                }
+                else
+                    beep();
+            }
+            break;
+
+        case _ECHAR:        /* CTRL-H -- Delete character */
+            if (p > wstr)
+            {
+                if (oldecho) 
+                    waddstr(win, "\b \b");
+                ch = *--p;
+                if ((ch < ' ') && (oldecho))
+                    waddstr(win, "\b \b");
+                chars--;
+            }
+            break;
+
+        case _DLCHAR:       /* CTRL-U -- Delete line */
+            while (p > wstr)
+            {
+                if (oldecho) 
+                    waddstr(win, "\b \b");
+                ch = *--p;
+                if ((ch < ' ') && (oldecho))
+                    waddstr(win, "\b \b");
+            }
+            chars = 0;
+            break;
+
+        case _DWCHAR:       /* CTRL-W -- Delete word */
+
+            while ((p > wstr) && (*(p - 1) == ' '))
+            {
+                if (oldecho) 
+                    waddstr(win, "\b \b");
+
+                --p;        /* remove space */
+                chars--;
+            }
+            while ((p > wstr) && (*(p - 1) != ' '))
+            {
+                if (oldecho) 
+                    waddstr(win, "\b \b");
+
+                ch = *--p;
+                if ((ch < ' ') && (oldecho))
+                    waddstr(win, "\b \b");
+                chars--;
+            }
+            break;
+
+        case '\n':
+        case '\r':
+            stop = TRUE;
+            if (oldecho) 
+                waddch(win, '\n');
+            break;
+
+        default:
+            if (chars < n)
+            {
+                if (!SP->key_code)
+                {
+                    *p++ = ch;
+                    if (oldecho)
+                        waddch(win, ch);
+                    chars++;
+                }
+            }
+            else
+                beep();
+
+            break;
+      
+        }
+
+        wrefresh(win);
+    }
+
+    *p = '\0';
+
+    SP->echo = oldecho;     /* restore old settings */
+    SP->cbreak = oldcbreak;
+    win->_nodelay = oldnodelay;
+
+    return OK;
+}
+
+int get_wstr(wint_t *wstr)
+{
+    PDC_LOG(("get_wstr() - called\n"));
+
+    return wgetn_wstr(stdscr, wstr, MAXLINE);
+}
+
+int wget_wstr(WINDOW *win, wint_t *wstr)
+{
+    PDC_LOG(("wget_wstr() - called\n"));
+
+    return wgetn_wstr(win, wstr, MAXLINE);
+}
+
+int mvget_wstr(int y, int x, wint_t *wstr)
+{
+    PDC_LOG(("mvget_wstr() - called\n"));
+
+    if (move(y, x) == ERR)
+        return ERR;
+
+    return wgetn_wstr(stdscr, wstr, MAXLINE);
+}
+
+int mvwget_wstr(WINDOW *win, int y, int x, wint_t *wstr)
+{
+    PDC_LOG(("mvwget_wstr() - called\n"));
+
+    if (wmove(win, y, x) == ERR)
+        return ERR;
+
+    return wgetn_wstr(win, wstr, MAXLINE);
+}
+
+int getn_wstr(wint_t *wstr, int n)
+{
+    PDC_LOG(("getn_wstr() - called\n"));
+
+    return wgetn_wstr(stdscr, wstr, n);
+}
+
+int mvgetn_wstr(int y, int x, wint_t *wstr, int n)
+{
+    PDC_LOG(("mvgetn_wstr() - called\n"));
+
+    if (move(y, x) == ERR)
+        return ERR;
+
+    return wgetn_wstr(stdscr, wstr, n);
+}
+
+int mvwgetn_wstr(WINDOW *win, int y, int x, wint_t *wstr, int n)
+{
+    PDC_LOG(("mvwgetn_wstr() - called\n"));
+
+    if (wmove(win, y, x) == ERR)
+        return ERR;
+
+    return wgetn_wstr(win, wstr, n);
+}
+#endif
diff --git a/apps/lib/curses/pdcurses/pdcurses/getyx.c b/apps/lib/curses/pdcurses/pdcurses/getyx.c
new file mode 100644
index 0000000..fd0564d
--- /dev/null
+++ b/apps/lib/curses/pdcurses/pdcurses/getyx.c
@@ -0,0 +1,143 @@
+/* Public Domain Curses */
+
+#include <curspriv.h>
+
+RCSID("$Id: getyx.c,v 1.29 2008/07/15 17:13:26 wmcbrine Exp $")
+
+/*man-start**************************************************************
+
+  Name:                                                         getyx
+
+  Synopsis:
+        void getyx(WINDOW *win, int y, int x);
+        void getparyx(WINDOW *win, int y, int x);
+        void getbegyx(WINDOW *win, int y, int x);
+        void getmaxyx(WINDOW *win, int y, int x);
+
+        void getsyx(int y, int x);
+        int setsyx(int y, int x);
+
+        int getbegy(WINDOW *win);
+        int getbegx(WINDOW *win);
+        int getcury(WINDOW *win);
+        int getcurx(WINDOW *win);
+        int getpary(WINDOW *win);
+        int getparx(WINDOW *win);
+        int getmaxy(WINDOW *win);
+        int getmaxx(WINDOW *win);
+
+  Description:
+        The getyx() macro (defined in curses.h -- the prototypes here 
+        are merely illustrative) puts the current cursor position of the 
+        specified window into y and x. getbegyx() and getmaxyx() return 
+        the starting coordinates and size of the specified window, 
+        respectively. getparyx() returns the starting coordinates of the 
+        parent's window, if the specified window is a subwindow; 
+        otherwise it sets y and x to -1. These are all macros.
+
+        getsyx() gets the coordinates of the virtual screen cursor, and
+        stores them in y and x. If leaveok() is TRUE, it returns -1, -1.
+        If lines have been removed with ripoffline(), then getsyx()
+        includes these lines in its count; so, the returned y and x
+        values should only be used with setsyx().
+
+        setsyx() sets the virtual screen cursor to the y, x coordinates.
+        If y, x are -1, -1, leaveok() is set TRUE.
+
+        getsyx() and setsyx() are meant to be used by a library routine
+        that manipulates curses windows without altering the position of
+        the cursor. Note that getsyx() is defined only as a macro.
+
+        getbegy(), getbegx(), getcurx(), getcury(), getmaxy(),
+        getmaxx(), getpary(), and getparx() return the appropriate
+        coordinate or size values, or ERR in the case of a NULL window.
+
+  Portability                                X/Open    BSD    SYS V
+        getyx                                   Y       Y       Y
+        getparyx                                -       -      4.0
+        getbegyx                                -       -      3.0
+        getmaxyx                                -       -      3.0
+        getsyx                                  -       -      3.0
+        setsyx                                  -       -      3.0
+        getbegy                                 -       -       -
+        getbegx                                 -       -       -
+        getcury                                 -       -       -
+        getcurx                                 -       -       -
+        getpary                                 -       -       -
+        getparx                                 -       -       -
+        getmaxy                                 -       -       -
+        getmaxx                                 -       -       -
+
+**man-end****************************************************************/
+
+int getbegy(WINDOW *win)
+{
+    PDC_LOG(("getbegy() - called\n"));
+
+    return win ? win->_begy : ERR;
+}
+
+int getbegx(WINDOW *win)
+{
+    PDC_LOG(("getbegx() - called\n"));
+
+    return win ? win->_begx : ERR;
+}
+
+int getcury(WINDOW *win)
+{
+    PDC_LOG(("getcury() - called\n"));
+
+    return win ? win->_cury : ERR;
+}
+
+int getcurx(WINDOW *win)
+{
+    PDC_LOG(("getcurx() - called\n"));
+
+    return win ? win->_curx : ERR;
+}
+
+int getpary(WINDOW *win)
+{
+    PDC_LOG(("getpary() - called\n"));
+
+    return win ? win->_pary : ERR;
+}
+
+int getparx(WINDOW *win)
+{
+    PDC_LOG(("getparx() - called\n"));
+
+    return win ? win->_parx : ERR;
+}
+
+int getmaxy(WINDOW *win)
+{
+    PDC_LOG(("getmaxy() - called\n"));
+
+    return win ? win->_maxy : ERR;
+}
+
+int getmaxx(WINDOW *win)
+{
+    PDC_LOG(("getmaxx() - called\n"));
+
+    return win ? win->_maxx : ERR;
+}
+
+int setsyx(int y, int x)
+{
+    PDC_LOG(("setsyx() - called\n"));
+
+    if(y == -1 && x == -1)
+    {
+        curscr->_leaveit = TRUE;
+        return OK;
+    }
+    else
+    {
+        curscr->_leaveit = FALSE;
+        return wmove(curscr, y, x);
+    }
+}
diff --git a/apps/lib/curses/pdcurses/pdcurses/inch.c b/apps/lib/curses/pdcurses/pdcurses/inch.c
new file mode 100644
index 0000000..7347e74
--- /dev/null
+++ b/apps/lib/curses/pdcurses/pdcurses/inch.c
@@ -0,0 +1,125 @@
+/* Public Domain Curses */
+
+#include <curspriv.h>
+
+RCSID("$Id: inch.c,v 1.33 2008/07/13 16:08:18 wmcbrine Exp $")
+
+/*man-start**************************************************************
+
+  Name:                                                         inch
+
+  Synopsis:
+        chtype inch(void);
+        chtype winch(WINDOW *win);
+        chtype mvinch(int y, int x);
+        chtype mvwinch(WINDOW *win, int y, int x);
+
+        int in_wch(cchar_t *wcval);
+        int win_wch(WINDOW *win, cchar_t *wcval);
+        int mvin_wch(int y, int x, cchar_t *wcval);
+        int mvwin_wch(WINDOW *win, int y, int x, cchar_t *wcval);
+
+  Description:
+        The inch() functions retrieve the character and attribute from 
+        the current or specified window position, in the form of a 
+        chtype. If a NULL window is specified, (chtype)ERR is returned.
+
+        The in_wch() functions are the wide-character versions; instead 
+        of returning a chtype, they store a cchar_t at the address 
+        specified by wcval, and return OK or ERR. (No value is stored 
+        when ERR is returned.) Note that in PDCurses, chtype and cchar_t 
+        are the same.
+
+  Portability                                X/Open    BSD    SYS V
+        inch                                    Y       Y       Y
+        winch                                   Y       Y       Y
+        mvinch                                  Y       Y       Y
+        mvwinch                                 Y       Y       Y
+        in_wch                                  Y
+        win_wch                                 Y
+        mvin_wch                                Y
+        mvwin_wch                               Y
+
+**man-end****************************************************************/
+
+chtype winch(WINDOW *win)
+{
+    PDC_LOG(("winch() - called\n"));
+
+    if (!win)
+        return (chtype)ERR;
+
+    return win->_y[win->_cury][win->_curx];
+}
+
+chtype inch(void)
+{
+    PDC_LOG(("inch() - called\n"));
+
+    return winch(stdscr);
+}
+
+chtype mvinch(int y, int x)
+{
+    PDC_LOG(("mvinch() - called\n"));
+
+    if (move(y, x) == ERR)
+        return (chtype)ERR;
+
+    return stdscr->_y[stdscr->_cury][stdscr->_curx];
+}
+
+chtype mvwinch(WINDOW *win, int y, int x)
+{
+    PDC_LOG(("mvwinch() - called\n"));
+
+    if (wmove(win, y, x) == ERR)
+        return (chtype)ERR;
+
+    return win->_y[win->_cury][win->_curx];
+}
+
+#ifdef PDC_WIDE
+int win_wch(WINDOW *win, cchar_t *wcval)
+{
+    PDC_LOG(("win_wch() - called\n"));
+
+    if (!win || !wcval)
+        return ERR;
+
+    *wcval = win->_y[win->_cury][win->_curx];
+
+    return OK;
+}
+
+int in_wch(cchar_t *wcval)
+{
+    PDC_LOG(("in_wch() - called\n"));
+
+    return win_wch(stdscr, wcval);
+}
+
+int mvin_wch(int y, int x, cchar_t *wcval)
+{
+    PDC_LOG(("mvin_wch() - called\n"));
+
+    if (!wcval || (move(y, x) == ERR))
+        return ERR;
+
+    *wcval = stdscr->_y[stdscr->_cury][stdscr->_curx];
+
+    return OK;
+}
+
+int mvwin_wch(WINDOW *win, int y, int x, cchar_t *wcval)
+{
+    PDC_LOG(("mvwin_wch() - called\n"));
+
+    if (!wcval || (wmove(win, y, x) == ERR))
+        return ERR;
+
+    *wcval = win->_y[win->_cury][win->_curx];
+
+    return OK;
+}
+#endif
diff --git a/apps/lib/curses/pdcurses/pdcurses/inchstr.c b/apps/lib/curses/pdcurses/pdcurses/inchstr.c
new file mode 100644
index 0000000..50b8cf5
--- /dev/null
+++ b/apps/lib/curses/pdcurses/pdcurses/inchstr.c
@@ -0,0 +1,211 @@
+/* Public Domain Curses */
+
+#include <curspriv.h>
+
+RCSID("$Id: inchstr.c,v 1.34 2008/07/13 16:08:18 wmcbrine Exp $")
+
+/*man-start**************************************************************
+
+  Name:                                                         inchstr
+
+  Synopsis:
+        int inchstr(chtype *ch);
+        int inchnstr(chtype *ch, int n);
+        int winchstr(WINDOW *win, chtype *ch);
+        int winchnstr(WINDOW *win, chtype *ch, int n);
+        int mvinchstr(int y, int x, chtype *ch);
+        int mvinchnstr(int y, int x, chtype *ch, int n);
+        int mvwinchstr(WINDOW *, int y, int x, chtype *ch);
+        int mvwinchnstr(WINDOW *, int y, int x, chtype *ch, int n);
+
+        int in_wchstr(cchar_t *wch);
+        int in_wchnstr(cchar_t *wch, int n);
+        int win_wchstr(WINDOW *win, cchar_t *wch);
+        int win_wchnstr(WINDOW *win, cchar_t *wch, int n);
+        int mvin_wchstr(int y, int x, cchar_t *wch);
+        int mvin_wchnstr(int y, int x, cchar_t *wch, int n);
+        int mvwin_wchstr(WINDOW *win, int y, int x, cchar_t *wch);
+        int mvwin_wchnstr(WINDOW *win, int y, int x, cchar_t *wch, int n);
+
+  Description:
+        These routines read a chtype or cchar_t string from the window, 
+        starting at the current or specified position, and ending at the 
+        right margin, or after n elements, whichever is less.
+
+  Return Value:
+        All functions return the number of elements read, or ERR on 
+        error.
+
+  Portability                                X/Open    BSD    SYS V
+        inchstr                                 Y       -      4.0
+        winchstr                                Y       -      4.0
+        mvinchstr                               Y       -      4.0
+        mvwinchstr                              Y       -      4.0
+        inchnstr                                Y       -      4.0
+        winchnstr                               Y       -      4.0
+        mvinchnstr                              Y       -      4.0
+        mvwinchnstr                             Y       -      4.0
+        in_wchstr                               Y
+        win_wchstr                              Y
+        mvin_wchstr                             Y
+        mvwin_wchstr                            Y
+        in_wchnstr                              Y
+        win_wchnstr                             Y
+        mvin_wchnstr                            Y
+        mvwin_wchnstr                           Y
+
+**man-end****************************************************************/
+
+int winchnstr(WINDOW *win, chtype *ch, int n)
+{
+    chtype *src;
+    int i;
+
+    PDC_LOG(("winchnstr() - called\n"));
+
+    if (!win || !ch || n < 0)
+        return ERR;
+
+    if ((win->_curx + n) > win->_maxx)
+        n = win->_maxx - win->_curx;
+
+    src = win->_y[win->_cury] + win->_curx;
+
+    for (i = 0; i < n; i++)
+        *ch++ = *src++;
+
+    *ch = (chtype)0;
+
+    return OK;
+}
+
+int inchstr(chtype *ch)
+{
+    PDC_LOG(("inchstr() - called\n"));
+
+    return winchnstr(stdscr, ch, stdscr->_maxx - stdscr->_curx);
+}
+
+int winchstr(WINDOW *win, chtype *ch)
+{
+    PDC_LOG(("winchstr() - called\n"));
+
+    return winchnstr(win, ch, win->_maxx - win->_curx);
+}
+
+int mvinchstr(int y, int x, chtype *ch)
+{
+    PDC_LOG(("mvinchstr() - called: y %d x %d\n", y, x));
+
+    if (move(y, x) == ERR)
+        return ERR;
+
+    return winchnstr(stdscr, ch, stdscr->_maxx - stdscr->_curx);
+}
+
+int mvwinchstr(WINDOW *win, int y, int x, chtype *ch)
+{
+    PDC_LOG(("mvwinchstr() - called:\n"));
+
+    if (wmove(win, y, x) == ERR)
+        return ERR;
+
+    return winchnstr(win, ch, win->_maxx - win->_curx);
+}
+
+int inchnstr(chtype *ch, int n)
+{
+    PDC_LOG(("inchnstr() - called\n"));
+
+    return winchnstr(stdscr, ch, n);
+}
+
+int mvinchnstr(int y, int x, chtype *ch, int n)
+{
+    PDC_LOG(("mvinchnstr() - called: y %d x %d n %d\n", y, x, n));
+
+    if (move(y, x) == ERR)
+        return ERR;
+
+    return winchnstr(stdscr, ch, n);
+}
+
+int mvwinchnstr(WINDOW *win, int y, int x, chtype *ch, int n)
+{
+    PDC_LOG(("mvwinchnstr() - called: y %d x %d n %d \n", y, x, n));
+
+    if (wmove(win, y, x) == ERR)
+        return ERR;
+
+    return winchnstr(win, ch, n);
+}
+
+#ifdef PDC_WIDE
+int win_wchnstr(WINDOW *win, cchar_t *wch, int n)
+{
+    PDC_LOG(("win_wchnstr() - called\n"));
+
+    return winchnstr(win, wch, n);
+}
+
+int in_wchstr(cchar_t *wch)
+{
+    PDC_LOG(("in_wchstr() - called\n"));
+
+    return win_wchnstr(stdscr, wch, stdscr->_maxx - stdscr->_curx);
+}
+
+int win_wchstr(WINDOW *win, cchar_t *wch)
+{
+    PDC_LOG(("win_wchstr() - called\n"));
+
+    return win_wchnstr(win, wch, win->_maxx - win->_curx);
+}
+
+int mvin_wchstr(int y, int x, cchar_t *wch)
+{
+    PDC_LOG(("mvin_wchstr() - called: y %d x %d\n", y, x));
+
+    if (move(y, x) == ERR)
+        return ERR;
+
+    return win_wchnstr(stdscr, wch, stdscr->_maxx - stdscr->_curx);
+}
+
+int mvwin_wchstr(WINDOW *win, int y, int x, cchar_t *wch)
+{
+    PDC_LOG(("mvwin_wchstr() - called:\n"));
+
+    if (wmove(win, y, x) == ERR)
+        return ERR;
+
+    return win_wchnstr(win, wch, win->_maxx - win->_curx);
+}
+
+int in_wchnstr(cchar_t *wch, int n)
+{
+    PDC_LOG(("in_wchnstr() - called\n"));
+
+    return win_wchnstr(stdscr, wch, n);
+}
+
+int mvin_wchnstr(int y, int x, cchar_t *wch, int n)
+{
+    PDC_LOG(("mvin_wchnstr() - called: y %d x %d n %d\n", y, x, n));
+
+    if (move(y, x) == ERR)
+        return ERR;
+
+    return win_wchnstr(stdscr, wch, n);
+}
+
+int mvwin_wchnstr(WINDOW *win, int y, int x, cchar_t *wch, int n)
+{
+    PDC_LOG(("mvwinchnstr() - called: y %d x %d n %d \n", y, x, n));
+
+    if (wmove(win, y, x) == ERR)
+        return ERR;
+
+    return win_wchnstr(win, wch, n);
+}
+#endif
diff --git a/apps/lib/curses/pdcurses/pdcurses/initscr.c b/apps/lib/curses/pdcurses/pdcurses/initscr.c
new file mode 100644
index 0000000..d80fa0c
--- /dev/null
+++ b/apps/lib/curses/pdcurses/pdcurses/initscr.c
@@ -0,0 +1,339 @@
+/* Public Domain Curses */
+
+#include <curspriv.h>
+
+RCSID("$Id: initscr.c,v 1.114 2008/07/13 16:08:18 wmcbrine Exp $")
+
+/*man-start**************************************************************
+
+  Name:                                                         initscr
+
+  Synopsis:
+        WINDOW *initscr(void);
+        WINDOW *Xinitscr(int argc, char *argv[]);
+        int endwin(void);
+        bool isendwin(void);
+        SCREEN *newterm(const char *type, FILE *outfd, FILE *infd);
+        SCREEN *set_term(SCREEN *new);
+        void delscreen(SCREEN *sp);
+
+        int resize_term(int nlines, int ncols);
+        bool is_termresized(void);
+        const char *curses_version(void);
+
+  Description:
+        initscr() should be the first curses routine called.  It will 
+        initialize all curses data structures, and arrange that the 
+        first call to refresh() will clear the screen.  In case of 
+        error, initscr() will write a message to standard error and end 
+        the program.
+
+        endwin() should be called before exiting or escaping from curses 
+        mode temporarily.  It will restore tty modes, move the cursor to 
+        the lower left corner of the screen and reset the terminal into 
+        the proper non-visual mode.  To resume curses after a temporary 
+        escape, call refresh() or doupdate().
+
+        isendwin() returns TRUE if endwin() has been called without a 
+        subsequent refresh, unless SP is NULL.
+
+        In some implementations of curses, newterm() allows the use of 
+        multiple terminals. Here, it's just an alternative interface for 
+        initscr(). It always returns SP, or NULL.
+
+        delscreen() frees the memory allocated by newterm() or
+        initscr(), since it's not freed by endwin(). This function is
+        usually not needed. In PDCurses, the parameter must be the
+        value of SP, and delscreen() sets SP to NULL.
+
+        set_term() does nothing meaningful in PDCurses, but is included 
+        for compatibility with other curses implementations.
+
+        resize_term() is effectively two functions: When called with 
+        nonzero values for nlines and ncols, it attempts to resize the 
+        screen to the given size. When called with (0, 0), it merely 
+        adjusts the internal structures to match the current size after 
+        the screen is resized by the user. On the currently supported 
+        platforms, this functionality is mutually exclusive: X11 allows 
+        user resizing, while DOS, OS/2 and Win32 allow programmatic 
+        resizing. If you want to support user resizing, you should check 
+        for getch() returning KEY_RESIZE, and/or call is_termresized() 
+        at appropriate times; if either condition occurs, call 
+        resize_term(0, 0). Then, with either user or programmatic 
+        resizing, you'll have to resize any windows you've created, as 
+        appropriate; resize_term() only handles stdscr and curscr.
+
+        is_termresized() returns TRUE if the curses screen has been
+        resized by the user, and a call to resize_term() is needed. 
+        Checking for KEY_RESIZE is generally preferable, unless you're 
+        not handling the keyboard.
+
+        curses_version() returns a string describing the version of 
+        PDCurses.
+
+  Return Value:
+        All functions return NULL on error, except endwin(), which
+        returns ERR on error.
+
+  Portability                                X/Open    BSD    SYS V
+        initscr                                 Y       Y       Y
+        endwin                                  Y       Y       Y
+        isendwin                                Y       -      3.0
+        newterm                                 Y       -       Y
+        set_term                                Y       -       Y
+        delscreen                               Y       -      4.0
+        resize_term                             -       -       -
+        is_termresized                          -       -       -
+        curses_version                          -       -       -
+
+**man-end****************************************************************/
+
+#include <stdlib.h>
+
+char ttytype[128];
+
+const char *_curses_notice = "PDCurses 3.4 - Public Domain 2008";
+
+SCREEN *SP = (SCREEN*)NULL;           /* curses variables */
+WINDOW *curscr = (WINDOW *)NULL;      /* the current screen image */
+WINDOW *stdscr = (WINDOW *)NULL;      /* the default screen window */
+WINDOW *pdc_lastscr = (WINDOW *)NULL; /* the last screen image */
+
+int LINES = 0;                        /* current terminal height */
+int COLS = 0;                         /* current terminal width */
+int TABSIZE = 8;
+
+MOUSE_STATUS Mouse_status, pdc_mouse_status;
+
+extern RIPPEDOFFLINE linesripped[5];
+extern char linesrippedoff;
+
+WINDOW *Xinitscr(int argc, char *argv[])
+{
+    int i;
+
+    PDC_LOG(("Xinitscr() - called\n"));
+
+    if (SP && SP->alive)
+        return NULL;
+
+    if (PDC_scr_open(argc, argv) == ERR)
+    {
+        fprintf(stderr, "initscr(): Unable to create SP\n");
+        exit(8);
+    }
+
+    SP->autocr = TRUE;       /* cr -> lf by default */
+    SP->raw_out = FALSE;     /* tty I/O modes */
+    SP->raw_inp = FALSE;     /* tty I/O modes */
+    SP->cbreak = TRUE;
+    SP->save_key_modifiers = FALSE;
+    SP->return_key_modifiers = FALSE;
+    SP->echo = TRUE;
+    SP->visibility = 1;
+    SP->resized = FALSE;
+    SP->_trap_mbe = 0L;
+    SP->_map_mbe_to_key = 0L;
+    SP->linesrippedoff = 0;
+    SP->linesrippedoffontop = 0;
+    SP->delaytenths = 0;
+    SP->line_color = -1;
+
+    SP->orig_cursor = PDC_get_cursor_mode();
+
+    LINES = SP->lines;
+    COLS = SP->cols;
+
+    if (LINES < 2 || COLS < 2)
+    {
+        fprintf(stderr, "initscr(): LINES=%d COLS=%d: too small.\n",
+                LINES, COLS);
+        exit(4);
+    }
+
+    if ((curscr = newwin(LINES, COLS, 0, 0)) == (WINDOW *)NULL)
+    {
+        fprintf(stderr, "initscr(): Unable to create curscr.\n");
+        exit(2);
+    }
+
+    if ((pdc_lastscr = newwin(LINES, COLS, 0, 0)) == (WINDOW *)NULL)
+    {
+        fprintf(stderr, "initscr(): Unable to create pdc_lastscr.\n");
+        exit(2);
+    }
+
+    wattrset(pdc_lastscr, (chtype)(-1));
+    werase(pdc_lastscr);
+
+    PDC_slk_initialize();
+    LINES -= SP->slklines;
+
+    /* We have to sort out ripped off lines here, and reduce the height 
+       of stdscr by the number of lines ripped off */
+
+    for (i = 0; i < linesrippedoff; i++)
+    {
+        if (linesripped[i].line < 0)
+            (*linesripped[i].init)(newwin(1, COLS, LINES - 1, 0), COLS);
+        else
+            (*linesripped[i].init)(newwin(1, COLS,
+                                   SP->linesrippedoffontop++, 0), COLS);
+
+        SP->linesrippedoff++;
+        LINES--;
+    }
+
+    linesrippedoff = 0;
+
+    if (!(stdscr = newwin(LINES, COLS, SP->linesrippedoffontop, 0)))
+    {
+        fprintf(stderr, "initscr(): Unable to create stdscr.\n");
+        exit(1);
+    }
+
+    wclrtobot(stdscr);
+
+    /* If preserving the existing screen, don't allow a screen clear */
+
+    if (SP->_preserve)
+    {
+        untouchwin(curscr);
+        untouchwin(stdscr);
+        stdscr->_clear = FALSE;
+        curscr->_clear = FALSE;
+    }
+    else
+        curscr->_clear = TRUE;
+
+    PDC_init_atrtab();  /* set up default colors */
+
+    MOUSE_X_POS = MOUSE_Y_POS = -1;
+    BUTTON_STATUS(1) = BUTTON_RELEASED;
+    BUTTON_STATUS(2) = BUTTON_RELEASED;
+    BUTTON_STATUS(3) = BUTTON_RELEASED;
+    Mouse_status.changes = 0;
+
+    SP->alive = TRUE;
+
+    def_shell_mode();
+
+    sprintf(ttytype, "pdcurses|PDCurses for %s", PDC_sysname());
+
+    return stdscr;
+}
+
+WINDOW *initscr(void)
+{
+    PDC_LOG(("initscr() - called\n"));
+
+    return Xinitscr(0, NULL);
+}
+
+int endwin(void)
+{
+    PDC_LOG(("endwin() - called\n"));
+
+    /* Allow temporary exit from curses using endwin() */
+
+    def_prog_mode();
+    PDC_scr_close();
+
+    SP->alive = FALSE;
+
+    return OK;
+}
+
+bool isendwin(void)
+{
+    PDC_LOG(("isendwin() - called\n"));
+    
+    return SP ? !(SP->alive) : FALSE;
+}
+
+SCREEN *newterm(const char *type, FILE *outfd, FILE *infd)
+{
+    PDC_LOG(("newterm() - called\n"));
+
+    return Xinitscr(0, NULL) ? SP : NULL;
+}
+
+SCREEN *set_term(SCREEN *new)
+{
+    PDC_LOG(("set_term() - called\n"));
+
+    /* We only support one screen */
+
+    return (new == SP) ? SP : NULL;
+}
+
+void delscreen(SCREEN *sp)
+{
+    PDC_LOG(("delscreen() - called\n"));
+
+    if (sp != SP)
+        return;
+
+    PDC_slk_free();     /* free the soft label keys, if needed */
+
+    delwin(stdscr);
+    delwin(curscr);
+    delwin(pdc_lastscr);
+    stdscr = (WINDOW *)NULL;
+    curscr = (WINDOW *)NULL;
+    pdc_lastscr = (WINDOW *)NULL;
+
+    SP->alive = FALSE;
+
+    PDC_scr_free();     /* free SP and pdc_atrtab */
+
+    SP = (SCREEN *)NULL;
+}
+
+int resize_term(int nlines, int ncols)
+{
+    PDC_LOG(("resize_term() - called: nlines %d\n", nlines));
+
+    if (!stdscr || PDC_resize_screen(nlines, ncols) == ERR)
+        return ERR;
+
+    SP->lines = PDC_get_rows();
+    LINES = SP->lines - SP->linesrippedoff - SP->slklines;
+    SP->cols = COLS = PDC_get_columns();
+
+    if (wresize(curscr, SP->lines, SP->cols) == ERR ||
+        wresize(stdscr, LINES, COLS) == ERR ||
+        wresize(pdc_lastscr, SP->lines, SP->cols) == ERR)
+        return ERR;
+
+    werase(pdc_lastscr);
+    curscr->_clear = TRUE;
+
+    if (SP->slk_winptr)
+    {
+        if (wresize(SP->slk_winptr, SP->slklines, COLS) == ERR)
+            return ERR;
+
+        wmove(SP->slk_winptr, 0, 0);
+        wclrtobot(SP->slk_winptr);
+        PDC_slk_initialize();
+        slk_noutrefresh();
+    }
+
+    touchwin(stdscr);
+    wnoutrefresh(stdscr);
+
+    return OK;
+}
+
+bool is_termresized(void)
+{
+    PDC_LOG(("is_termresized() - called\n"));
+
+    return SP->resized;
+}
+
+const char *curses_version(void)
+{
+    return _curses_notice;
+}
diff --git a/apps/lib/curses/pdcurses/pdcurses/inopts.c b/apps/lib/curses/pdcurses/pdcurses/inopts.c
new file mode 100644
index 0000000..6d33fc2
--- /dev/null
+++ b/apps/lib/curses/pdcurses/pdcurses/inopts.c
@@ -0,0 +1,321 @@
+/* Public Domain Curses */
+
+#include <curspriv.h>
+
+RCSID("$Id: inopts.c,v 1.43 2008/07/13 16:08:18 wmcbrine Exp $")
+
+/*man-start**************************************************************
+
+  Name:                                                         inopts
+
+  Synopsis:
+        int cbreak(void);
+        int nocbreak(void);
+        int echo(void);
+        int noecho(void);
+        int halfdelay(int tenths);
+        int intrflush(WINDOW *win, bool bf);
+        int keypad(WINDOW *win, bool bf);
+        int meta(WINDOW *win, bool bf);
+        int nl(void);
+        int nonl(void);
+        int nodelay(WINDOW *win, bool bf);
+        int notimeout(WINDOW *win, bool bf);
+        int raw(void);
+        int noraw(void);
+        void noqiflush(void);
+        void qiflush(void);
+        void timeout(int delay);
+        void wtimeout(WINDOW *win, int delay);
+        int typeahead(int fildes);
+
+        int crmode(void);
+        int nocrmode(void);
+
+  Description:
+        cbreak() and nocbreak() toggle cbreak mode. In cbreak mode, 
+        characters typed by the user are made available immediately, and 
+        erase/kill character processing is not performed.  In nocbreak 
+        mode, typed characters are buffered until a newline or carriage 
+        return. Interrupt and flow control characters are unaffected by 
+        this mode. PDCurses always starts in cbreak mode.
+
+        echo() and noecho() control whether typed characters are echoed 
+        by the input routine.  Initially, input characters are echoed.  
+        Subsequent calls to echo() and noecho() do not flush type-ahead.
+
+        halfdelay() is similar to cbreak(), but allows for a time limit 
+        to be specified, in tenths of a second. This causes getch() to 
+        block for that period before returning ERR if no key has been 
+        received.  tenths must be between 1 and 255.
+
+        keypad() controls whether getch() returns function/special keys 
+        as single key codes (e.g., the left arrow key as KEY_LEFT). Per 
+        X/Open, the default for keypad mode is OFF. You'll probably want 
+        it on. With keypad mode off, if a special key is pressed, 
+        getch() does nothing or returns ERR.
+
+        nodelay() controls whether wgetch() is a non-blocking call. If 
+        the option is enabled, and no input is ready, wgetch() will 
+        return ERR. If disabled, wgetch() will hang until input is 
+        ready.
+
+        nl() enables the translation of a carriage return into a newline 
+        on input. nonl() disables this. Initially, the translation does 
+        occur.
+
+        raw() and noraw() toggle raw mode. Raw mode is similar to cbreak 
+        mode, in that characters typed are immediately passed through to 
+        the user program.  The difference is that in raw mode, the INTR, 
+        QUIT, SUSP, and STOP characters are passed through without being 
+        interpreted, and without generating a signal.
+
+        In PDCurses, the meta() function sets raw mode on or off.
+
+        timeout() and wtimeout() set blocking or non-blocking reads for 
+        the specified window. The delay is measured in milliseconds. If 
+        it's negative, a blocking read is used; if zero, then non- 
+        blocking reads are done -- if no input is waiting, ERR is 
+        returned immediately. If the delay is positive, the read blocks 
+        for the delay period; if the period expires, ERR is returned.
+
+        intrflush(), notimeout(), noqiflush(), qiflush() and typeahead()
+        do nothing in PDCurses, but are included for compatibility with 
+        other curses implementations.
+
+        crmode() and nocrmode() are archaic equivalents to cbreak() and 
+        nocbreak(), respectively.
+
+  Return Value:
+        All functions return OK on success and ERR on error.
+
+  Portability                                X/Open    BSD    SYS V
+        cbreak                                  Y       Y       Y
+        nocbreak                                Y       Y       Y
+        echo                                    Y       Y       Y
+        noecho                                  Y       Y       Y
+        halfdelay                               Y       -       Y
+        intrflush                               Y       -       Y
+        keypad                                  Y       -       Y
+        meta                                    Y       -       Y
+        nl                                      Y       Y       Y
+        nonl                                    Y       Y       Y
+        nodelay                                 Y       -       Y
+        notimeout                               Y       -       Y
+        raw                                     Y       Y       Y
+        noraw                                   Y       Y       Y
+        noqiflush                               Y       -       Y
+        qiflush                                 Y       -       Y
+        timeout                                 Y       -       Y
+        wtimeout                                Y       -       Y
+        typeahead                               Y       -       Y
+        crmode                                  -
+        nocrmode                                -
+
+**man-end****************************************************************/
+
+int cbreak(void)
+{
+    PDC_LOG(("cbreak() - called\n"));
+
+    SP->cbreak = TRUE;
+
+    return OK;
+}
+
+int nocbreak(void)
+{
+    PDC_LOG(("nocbreak() - called\n"));
+
+    SP->cbreak = FALSE;
+    SP->delaytenths = 0;
+
+    return OK;
+}
+
+int echo(void)
+{
+    PDC_LOG(("echo() - called\n"));
+
+    SP->echo = TRUE;
+
+    return OK;
+}
+
+int noecho(void)
+{
+    PDC_LOG(("noecho() - called\n"));
+
+    SP->echo = FALSE;
+
+    return OK;
+}
+
+int halfdelay(int tenths)
+{
+    PDC_LOG(("halfdelay() - called\n"));
+
+    if (tenths < 1 || tenths > 255)
+        return ERR;
+
+    SP->delaytenths = tenths;
+
+    return OK;
+}
+
+int intrflush(WINDOW *win, bool bf)
+{
+    PDC_LOG(("intrflush() - called\n"));
+
+    return OK;
+}
+
+int keypad(WINDOW *win, bool bf)
+{
+    PDC_LOG(("keypad() - called\n"));
+
+    if (!win)
+        return ERR;
+
+    win->_use_keypad = bf;
+
+    return OK;
+}
+
+int meta(WINDOW *win, bool bf)
+{
+    PDC_LOG(("meta() - called\n"));
+
+    SP->raw_inp = bf;
+
+    return OK;
+}
+
+int nl(void)
+{
+    PDC_LOG(("nl() - called\n"));
+
+    SP->autocr = TRUE;
+
+    return OK;
+}
+
+int nonl(void)
+{
+    PDC_LOG(("nonl() - called\n"));
+
+    SP->autocr = FALSE;
+
+    return OK;
+}
+
+int nodelay(WINDOW *win, bool flag)
+{
+    PDC_LOG(("nodelay() - called\n"));
+
+    if (!win)
+        return ERR;
+
+    win->_nodelay = flag;
+
+    return OK;
+}
+
+int notimeout(WINDOW *win, bool flag)
+{
+    PDC_LOG(("notimeout() - called\n"));
+
+    return OK;
+}
+
+int raw(void)
+{
+    PDC_LOG(("raw() - called\n"));
+
+    PDC_set_keyboard_binary(TRUE);
+    SP->raw_inp = TRUE;
+
+    return OK;
+}
+
+int noraw(void)
+{
+    PDC_LOG(("noraw() - called\n"));
+
+    PDC_set_keyboard_binary(FALSE);
+    SP->raw_inp = FALSE;
+
+    return OK;
+}
+
+void noqiflush(void)
+{
+    PDC_LOG(("noqiflush() - called\n"));
+}
+
+void qiflush(void)
+{
+    PDC_LOG(("qiflush() - called\n"));
+}
+
+int typeahead(int fildes)
+{
+    PDC_LOG(("typeahead() - called\n"));
+
+    return OK;
+}
+
+void wtimeout(WINDOW *win, int delay)
+{
+    PDC_LOG(("wtimeout() - called\n"));
+
+    if (!win)
+        return;
+
+    if (delay < 0)
+    {
+        /* This causes a blocking read on the window, so turn on delay 
+           mode */
+
+        win->_nodelay = FALSE;
+        win->_delayms = 0;
+    }
+    else if (!delay)
+    {
+        /* This causes a non-blocking read on the window, so turn off 
+           delay mode */
+
+        win->_nodelay = TRUE;
+        win->_delayms = 0;
+    }
+    else
+    {
+        /* This causes the read on the window to delay for the number of 
+           milliseconds. Also forces the window into non-blocking read 
+           mode */
+
+        /*win->_nodelay = TRUE;*/
+        win->_delayms = delay;
+    }
+}
+
+void timeout(int delay)
+{
+    PDC_LOG(("timeout() - called\n"));
+
+    wtimeout(stdscr, delay);
+}
+
+int crmode(void)
+{
+    PDC_LOG(("crmode() - called\n"));
+
+    return cbreak();
+}
+
+int nocrmode(void)
+{
+    PDC_LOG(("nocrmode() - called\n"));
+
+    return nocbreak();
+}
diff --git a/apps/lib/curses/pdcurses/pdcurses/insch.c b/apps/lib/curses/pdcurses/pdcurses/insch.c
new file mode 100644
index 0000000..50527f2
--- /dev/null
+++ b/apps/lib/curses/pdcurses/pdcurses/insch.c
@@ -0,0 +1,268 @@
+/* Public Domain Curses */
+
+#include <curspriv.h>
+
+RCSID("$Id: insch.c,v 1.44 2008/07/13 16:08:18 wmcbrine Exp $")
+
+/*man-start**************************************************************
+
+  Name:                                                         insch
+
+  Synopsis:
+        int insch(chtype ch);
+        int winsch(WINDOW *win, chtype ch);
+        int mvinsch(int y, int x, chtype ch);
+        int mvwinsch(WINDOW *win, int y, int x, chtype ch);
+
+        int insrawch(chtype ch);
+        int winsrawch(WINDOW *win, chtype ch);
+        int mvinsrawch(int y, int x, chtype ch);
+        int mvwinsrawch(WINDOW *win, int y, int x, chtype ch);
+
+        int ins_wch(const cchar_t *wch);
+        int wins_wch(WINDOW *win, const cchar_t *wch);
+        int mvins_wch(int y, int x, const cchar_t *wch);
+        int mvwins_wch(WINDOW *win, int y, int x, const cchar_t *wch);
+
+  Description:
+        The insch() functions insert a chtype into the window at the 
+        current or specified cursor position. The cursor is NOT 
+        advanced. A newline is equivalent to clrtoeol(); tabs are 
+        expanded; other control characters are converted as with 
+        unctrl().
+
+        The ins_wch() functions are the wide-character
+        equivalents, taking cchar_t pointers rather than chtypes.
+
+        Video attributes can be combined with a character by ORing
+        them into the parameter. Text, including attributes, can be 
+        copied from one place to another using inch() and insch().
+
+        insrawch() etc. are PDCurses-specific wrappers for insch() etc. 
+        that disable the translation of control characters.
+
+  Return Value:
+        All functions return OK on success and ERR on error.
+
+  Portability                                X/Open    BSD    SYS V
+        insch                                   Y       Y       Y
+        winsch                                  Y       Y       Y
+        mvinsch                                 Y       Y       Y
+        mvwinsch                                Y       Y       Y
+        insrawch                                -       -       -
+        winsrawch                               -       -       -
+        ins_wch                                 Y
+        wins_wch                                Y
+        mvins_wch                               Y
+        mvwins_wch                              Y
+
+**man-end****************************************************************/
+
+#include <string.h>
+
+int winsch(WINDOW *win, chtype ch)
+{
+    int x, y;
+    chtype attr;
+    bool xlat;
+
+    PDC_LOG(("winsch() - called: win=%p ch=%x (text=%c attr=0x%x)\n",
+             win, ch, ch & A_CHARTEXT, ch & A_ATTRIBUTES));
+
+    if (!win)
+        return ERR;
+
+    x = win->_curx;
+    y = win->_cury;
+
+    if (y > win->_maxy || x > win->_maxx || y < 0 || x < 0)
+        return ERR;
+
+    xlat = !SP->raw_out && !(ch & A_ALTCHARSET);
+    attr = ch & A_ATTRIBUTES;
+    ch &= A_CHARTEXT;
+
+    if (xlat && (ch < ' ' || ch == 0x7f))
+    {
+        int x2;
+
+        switch (ch)
+        {
+        case '\t':
+            for (x2 = ((x / TABSIZE) + 1) * TABSIZE; x < x2; x++)
+            {
+                if (winsch(win, attr | ' ') == ERR)
+                    return ERR;
+            }
+            return OK;
+
+        case '\n':
+            wclrtoeol(win);
+            break;
+
+        case 0x7f:
+            if (winsch(win, attr | '?') == ERR)
+                return ERR;
+
+            return winsch(win, attr | '^');
+
+        default:
+            /* handle control chars */
+
+            if (winsch(win, attr | (ch + '@')) == ERR)
+                return ERR;
+
+            return winsch(win, attr | '^');
+        }
+    }
+    else
+    {
+        int maxx;
+        chtype *temp;
+
+        /* If the incoming character doesn't have its own attribute,
+           then use the current attributes for the window. If it has
+           attributes but not a color component, OR the attributes to
+           the current attributes for the window. If it has a color
+           component, use the attributes solely from the incoming
+           character. */
+
+        if (!(attr & A_COLOR))
+            attr |= win->_attrs;
+
+        /* wrs (4/10/93): Apply the same sort of logic for the window
+           background, in that it only takes precedence if other color
+           attributes are not there and that the background character
+           will only print if the printing character is blank. */
+
+        if (!(attr & A_COLOR))
+            attr |= win->_bkgd & A_ATTRIBUTES;
+        else
+            attr |= win->_bkgd & (A_ATTRIBUTES ^ A_COLOR);
+
+        if (ch == ' ')
+            ch = win->_bkgd & A_CHARTEXT;
+
+        /* Add the attribute back into the character. */
+
+        ch |= attr;
+
+        maxx = win->_maxx;
+        temp = &win->_y[y][x];
+
+        memmove(temp + 1, temp, (maxx - x - 1) * sizeof(chtype));
+
+        win->_lastch[y] = maxx - 1;
+
+        if ((win->_firstch[y] == _NO_CHANGE) || (win->_firstch[y] > x))
+            win->_firstch[y] = x;
+
+        *temp = ch;
+    }
+
+    PDC_sync(win);
+
+    return OK;
+}
+
+int insch(chtype ch)
+{
+    PDC_LOG(("insch() - called\n"));
+
+    return winsch(stdscr, ch);
+}
+
+int mvinsch(int y, int x, chtype ch)
+{
+    PDC_LOG(("mvinsch() - called\n"));
+
+    if (move(y, x) == ERR)
+        return ERR;
+
+    return winsch(stdscr, ch);
+}
+
+int mvwinsch(WINDOW *win, int y, int x, chtype ch)
+{
+    PDC_LOG(("mvwinsch() - called\n"));
+
+    if (wmove(win, y, x) == ERR)
+        return ERR;
+
+    return winsch(win, ch);
+}
+
+int winsrawch(WINDOW *win, chtype ch)
+{
+    PDC_LOG(("winsrawch() - called: win=%p ch=%x "
+             "(char=%c attr=0x%x)\n", win, ch,
+             ch & A_CHARTEXT, ch & A_ATTRIBUTES));
+
+    if ((ch & A_CHARTEXT) < ' ' || (ch & A_CHARTEXT) == 0x7f)
+        ch |= A_ALTCHARSET;
+
+    return winsch(win, ch);
+}
+
+int insrawch(chtype ch)
+{
+    PDC_LOG(("insrawch() - called\n"));
+
+    return winsrawch(stdscr, ch);
+}
+
+int mvinsrawch(int y, int x, chtype ch)
+{
+    PDC_LOG(("mvinsrawch() - called\n"));
+
+    if (move(y, x) == ERR)
+        return ERR;
+
+    return winsrawch(stdscr, ch);
+}
+
+int mvwinsrawch(WINDOW *win, int y, int x, chtype ch)
+{
+    PDC_LOG(("mvwinsrawch() - called\n"));
+
+    if (wmove(win, y, x) == ERR)
+        return ERR;
+
+    return winsrawch(win, ch);
+}
+
+#ifdef PDC_WIDE
+int wins_wch(WINDOW *win, const cchar_t *wch)
+{
+    PDC_LOG(("wins_wch() - called\n"));
+
+    return wch ? winsch(win, *wch) : ERR;
+}
+
+int ins_wch(const cchar_t *wch)
+{
+    PDC_LOG(("ins_wch() - called\n"));
+
+    return wins_wch(stdscr, wch);
+}
+
+int mvins_wch(int y, int x, const cchar_t *wch)
+{
+    PDC_LOG(("mvins_wch() - called\n"));
+
+    if (move(y, x) == ERR)
+        return ERR;
+
+    return wins_wch(stdscr, wch);
+}
+
+int mvwins_wch(WINDOW *win, int y, int x, const cchar_t *wch)
+{
+    PDC_LOG(("mvwins_wch() - called\n"));
+
+    if (wmove(win, y, x) == ERR)
+        return ERR;
+
+    return wins_wch(win, wch);
+}
+#endif
diff --git a/apps/lib/curses/pdcurses/pdcurses/insstr.c b/apps/lib/curses/pdcurses/pdcurses/insstr.c
new file mode 100644
index 0000000..38fa389
--- /dev/null
+++ b/apps/lib/curses/pdcurses/pdcurses/insstr.c
@@ -0,0 +1,261 @@
+/* Public Domain Curses */
+
+#include <curspriv.h>
+
+RCSID("$Id: insstr.c,v 1.46 2008/07/13 16:08:18 wmcbrine Exp $")
+
+/*man-start**************************************************************
+
+  Name:                                                         insstr
+
+  Synopsis:
+        int insstr(const char *str);
+        int insnstr(const char *str, int n);
+        int winsstr(WINDOW *win, const char *str);
+        int winsnstr(WINDOW *win, const char *str, int n);
+        int mvinsstr(int y, int x, const char *str);
+        int mvinsnstr(int y, int x, const char *str, int n);
+        int mvwinsstr(WINDOW *win, int y, int x, const char *str);
+        int mvwinsnstr(WINDOW *win, int y, int x, const char *str, int n);
+
+        int ins_wstr(const wchar_t *wstr);
+        int ins_nwstr(const wchar_t *wstr, int n);
+        int wins_wstr(WINDOW *win, const wchar_t *wstr);
+        int wins_nwstr(WINDOW *win, const wchar_t *wstr, int n);
+        int mvins_wstr(int y, int x, const wchar_t *wstr);
+        int mvins_nwstr(int y, int x, const wchar_t *wstr, int n);
+        int mvwins_wstr(WINDOW *win, int y, int x, const wchar_t *wstr);
+        int mvwins_nwstr(WINDOW *win, int y, int x, const wchar_t *wstr, int n);
+
+  Description:
+        The insstr() functions insert a character string into a window
+        at the current cursor position, by repeatedly calling winsch().
+        When PDCurses is built with wide-character support enabled, the
+        narrow-character functions treat the string as a multibyte
+        string in the current locale, and convert it first. All 
+        characters to the right of the cursor are moved to the right, 
+        with the possibility of the rightmost characters on the line 
+        being lost.  The cursor position does not change (after moving 
+        to y, x, if specified).  The routines with n as the last 
+        argument insert at most n characters; if n is negative, then the 
+        entire string is inserted.
+
+  Return Value:
+        All functions return OK on success and ERR on error.
+
+  Portability                                X/Open    BSD    SYS V
+        insstr                                  Y       -      4.0
+        winsstr                                 Y       -      4.0
+        mvinsstr                                Y       -      4.0
+        mvwinsstr                               Y       -      4.0
+        insnstr                                 Y       -      4.0
+        winsnstr                                Y       -      4.0
+        mvinsnstr                               Y       -      4.0
+        mvwinsnstr                              Y       -      4.0
+        ins_wstr                                Y
+        wins_wstr                               Y
+        mvins_wstr                              Y
+        mvwins_wstr                             Y
+        ins_nwstr                               Y
+        wins_nwstr                              Y
+        mvins_nwstr                             Y
+        mvwins_nwstr                            Y
+
+**man-end****************************************************************/
+
+#include <string.h>
+
+int winsnstr(WINDOW *win, const char *str, int n)
+{
+#ifdef PDC_WIDE
+    wchar_t wstr[513], *p;
+    int i;
+#endif
+    int len;
+
+    PDC_LOG(("winsnstr() - called: string=\"%s\" n %d \n", str, n));
+
+    if (!win || !str)
+        return ERR;
+
+    len = strlen(str);
+
+    if (n < 0 || n < len)
+        n = len;
+
+#ifdef PDC_WIDE
+    if (n > 512)
+        n = 512;
+
+    p = wstr;
+    i = 0;
+
+    while (str[i] && i < n)
+    {
+        int retval = PDC_mbtowc(p, str + i, n - i);
+
+        if (retval <= 0)
+            break;
+        p++;
+        i += retval;
+    }
+
+    while (p > wstr)
+        if (winsch(win, *--p) == ERR)
+#else
+    while (n)
+        if (winsch(win, (unsigned char)(str[--n])) == ERR)
+#endif
+            return ERR;
+
+    return OK;
+}
+
+int insstr(const char *str)
+{
+    PDC_LOG(("insstr() - called: string=\"%s\"\n", str));
+
+    return winsnstr(stdscr, str, -1);
+}
+
+int winsstr(WINDOW *win, const char *str)
+{
+    PDC_LOG(("winsstr() - called: string=\"%s\"\n", str));
+
+    return winsnstr(win, str, -1);
+}
+
+int mvinsstr(int y, int x, const char *str)
+{
+    PDC_LOG(("mvinsstr() - called: y %d x %d string=\"%s\"\n", y, x, str));
+
+    if (move(y, x) == ERR)
+        return ERR;
+
+    return winsnstr(stdscr, str, -1);
+}
+
+int mvwinsstr(WINDOW *win, int y, int x, const char *str)
+{
+    PDC_LOG(("mvwinsstr() - called: string=\"%s\"\n", str));
+
+    if (wmove(win, y, x) == ERR)
+        return ERR;
+
+    return winsnstr(win, str, -1);
+}
+
+int insnstr(const char *str, int n)
+{
+    PDC_LOG(("insnstr() - called: string=\"%s\" n %d \n", str, n));
+
+    return winsnstr(stdscr, str, n);
+}
+
+int mvinsnstr(int y, int x, const char *str, int n)
+{
+    PDC_LOG(("mvinsnstr() - called: y %d x %d string=\"%s\" n %d \n",
+             y, x, str, n));
+
+    if (move(y, x) == ERR)
+        return ERR;
+
+    return winsnstr(stdscr, str, n);
+}
+
+int mvwinsnstr(WINDOW *win, int y, int x, const char *str, int n)
+{
+    PDC_LOG(("mvwinsnstr() - called: y %d x %d string=\"%s\" n %d \n",
+             y, x, str, n));
+
+    if (wmove(win, y, x) == ERR)
+        return ERR;
+
+    return winsnstr(win, str, n);
+}
+
+#ifdef PDC_WIDE
+int wins_nwstr(WINDOW *win, const wchar_t *wstr, int n)
+{
+    const wchar_t *p;
+    int len;
+
+    PDC_LOG(("wins_nwstr() - called\n"));
+
+    if (!win || !wstr)
+        return ERR;
+
+    for (len = 0, p = wstr; *p; p++)
+        len++;
+
+    if (n < 0 || n < len)
+        n = len;
+
+    while (n)
+        if (winsch(win, wstr[--n]) == ERR)
+            return ERR;
+
+    return OK;
+}
+
+int ins_wstr(const wchar_t *wstr)
+{
+    PDC_LOG(("ins_wstr() - called\n"));
+
+    return wins_nwstr(stdscr, wstr, -1);
+}
+
+int wins_wstr(WINDOW *win, const wchar_t *wstr)
+{
+    PDC_LOG(("wins_wstr() - called\n"));
+
+    return wins_nwstr(win, wstr, -1);
+}
+
+int mvins_wstr(int y, int x, const wchar_t *wstr)
+{
+    PDC_LOG(("mvins_wstr() - called\n"));
+
+    if (move(y, x) == ERR)
+        return ERR;
+
+    return wins_nwstr(stdscr, wstr, -1);
+}
+
+int mvwins_wstr(WINDOW *win, int y, int x, const wchar_t *wstr)
+{
+    PDC_LOG(("mvwinsstr() - called\n"));
+
+    if (wmove(win, y, x) == ERR)
+        return ERR;
+
+    return wins_nwstr(win, wstr, -1);
+}
+
+int ins_nwstr(const wchar_t *wstr, int n)
+{
+    PDC_LOG(("ins_nwstr() - called\n"));
+
+    return wins_nwstr(stdscr, wstr, n);
+}
+
+int mvins_nwstr(int y, int x, const wchar_t *wstr, int n)
+{
+    PDC_LOG(("mvinsnstr() - called\n"));
+
+    if (move(y, x) == ERR)
+        return ERR;
+
+    return wins_nwstr(stdscr, wstr, n);
+}
+
+int mvwins_nwstr(WINDOW *win, int y, int x, const wchar_t *wstr, int n)
+{
+    PDC_LOG(("mvwinsnstr() - called\n"));
+
+    if (wmove(win, y, x) == ERR)
+        return ERR;
+
+    return wins_nwstr(win, wstr, n);
+}
+#endif
diff --git a/apps/lib/curses/pdcurses/pdcurses/instr.c b/apps/lib/curses/pdcurses/pdcurses/instr.c
new file mode 100644
index 0000000..bbf369c
--- /dev/null
+++ b/apps/lib/curses/pdcurses/pdcurses/instr.c
@@ -0,0 +1,243 @@
+/* Public Domain Curses */
+
+#include <curspriv.h>
+
+RCSID("$Id: instr.c,v 1.44 2008/07/13 16:08:18 wmcbrine Exp $")
+
+/*man-start**************************************************************
+
+  Name:                                                         instr
+
+  Synopsis:
+        int instr(char *str);
+        int innstr(char *str, int n);
+        int winstr(WINDOW *win, char *str);
+        int winnstr(WINDOW *win, char *str, int n);
+        int mvinstr(int y, int x, char *str);
+        int mvinnstr(int y, int x, char *str, int n);
+        int mvwinstr(WINDOW *win, int y, int x, char *str);
+        int mvwinnstr(WINDOW *win, int y, int x, char *str, int n);
+
+        int inwstr(wchar_t *wstr);
+        int innwstr(wchar_t *wstr, int n);
+        int winwstr(WINDOW *win, wchar_t *wstr);
+        int winnwstr(WINDOW *win, wchar_t *wstr, int n);
+        int mvinwstr(int y, int x, wchar_t *wstr);
+        int mvinnwstr(int y, int x, wchar_t *wstr, int n);
+        int mvwinwstr(WINDOW *win, int y, int x, wchar_t *wstr);
+        int mvwinnwstr(WINDOW *win, int y, int x, wchar_t *wstr, int n);
+
+  Description:
+        These functions take characters (or wide characters) from the 
+        current or specified position in the window, and return them as 
+        a string in str (or wstr). Attributes are ignored. The functions 
+        with n as the last argument return a string at most n characters 
+        long.
+
+  Return Value:
+        Upon successful completion, innstr(), mvinnstr(), mvwinnstr() 
+        and winnstr() return the number of characters actually read into
+        the string; instr(), mvinstr(), mvwinstr() and winstr() return 
+        OK. Otherwise, all these functions return ERR.
+
+  Portability                                X/Open    BSD    SYS V
+        instr                                   Y       -      4.0
+        winstr                                  Y       -      4.0
+        mvinstr                                 Y       -      4.0
+        mvwinstr                                Y       -      4.0
+        innstr                                  Y       -      4.0
+        winnstr                                 Y       -      4.0
+        mvinnstr                                Y       -      4.0
+        mvwinnstr                               Y       -      4.0
+        inwstr                                  Y
+        winwstr                                 Y
+        mvinwstr                                Y
+        mvwinwstr                               Y
+        innwstr                                 Y
+        winnwstr                                Y
+        mvinnwstr                               Y
+        mvwinnwstr                              Y
+
+**man-end****************************************************************/
+
+int winnstr(WINDOW *win, char *str, int n)
+{
+#ifdef PDC_WIDE
+    wchar_t wstr[513];
+
+    if (n < 0 || n > 512)
+        n = 512;
+
+    if (winnwstr(win, wstr, n) == ERR)
+        return ERR;
+
+    return PDC_wcstombs(str, wstr, n);
+#else
+    chtype *src;
+    int i;
+
+    PDC_LOG(("winnstr() - called: n %d \n", n));
+
+    if (!win || !str)
+        return ERR;
+
+    if (n < 0 || (win->_curx + n) > win->_maxx)
+        n = win->_maxx - win->_curx;
+
+    src = win->_y[win->_cury] + win->_curx;
+
+    for (i = 0; i < n; i++)
+        str[i] = src[i] & A_CHARTEXT;
+
+    str[i] = '\0';
+
+    return i;
+#endif
+}
+
+int instr(char *str)
+{
+    PDC_LOG(("instr() - called: string=\"%s\"\n", str));
+
+    return (ERR == winnstr(stdscr, str, stdscr->_maxx)) ? ERR : OK;
+}
+
+int winstr(WINDOW *win, char *str)
+{
+    PDC_LOG(("winstr() - called: \n"));
+
+    return (ERR == winnstr(win, str, win->_maxx)) ? ERR : OK;
+}
+
+int mvinstr(int y, int x, char *str)
+{
+    PDC_LOG(("mvinstr() - called: y %d x %d \n", y, x));
+
+    if (move(y, x) == ERR)
+        return ERR;
+
+    return (ERR == winnstr(stdscr, str, stdscr->_maxx)) ? ERR : OK;
+}
+
+int mvwinstr(WINDOW *win, int y, int x, char *str)
+{
+    PDC_LOG(("mvwinstr() - called: y %d x %d \n", y, x));
+
+    if (wmove(win, y, x) == ERR)
+        return ERR;
+
+    return (ERR == winnstr(win, str, win->_maxx)) ? ERR : OK;
+}
+
+int innstr(char *str, int n)
+{
+    PDC_LOG(("innstr() - called: n %d \n", n));
+
+    return winnstr(stdscr, str, n);
+}
+
+int mvinnstr(int y, int x, char *str, int n)
+{
+    PDC_LOG(("mvinnstr() - called: y %d x %d n %d \n", y, x, n));
+
+    if (move(y, x) == ERR)
+        return ERR;
+
+    return winnstr(stdscr, str, n);
+}
+
+int mvwinnstr(WINDOW *win, int y, int x, char *str, int n)
+{
+    PDC_LOG(("mvwinnstr() - called: y %d x %d n %d \n", y, x, n));
+
+    if (wmove(win, y, x) == ERR)
+        return ERR;
+
+    return winnstr(win, str, n);
+}
+
+#ifdef PDC_WIDE
+int winnwstr(WINDOW *win, wchar_t *wstr, int n)
+{
+    chtype *src;
+    int i;
+
+    PDC_LOG(("winnstr() - called: n %d \n", n));
+
+    if (!win || !wstr)
+        return ERR;
+
+    if (n < 0 || (win->_curx + n) > win->_maxx)
+        n = win->_maxx - win->_curx;
+
+    src = win->_y[win->_cury] + win->_curx;
+
+    for (i = 0; i < n; i++)
+        wstr[i] = src[i] & A_CHARTEXT;
+
+    wstr[i] = L'\0';
+
+    return i;
+}
+
+int inwstr(wchar_t *wstr)
+{
+    PDC_LOG(("inwstr() - called\n"));
+
+    return (ERR == winnwstr(stdscr, wstr, stdscr->_maxx)) ? ERR : OK;
+}
+
+int winwstr(WINDOW *win, wchar_t *wstr)
+{
+    PDC_LOG(("winwstr() - called\n"));
+
+    return (ERR == winnwstr(win, wstr, win->_maxx)) ? ERR : OK;
+}
+
+int mvinwstr(int y, int x, wchar_t *wstr)
+{
+    PDC_LOG(("mvinwstr() - called\n"));
+
+    if (move(y, x) == ERR)
+        return ERR;
+
+    return (ERR == winnwstr(stdscr, wstr, stdscr->_maxx)) ? ERR : OK;
+}
+
+int mvwinwstr(WINDOW *win, int y, int x, wchar_t *wstr)
+{
+    PDC_LOG(("mvwinstr() - called\n"));
+
+    if (wmove(win, y, x) == ERR)
+        return ERR;
+
+    return (ERR == winnwstr(win, wstr, win->_maxx)) ? ERR : OK;
+}
+
+int innwstr(wchar_t *wstr, int n)
+{
+    PDC_LOG(("innwstr() - called\n"));
+
+    return winnwstr(stdscr, wstr, n);
+}
+
+int mvinnwstr(int y, int x, wchar_t *wstr, int n)
+{
+    PDC_LOG(("mvinnstr() - called\n"));
+
+    if (move(y, x) == ERR)
+        return ERR;
+
+    return winnwstr(stdscr, wstr, n);
+}
+
+int mvwinnwstr(WINDOW *win, int y, int x, wchar_t *wstr, int n)
+{
+    PDC_LOG(("mvwinnwstr() - called\n"));
+
+    if (wmove(win, y, x) == ERR)
+        return ERR;
+
+    return winnwstr(win, wstr, n);
+}
+#endif
diff --git a/apps/lib/curses/pdcurses/pdcurses/kernel.c b/apps/lib/curses/pdcurses/pdcurses/kernel.c
new file mode 100644
index 0000000..7e41ccf
--- /dev/null
+++ b/apps/lib/curses/pdcurses/pdcurses/kernel.c
@@ -0,0 +1,256 @@
+/* Public Domain Curses */
+
+#include <curspriv.h>
+
+RCSID("$Id: kernel.c,v 1.78 2008/07/15 17:13:26 wmcbrine Exp $")
+
+/*man-start**************************************************************
+
+  Name:                                                         kernel
+
+  Synopsis:
+        int def_prog_mode(void);
+        int def_shell_mode(void);
+        int reset_prog_mode(void);
+        int reset_shell_mode(void);
+        int resetty(void);
+        int savetty(void);
+        int ripoffline(int line, int (*init)(WINDOW *, int));
+        int curs_set(int visibility);
+        int napms(int ms);
+
+        int draino(int ms);
+        int resetterm(void);
+        int fixterm(void);
+        int saveterm(void);
+
+  Description:
+        def_prog_mode() and def_shell_mode() save the current terminal
+        modes as the "program" (in curses) or "shell" (not in curses)
+        state for use by the reset_prog_mode() and reset_shell_mode()
+        functions.  This is done automatically by initscr().
+
+        reset_prog_mode() and reset_shell_mode() restore the terminal to
+        "program" (in curses) or "shell" (not in curses) state.  These
+        are done automatically by endwin() and doupdate() after an
+        endwin(), so they would normally not be called before these
+        functions.
+
+        savetty() and resetty() save and restore the state of the
+        terminal modes. savetty() saves the current state in a buffer,
+        and resetty() restores the state to what it was at the last call
+        to savetty().
+
+        curs_set() alters the appearance of the cursor. A visibility of
+        0 makes it disappear; 1 makes it appear "normal" (usually an
+        underline) and 2 makes it "highly visible" (usually a block).
+
+        ripoffline() reduces the size of stdscr by one line.  If the 
+        "line" parameter is positive, the line is removed from the top 
+        of the screen; if negative, from the bottom. Up to 5 lines can 
+        be ripped off stdscr by calling ripoffline() repeatedly. The 
+        function argument, init, is called from within initscr() or 
+        newterm(), so ripoffline() must be called before either of these 
+        functions.  The init function receives a pointer to a one-line 
+        WINDOW, and the width of the window. Calling ripoffline() with a 
+        NULL init function pointer is an error.
+
+        napms() suspends the program for the specified number of 
+        milliseconds. draino() is an archaic equivalent.
+
+        resetterm(), fixterm() and saveterm() are archaic equivalents
+        for reset_shell_mode(), reset_prog_mode() and def_prog_mode(),
+        respectively.
+
+  Return Value:
+        All functions return OK on success and ERR on error, except
+        curs_set(), which returns the previous visibility.
+
+  Portability                                X/Open    BSD    SYS V
+        def_prog_mode                           Y       Y       Y
+        def_shell_mode                          Y       Y       Y
+        reset_prog_mode                         Y       Y       Y
+        reset_shell_mode                        Y       Y       Y
+        resetty                                 Y       Y       Y
+        savetty                                 Y       Y       Y
+        ripoffline                              Y       -      3.0
+        curs_set                                Y       -      3.0
+        napms                                   Y       Y       Y
+        draino                                  -
+        resetterm                               -
+        fixterm                                 -
+        saveterm                                -
+
+**man-end****************************************************************/
+
+#include <string.h>
+
+RIPPEDOFFLINE linesripped[5];
+char linesrippedoff = 0;
+
+static struct cttyset
+{
+    bool been_set;
+    SCREEN saved;
+} ctty[3];
+
+enum { PDC_SH_TTY, PDC_PR_TTY, PDC_SAVE_TTY };
+
+static void _save_mode(int i)
+{
+    ctty[i].been_set = TRUE;
+
+    memcpy(&(ctty[i].saved), SP, sizeof(SCREEN));
+
+    PDC_save_screen_mode(i);
+}
+
+static int _restore_mode(int i)
+{
+    if (ctty[i].been_set == TRUE)
+    {
+        memcpy(SP, &(ctty[i].saved), sizeof(SCREEN));
+
+        if (ctty[i].saved.raw_out)
+            raw();
+
+        PDC_restore_screen_mode(i);
+
+        if ((LINES != ctty[i].saved.lines) ||
+            (COLS != ctty[i].saved.cols))
+            resize_term(ctty[i].saved.lines, ctty[i].saved.cols);
+
+        PDC_curs_set(ctty[i].saved.visibility);
+
+        PDC_gotoyx(ctty[i].saved.cursrow, ctty[i].saved.curscol);
+    }
+
+    return ctty[i].been_set ? OK : ERR;
+}
+
+int def_prog_mode(void)
+{
+    PDC_LOG(("def_prog_mode() - called\n"));
+
+    _save_mode(PDC_PR_TTY);
+
+    return OK;
+}
+
+int def_shell_mode(void)
+{
+    PDC_LOG(("def_shell_mode() - called\n"));
+
+    _save_mode(PDC_SH_TTY);
+
+    return OK;
+}
+
+int reset_prog_mode(void)
+{
+    PDC_LOG(("reset_prog_mode() - called\n"));
+
+    _restore_mode(PDC_PR_TTY);
+    PDC_reset_prog_mode();
+
+    return OK;
+}
+
+int reset_shell_mode(void)
+{
+    PDC_LOG(("reset_shell_mode() - called\n"));
+
+    _restore_mode(PDC_SH_TTY);
+    PDC_reset_shell_mode();
+
+    return OK;
+}
+
+int resetty(void)
+{
+    PDC_LOG(("resetty() - called\n"));
+
+    return _restore_mode(PDC_SAVE_TTY);
+}
+
+int savetty(void)
+{
+    PDC_LOG(("savetty() - called\n"));
+
+    _save_mode(PDC_SAVE_TTY);
+
+    return OK;
+}
+
+int curs_set(int visibility)
+{
+    int ret_vis;
+
+    PDC_LOG(("curs_set() - called: visibility=%d\n", visibility));
+
+    if ((visibility < 0) || (visibility > 2))
+        return ERR;
+
+    ret_vis = PDC_curs_set(visibility);
+
+    /* If the cursor is changing from invisible to visible, update 
+       its position */
+
+    if (visibility && !ret_vis)
+        PDC_gotoyx(SP->cursrow, SP->curscol);
+
+    return ret_vis;
+}
+
+int napms(int ms)
+{
+    PDC_LOG(("napms() - called: ms=%d\n", ms));
+
+    if (ms)
+        PDC_napms(ms);
+
+    return OK;
+}
+
+int ripoffline(int line, int (*init)(WINDOW *, int))
+{
+    PDC_LOG(("ripoffline() - called: line=%d\n", line));
+
+    if (linesrippedoff < 5 && line && init)
+    {
+        linesripped[(int)linesrippedoff].line = line;
+        linesripped[(int)linesrippedoff++].init = init;
+
+        return OK;
+    }
+
+    return ERR;
+}
+
+int draino(int ms)
+{
+    PDC_LOG(("draino() - called\n"));
+
+    return napms(ms);
+}
+
+int resetterm(void)
+{
+    PDC_LOG(("resetterm() - called\n"));
+
+    return reset_shell_mode();
+}
+
+int fixterm(void)
+{
+    PDC_LOG(("fixterm() - called\n"));
+
+    return reset_prog_mode();
+}
+
+int saveterm(void)
+{
+    PDC_LOG(("saveterm() - called\n"));
+
+    return def_prog_mode();
+}
diff --git a/apps/lib/curses/pdcurses/pdcurses/keyname.c b/apps/lib/curses/pdcurses/pdcurses/keyname.c
new file mode 100644
index 0000000..6d02cef
--- /dev/null
+++ b/apps/lib/curses/pdcurses/pdcurses/keyname.c
@@ -0,0 +1,125 @@
+/* Public Domain Curses */
+
+#include <curspriv.h>
+
+RCSID("$Id: keyname.c,v 1.8 2008/07/13 16:08:18 wmcbrine Exp $")
+
+/*man-start**************************************************************
+
+  Name:                                                         keyname
+
+  Synopsis:
+        char *keyname(int key);
+
+        char *key_name(wchar_t c);
+
+        bool has_key(int key);
+
+  Description:
+        keyname() returns a string corresponding to the argument key. 
+        key may be any key returned by wgetch().
+
+        key_name() is the wide-character version. It takes a wchar_t 
+        parameter, but still returns a char *.
+
+        has_key() returns TRUE for recognized keys, FALSE otherwise. 
+        This function is an ncurses extension.
+
+  Portability                                X/Open    BSD    SYS V
+        keyname                                 Y       -      3.0
+        key_name                                Y
+        has_key                                 -       -       -
+
+**man-end****************************************************************/
+
+char *keyname(int key)
+{
+    /* Key names must be in exactly the same order as in curses.h */
+
+    static char *key_name[] =
+    {
+        "KEY_BREAK", "KEY_DOWN", "KEY_UP", "KEY_LEFT", "KEY_RIGHT",
+        "KEY_HOME", "KEY_BACKSPACE", "KEY_F0", "KEY_F(1)", "KEY_F(2)",
+        "KEY_F(3)", "KEY_F(4)", "KEY_F(5)", "KEY_F(6)", "KEY_F(7)",
+        "KEY_F(8)", "KEY_F(9)", "KEY_F(10)", "KEY_F(11)", "KEY_F(12)",
+        "KEY_F(13)", "KEY_F(14)", "KEY_F(15)", "KEY_F(16)", "KEY_F(17)",
+        "KEY_F(18)", "KEY_F(19)", "KEY_F(20)", "KEY_F(21)", "KEY_F(22)",
+        "KEY_F(23)", "KEY_F(24)", "KEY_F(25)", "KEY_F(26)", "KEY_F(27)",
+        "KEY_F(28)", "KEY_F(29)", "KEY_F(30)", "KEY_F(31)", "KEY_F(32)",
+        "KEY_F(33)", "KEY_F(34)", "KEY_F(35)", "KEY_F(36)", "KEY_F(37)",
+        "KEY_F(38)", "KEY_F(39)", "KEY_F(40)", "KEY_F(41)", "KEY_F(42)",
+        "KEY_F(43)", "KEY_F(44)", "KEY_F(45)", "KEY_F(46)", "KEY_F(47)",
+        "KEY_F(48)", "KEY_F(49)", "KEY_F(50)", "KEY_F(51)", "KEY_F(52)",
+        "KEY_F(53)", "KEY_F(54)", "KEY_F(55)", "KEY_F(56)", "KEY_F(57)",
+        "KEY_F(58)", "KEY_F(59)", "KEY_F(60)", "KEY_F(61)", "KEY_F(62)",
+        "KEY_F(63)", "KEY_DL", "KEY_IL", "KEY_DC", "KEY_IC", "KEY_EIC",
+        "KEY_CLEAR", "KEY_EOS", "KEY_EOL", "KEY_SF", "KEY_SR",
+        "KEY_NPAGE", "KEY_PPAGE", "KEY_STAB", "KEY_CTAB", "KEY_CATAB",
+        "KEY_ENTER", "KEY_SRESET", "KEY_RESET", "KEY_PRINT", "KEY_LL",
+        "KEY_ABORT", "KEY_SHELP", "KEY_LHELP", "KEY_BTAB", "KEY_BEG",
+        "KEY_CANCEL", "KEY_CLOSE", "KEY_COMMAND", "KEY_COPY",
+        "KEY_CREATE", "KEY_END", "KEY_EXIT", "KEY_FIND", "KEY_HELP",
+        "KEY_MARK", "KEY_MESSAGE", "KEY_MOVE", "KEY_NEXT", "KEY_OPEN",
+        "KEY_OPTIONS", "KEY_PREVIOUS", "KEY_REDO", "KEY_REFERENCE",
+        "KEY_REFRESH", "KEY_REPLACE", "KEY_RESTART", "KEY_RESUME",
+        "KEY_SAVE", "KEY_SBEG", "KEY_SCANCEL", "KEY_SCOMMAND",
+        "KEY_SCOPY", "KEY_SCREATE", "KEY_SDC", "KEY_SDL", "KEY_SELECT",
+        "KEY_SEND", "KEY_SEOL", "KEY_SEXIT", "KEY_SFIND", "KEY_SHOME",
+        "KEY_SIC", "UNKNOWN KEY", "KEY_SLEFT", "KEY_SMESSAGE",
+        "KEY_SMOVE", "KEY_SNEXT", "KEY_SOPTIONS", "KEY_SPREVIOUS",
+        "KEY_SPRINT", "KEY_SREDO", "KEY_SREPLACE", "KEY_SRIGHT",
+        "KEY_SRSUME", "KEY_SSAVE", "KEY_SSUSPEND", "KEY_SUNDO",
+        "KEY_SUSPEND", "KEY_UNDO", "ALT_0", "ALT_1", "ALT_2", "ALT_3",
+        "ALT_4", "ALT_5", "ALT_6", "ALT_7", "ALT_8", "ALT_9", "ALT_A",
+        "ALT_B", "ALT_C", "ALT_D", "ALT_E", "ALT_F", "ALT_G", "ALT_H",
+        "ALT_I", "ALT_J", "ALT_K", "ALT_L", "ALT_M", "ALT_N", "ALT_O",
+        "ALT_P", "ALT_Q", "ALT_R", "ALT_S", "ALT_T", "ALT_U", "ALT_V",
+        "ALT_W", "ALT_X", "ALT_Y", "ALT_Z", "CTL_LEFT", "CTL_RIGHT",
+        "CTL_PGUP", "CTL_PGDN", "CTL_HOME", "CTL_END", "KEY_A1",
+        "KEY_A2", "KEY_A3", "KEY_B1", "KEY_B2", "KEY_B3", "KEY_C1",
+        "KEY_C2", "KEY_C3", "PADSLASH", "PADENTER", "CTL_PADENTER",
+        "ALT_PADENTER", "PADSTOP", "PADSTAR", "PADMINUS", "PADPLUS",
+        "CTL_PADSTOP", "CTL_PADCENTER", "CTL_PADPLUS", "CTL_PADMINUS",
+        "CTL_PADSLASH", "CTL_PADSTAR", "ALT_PADPLUS", "ALT_PADMINUS",
+        "ALT_PADSLASH", "ALT_PADSTAR", "ALT_PADSTOP", "CTL_INS",
+        "ALT_DEL", "ALT_INS", "CTL_UP", "CTL_DOWN", "CTL_TAB",
+        "ALT_TAB", "ALT_MINUS", "ALT_EQUAL", "ALT_HOME", "ALT_PGUP",
+        "ALT_PGDN", "ALT_END", "ALT_UP", "ALT_DOWN", "ALT_RIGHT",
+        "ALT_LEFT", "ALT_ENTER", "ALT_ESC", "ALT_BQUOTE",
+        "ALT_LBRACKET", "ALT_RBRACKET", "ALT_SEMICOLON", "ALT_FQUOTE",
+        "ALT_COMMA", "ALT_STOP", "ALT_FSLASH", "ALT_BKSP", "CTL_BKSP",
+        "PAD0", "CTL_PAD0", "CTL_PAD1", "CTL_PAD2", "CTL_PAD3",
+        "CTL_PAD4", "CTL_PAD5", "CTL_PAD6", "CTL_PAD7","CTL_PAD8",
+        "CTL_PAD9", "ALT_PAD0", "ALT_PAD1", "ALT_PAD2", "ALT_PAD3",
+        "ALT_PAD4", "ALT_PAD5", "ALT_PAD6", "ALT_PAD7", "ALT_PAD8",
+        "ALT_PAD9", "CTL_DEL", "ALT_BSLASH", "CTL_ENTER",
+        "SHF_PADENTER", "SHF_PADSLASH", "SHF_PADSTAR", "SHF_PADPLUS",
+        "SHF_PADMINUS", "SHF_UP", "SHF_DOWN", "SHF_IC", "SHF_DC",
+        "KEY_MOUSE", "KEY_SHIFT_L", "KEY_SHIFT_R", "KEY_CONTROL_L",
+        "KEY_CONTROL_R", "KEY_ALT_L", "KEY_ALT_R", "KEY_RESIZE",
+        "KEY_SUP", "KEY_SDOWN"
+    };
+
+    PDC_LOG(("keyname() - called: key %d\n", key));
+
+    if ((key >= 0) && (key < 0x80))
+        return unctrl((chtype)key);
+
+    return has_key(key) ? key_name[key - KEY_MIN] : "UNKNOWN KEY";
+}
+
+bool has_key(int key)
+{
+    PDC_LOG(("has_key() - called: key %d\n", key));
+
+    return (key >= KEY_MIN && key <= KEY_MAX);
+}
+
+#ifdef PDC_WIDE
+char *key_name(wchar_t c)
+{
+    PDC_LOG(("key_name() - called\n"));
+
+    return keyname((int)c);
+}
+#endif
diff --git a/apps/lib/curses/pdcurses/pdcurses/mouse.c b/apps/lib/curses/pdcurses/pdcurses/mouse.c
new file mode 100644
index 0000000..1f476dd
--- /dev/null
+++ b/apps/lib/curses/pdcurses/pdcurses/mouse.c
@@ -0,0 +1,429 @@
+/* Public Domain Curses */
+
+#include <curspriv.h>
+
+RCSID("$Id: mouse.c,v 1.45 2008/07/13 16:08:18 wmcbrine Exp $")
+
+/*man-start**************************************************************
+
+  Name:                                                         mouse
+
+  Synopsis:
+        int mouse_set(unsigned long mbe);
+        int mouse_on(unsigned long mbe);
+        int mouse_off(unsigned long mbe);
+        int request_mouse_pos(void);
+        int map_button(unsigned long button);
+        void wmouse_position(WINDOW *win, int *y, int *x);
+        unsigned long getmouse(void);
+        unsigned long getbmap(void);
+
+        int mouseinterval(int wait);
+        bool wenclose(const WINDOW *win, int y, int x);
+        bool wmouse_trafo(const WINDOW *win, int *y, int *x, bool to_screen);
+        bool mouse_trafo(int *y, int *x, bool to_screen);
+        mmask_t mousemask(mmask_t mask, mmask_t *oldmask);
+        int nc_getmouse(MEVENT *event);
+        int ungetmouse(MEVENT *event);
+
+  Description:
+        As of PDCurses 3.0, there are two separate mouse interfaces: the
+        classic interface, which is based on the undocumented Sys V
+        mouse functions; and an ncurses-compatible interface. Both are
+        active at all times, and you can mix and match functions from
+        each, though it's not recommended. The ncurses interface is
+        essentially an emulation layer built on top of the classic
+        interface; it's here to allow easier porting of ncurses apps.
+
+        The classic interface: mouse_set(), mouse_on(), mouse_off(),
+        request_mouse_pos(), map_button(), wmouse_position(),
+        getmouse(), and getbmap(). An application using this interface
+        would start by calling mouse_set() or mouse_on() with a non-zero
+        value, often ALL_MOUSE_EVENTS. Then it would check for a
+        KEY_MOUSE return from getch(). If found, it would call
+        request_mouse_pos() to get the current mouse status.
+
+        mouse_set(), mouse_on() and mouse_off() are analagous to
+        attrset(), attron() and attroff().  These functions set the
+        mouse button events to trap.  The button masks used in these
+        functions are defined in curses.h and can be or'ed together.
+        They are the group of masks starting with BUTTON1_RELEASED.
+
+        request_mouse_pos() requests curses to fill in the Mouse_status
+        structure with the current state of the mouse.
+
+        map_button() enables the specified mouse action to activate the
+        Soft Label Keys if the action occurs over the area of the screen
+        where the Soft Label Keys are displayed.  The mouse actions are
+        defined in curses.h in the group that starts with BUTTON_RELEASED.
+
+        wmouse_position() determines if the current mouse position is
+        within the window passed as an argument.  If the mouse is
+        outside the current window, -1 is returned in the y and x
+        arguments; otherwise the y and x coordinates of the mouse
+        (relative to the top left corner of the window) are returned in
+        y and x.
+
+        getmouse() returns the current status of the trapped mouse
+        buttons as set by mouse_set() or mouse_on().
+
+        getbmap() returns the current status of the button action used
+        to map a mouse action to the Soft Label Keys as set by the
+        map_button() function.
+
+        The ncurses interface: mouseinterval(), wenclose(),
+        wmouse_trafo(), mouse_trafo(), mousemask(), nc_getmouse(), and
+        ungetmouse(). A typical application using this interface would
+        start by calling mousemask() with a non-zero value, often
+        ALL_MOUSE_EVENTS. Then it would check for a KEY_MOUSE return
+        from getch(). If found, it would call nc_getmouse() to get the
+        current mouse status.
+
+        mouseinterval() sets the timeout for a mouse click. On all
+        current platforms, PDCurses receives mouse button press and
+        release events, but must synthesize click events. It does this
+        by checking whether a release event is queued up after a press
+        event. If it gets a press event, and there are no more events
+        waiting, it will wait for the timeout interval, then check again
+        for a release. A press followed by a release is reported as
+        BUTTON_CLICKED; otherwise it's passed through as BUTTON_PRESSED.
+        The default timeout is 150ms; valid values are 0 (no clicks
+        reported) through 1000ms. In x11, the timeout can also be set
+        via the clickPeriod resource. The return value from
+        mouseinterval() is the old timeout. To check the old value
+        without setting a new one, call it with a parameter of -1. Note 
+        that although there's no classic equivalent for this function 
+        (apart from the clickPeriod resource), the value set applies in 
+        both interfaces.
+
+        wenclose() reports whether the given screen-relative y, x
+        coordinates fall within the given window.
+
+        wmouse_trafo() converts between screen-relative and window-
+        relative coordinates. A to_screen parameter of TRUE means to
+        convert from window to screen; otherwise the reverse. The
+        function returns FALSE if the coordinates aren't within the
+        window, or if any of the parameters are NULL. The coordinates
+        have been converted when the function returns TRUE.
+
+        mouse_trafo() is the stdscr version of wmouse_trafo().
+
+        mousemask() is nearly equivalent to mouse_set(), but instead of
+        OK/ERR, it returns the value of the mask after setting it. (This
+        isn't necessarily the same value passed in, since the mask could
+        be altered on some platforms.) And if the second parameter is a 
+        non-null pointer, mousemask() stores the previous mask value 
+        there. Also, since the ncurses interface doesn't work with 
+        PDCurses' BUTTON_MOVED events, mousemask() filters them out.
+
+        nc_getmouse() returns the current mouse status in an MEVENT 
+        struct. This is equivalent to ncurses' getmouse(), renamed to 
+        avoid conflict with PDCurses' getmouse(). But if you define 
+        NCURSES_MOUSE_VERSION (preferably as 2) before including 
+        curses.h, it defines getmouse() to nc_getmouse(), along with a 
+        few other redefintions needed for compatibility with ncurses 
+        code. nc_getmouse() calls request_mouse_pos(), which (not 
+        getmouse()) is the classic equivalent.
+
+        ungetmouse() is the mouse equivalent of ungetch(). However, 
+        PDCurses doesn't maintain a queue of mouse events; only one can 
+        be pushed back, and it can overwrite or be overwritten by real 
+        mouse events.
+
+  Portability                                X/Open    BSD    SYS V
+        mouse_set                               -       -      4.0
+        mouse_on                                -       -      4.0
+        mouse_off                               -       -      4.0
+        request_mouse_pos                       -       -      4.0
+        map_button                              -       -      4.0
+        wmouse_position                         -       -      4.0
+        getmouse                                -       -      4.0
+        getbmap                                 -       -      4.0
+        mouseinterval                           -       -       -
+        wenclose                                -       -       -
+        wmouse_trafo                            -       -       -
+        mouse_trafo                             -       -       -
+        mousemask                               -       -       -
+        nc_getmouse                             -       -       -
+        ungetmouse                              -       -       -
+
+**man-end****************************************************************/
+
+#include <string.h>
+
+static bool ungot = FALSE;
+
+int mouse_set(unsigned long mbe)
+{
+    PDC_LOG(("mouse_set() - called: event %x\n", mbe));
+
+    SP->_trap_mbe = mbe;
+    return PDC_mouse_set();
+}
+
+int mouse_on(unsigned long mbe)
+{
+    PDC_LOG(("mouse_on() - called: event %x\n", mbe));
+
+    SP->_trap_mbe |= mbe;
+    return PDC_mouse_set();
+}
+
+int mouse_off(unsigned long mbe)
+{
+    PDC_LOG(("mouse_off() - called: event %x\n", mbe));
+
+    SP->_trap_mbe &= ~mbe;
+    return PDC_mouse_set();
+}
+
+int map_button(unsigned long button)
+{
+    PDC_LOG(("map_button() - called: button %x\n", button));
+
+/****************** this does nothing at the moment ***************/
+    SP->_map_mbe_to_key = button;
+
+    return OK;
+}
+
+int request_mouse_pos(void)
+{
+    PDC_LOG(("request_mouse_pos() - called\n"));
+
+    Mouse_status = pdc_mouse_status;
+
+    return OK;
+}
+
+void wmouse_position(WINDOW *win, int *y, int *x)
+{
+    PDC_LOG(("wmouse_position() - called\n"));
+
+    if (win && wenclose(win, MOUSE_Y_POS, MOUSE_X_POS))
+    {
+        if (y)
+            *y = MOUSE_Y_POS - win->_begy;
+        if (x)
+            *x = MOUSE_X_POS - win->_begx;
+    }
+    else
+    {
+        if (y)
+            *y = -1;
+        if (x)
+            *x = -1;
+    }
+}
+
+unsigned long getmouse(void)
+{
+    PDC_LOG(("getmouse() - called\n"));
+
+    return SP->_trap_mbe;
+}
+
+unsigned long getbmap(void)
+{
+    PDC_LOG(("getbmap() - called\n"));
+
+    return SP->_map_mbe_to_key;
+}
+
+/* ncurses mouse interface */
+
+int mouseinterval(int wait)
+{
+    int old_wait;
+
+    PDC_LOG(("mouseinterval() - called: %d\n", wait));
+
+    old_wait = SP->mouse_wait;
+
+    if (wait >= 0 && wait <= 1000)
+        SP->mouse_wait = wait;
+
+    return old_wait;
+}
+
+bool wenclose(const WINDOW *win, int y, int x)
+{
+    PDC_LOG(("wenclose() - called: %p %d %d\n", win, y, x));
+
+    return (win && y >= win->_begy && y < win->_begy + win->_maxy
+                && x >= win->_begx && x < win->_begx + win->_maxx);
+}
+
+bool wmouse_trafo(const WINDOW *win, int *y, int *x, bool to_screen)
+{
+    int newy, newx;
+
+    PDC_LOG(("wmouse_trafo() - called\n"));
+
+    if (!win || !y || !x)
+        return FALSE;
+
+    newy = *y;
+    newx = *x;
+
+    if (to_screen)
+    {
+        newy += win->_begy;
+        newx += win->_begx;
+
+        if (!wenclose(win, newy, newx))
+            return FALSE;
+    }
+    else
+    {
+        if (wenclose(win, newy, newx))
+        {
+            newy -= win->_begy;
+            newx -= win->_begx;
+        }
+        else
+            return FALSE;
+    }
+
+    *y = newy;
+    *x = newx;
+
+    return TRUE;
+}
+
+bool mouse_trafo(int *y, int *x, bool to_screen)
+{
+    PDC_LOG(("mouse_trafo() - called\n"));
+
+    return wmouse_trafo(stdscr, y, x, to_screen);
+}
+
+mmask_t mousemask(mmask_t mask, mmask_t *oldmask)
+{
+    PDC_LOG(("mousemask() - called\n"));
+
+    if (oldmask)
+        *oldmask = SP->_trap_mbe;
+
+    /* The ncurses interface doesn't work with our move events, so 
+       filter them here */
+
+    mask &= ~(BUTTON1_MOVED | BUTTON2_MOVED | BUTTON3_MOVED);
+
+    mouse_set(mask);
+
+    return SP->_trap_mbe;
+}
+
+int nc_getmouse(MEVENT *event)
+{
+    int i;
+    mmask_t bstate = 0;
+
+    PDC_LOG(("nc_getmouse() - called\n"));
+
+    if (!event)
+        return ERR;
+
+    ungot = FALSE;
+
+    request_mouse_pos();
+
+    event->id = 0;
+
+    event->x = Mouse_status.x;
+    event->y = Mouse_status.y;
+    event->z = 0;
+
+    for (i = 0; i < 3; i++)
+    {
+        if (Mouse_status.changes & (1 << i))
+        {
+            int shf = i * 5;
+            short button = Mouse_status.button[i] & BUTTON_ACTION_MASK;
+
+            if (button == BUTTON_RELEASED)
+                bstate |= (BUTTON1_RELEASED << shf);
+            else if (button == BUTTON_PRESSED)
+                bstate |= (BUTTON1_PRESSED << shf);
+            else if (button == BUTTON_CLICKED)
+                bstate |= (BUTTON1_CLICKED << shf);
+            else if (button == BUTTON_DOUBLE_CLICKED)
+                bstate |= (BUTTON1_DOUBLE_CLICKED << shf);
+
+            button = Mouse_status.button[i] & BUTTON_MODIFIER_MASK;
+
+            if (button & PDC_BUTTON_SHIFT)
+                bstate |= BUTTON_MODIFIER_SHIFT;
+            if (button & PDC_BUTTON_CONTROL)
+                bstate |= BUTTON_MODIFIER_CONTROL;
+            if (button & PDC_BUTTON_ALT)
+                bstate |= BUTTON_MODIFIER_ALT;
+        }
+    }
+
+    if (MOUSE_WHEEL_UP)
+        bstate |= BUTTON4_PRESSED;
+    else if (MOUSE_WHEEL_DOWN)
+        bstate |= BUTTON5_PRESSED;
+
+    /* extra filter pass -- mainly for button modifiers */
+
+    event->bstate = bstate & SP->_trap_mbe;
+
+    return OK;
+}
+
+int ungetmouse(MEVENT *event)
+{
+    int i;
+    unsigned long bstate;
+
+    PDC_LOG(("ungetmouse() - called\n"));
+
+    if (!event || ungot)
+        return ERR;
+
+    ungot = TRUE;
+
+    pdc_mouse_status.x = event->x;
+    pdc_mouse_status.y = event->y;
+
+    pdc_mouse_status.changes = 0;
+    bstate = event->bstate;
+
+    for (i = 0; i < 3; i++)
+    {
+        int shf = i * 5;
+        short button = 0;
+
+        if (bstate & ((BUTTON1_RELEASED | BUTTON1_PRESSED | 
+            BUTTON1_CLICKED | BUTTON1_DOUBLE_CLICKED) << shf))
+        {
+            pdc_mouse_status.changes |= 1 << i;
+
+            if (bstate & (BUTTON1_PRESSED << shf))
+                button = BUTTON_PRESSED;
+            if (bstate & (BUTTON1_CLICKED << shf))
+                button = BUTTON_CLICKED;
+            if (bstate & (BUTTON1_DOUBLE_CLICKED << shf))
+                button = BUTTON_DOUBLE_CLICKED;
+
+            if (bstate & BUTTON_MODIFIER_SHIFT)
+                button |= PDC_BUTTON_SHIFT;
+            if (bstate & BUTTON_MODIFIER_CONTROL)
+                button |= PDC_BUTTON_CONTROL;
+            if (bstate & BUTTON_MODIFIER_ALT)
+                button |= PDC_BUTTON_ALT;
+        }
+
+        pdc_mouse_status.button[i] = button;
+    }
+
+    if (bstate & BUTTON4_PRESSED)
+        pdc_mouse_status.changes |= PDC_MOUSE_WHEEL_UP;
+    else if (bstate & BUTTON5_PRESSED)
+        pdc_mouse_status.changes |= PDC_MOUSE_WHEEL_DOWN;
+
+    return ungetch(KEY_MOUSE);
+}
diff --git a/apps/lib/curses/pdcurses/pdcurses/move.c b/apps/lib/curses/pdcurses/pdcurses/move.c
new file mode 100644
index 0000000..30e5908
--- /dev/null
+++ b/apps/lib/curses/pdcurses/pdcurses/move.c
@@ -0,0 +1,54 @@
+/* Public Domain Curses */
+
+#include <curspriv.h>
+
+RCSID("$Id: move.c,v 1.28 2008/07/13 16:08:18 wmcbrine Exp $")
+
+/*man-start**************************************************************
+
+  Name:                                                         move
+
+  Synopsis:
+        int move(int y, int x);
+        int wmove(WINDOW *win, int y, int x);
+
+  Description:
+        The cursor associated with the window is moved to the given
+        location.  This does not move the physical cursor of the
+        terminal until refresh() is called.  The position specified is
+        relative to the upper left corner of the window, which is (0,0).
+
+  Return Value:
+        All functions return OK on success and ERR on error.
+
+  Portability                                X/Open    BSD    SYS V
+        move                                    Y       Y       Y
+        wmove                                   Y       Y       Y
+
+**man-end****************************************************************/
+
+int move(int y, int x)
+{
+    PDC_LOG(("move() - called: y=%d x=%d\n", y, x));
+
+    if (!stdscr || x < 0 || y < 0 || x >= stdscr->_maxx || y >= stdscr->_maxy)
+        return ERR;
+
+    stdscr->_curx = x;
+    stdscr->_cury = y;
+
+    return OK;
+}
+
+int wmove(WINDOW *win, int y, int x)
+{
+    PDC_LOG(("wmove() - called: y=%d x=%d\n", y, x));
+
+    if (!win || x < 0 || y < 0 || x >= win->_maxx || y >= win->_maxy)
+        return ERR;
+
+    win->_curx = x;
+    win->_cury = y;
+
+    return OK;
+}
diff --git a/apps/lib/curses/pdcurses/pdcurses/outopts.c b/apps/lib/curses/pdcurses/pdcurses/outopts.c
new file mode 100644
index 0000000..0a8fd2d
--- /dev/null
+++ b/apps/lib/curses/pdcurses/pdcurses/outopts.c
@@ -0,0 +1,156 @@
+/* Public Domain Curses */
+
+#include <curspriv.h>
+
+RCSID("$Id: outopts.c,v 1.39 2008/07/14 12:22:13 wmcbrine Exp $")
+
+/*man-start**************************************************************
+
+  Name:                                                         outopts
+
+  Synopsis:
+        int clearok(WINDOW *win, bool bf);
+        int idlok(WINDOW *win, bool bf);
+        void idcok(WINDOW *win, bool bf);
+        void immedok(WINDOW *win, bool bf);
+        int leaveok(WINDOW *win, bool bf);
+        int setscrreg(int top, int bot);
+        int wsetscrreg(WINDOW *win, int top, int bot);
+        int scrollok(WINDOW *win, bool bf);
+
+        int raw_output(bool bf);
+
+  Description:
+        With clearok(), if bf is TRUE, the next call to wrefresh() with 
+        this window will clear the screen completely and redraw the 
+        entire screen.
+
+        immedok(), called with a second argument of TRUE, causes an 
+        automatic wrefresh() every time a change is made to the 
+        specified window.
+
+        Normally, the hardware cursor is left at the location of the
+        window being refreshed.  leaveok() allows the cursor to be
+        left wherever the update happens to leave it.  It's useful
+        for applications where the cursor is not used, since it reduces
+        the need for cursor motions.  If possible, the cursor is made
+        invisible when this option is enabled.
+
+        wsetscrreg() sets a scrolling region in a window; "top" and 
+        "bot" are the line numbers for the top and bottom margins. If 
+        this option and scrollok() are enabled, any attempt to move off 
+        the bottom margin will cause all lines in the scrolling region 
+        to scroll up one line. setscrreg() is the stdscr version.
+
+        idlok() and idcok() do nothing in PDCurses, but are provided for 
+        compatibility with other curses implementations.
+
+        raw_output() enables the output of raw characters using the 
+        standard *add* and *ins* curses functions (that is, it disables 
+        translation of control characters).
+
+  Return Value:
+        All functions return OK on success and ERR on error.
+
+  Portability                                X/Open    BSD    SYS V
+        clearok                                 Y       Y       Y
+        idlok                                   Y       Y       Y
+        idcok                                   Y       -      4.0
+        immedok                                 Y       -      4.0
+        leaveok                                 Y       Y       Y
+        setscrreg                               Y       Y       Y
+        wsetscrreg                              Y       Y       Y
+        scrollok                                Y       Y       Y
+        raw_output                              -       -       -
+
+**man-end****************************************************************/
+
+int clearok(WINDOW *win, bool bf)
+{
+    PDC_LOG(("clearok() - called\n"));
+
+    if (!win)
+        return ERR;
+
+    win->_clear = bf;
+
+    return OK;
+}
+
+int idlok(WINDOW *win, bool bf)
+{
+    PDC_LOG(("idlok() - called\n"));
+
+    return OK;
+}
+
+void idcok(WINDOW *win, bool bf)
+{
+    PDC_LOG(("idcok() - called\n"));
+}
+
+void immedok(WINDOW *win, bool bf)
+{
+    PDC_LOG(("immedok() - called\n"));
+
+    if (win)
+        win->_immed = bf;
+}
+
+int leaveok(WINDOW *win, bool bf)
+{
+    PDC_LOG(("leaveok() - called\n"));
+
+    if (!win)
+        return ERR;
+
+    win->_leaveit = bf;
+
+    curs_set(!bf);
+
+    return OK;
+}
+
+int setscrreg(int top, int bottom)
+{
+    PDC_LOG(("setscrreg() - called: top %d bottom %d\n", top, bottom));
+
+    return wsetscrreg(stdscr, top, bottom);
+}
+
+int wsetscrreg(WINDOW *win, int top, int bottom)
+{
+    PDC_LOG(("wsetscrreg() - called: top %d bottom %d\n", top, bottom));
+
+    if (win && 0 <= top && top <= win->_cury &&
+        win->_cury <= bottom && bottom < win->_maxy)
+    {
+        win->_tmarg = top;
+        win->_bmarg = bottom;
+
+        return OK;
+    }
+    else
+        return ERR;
+}
+
+int scrollok(WINDOW *win, bool bf)
+{
+    PDC_LOG(("scrollok() - called\n"));
+
+    if (!win)
+        return ERR;
+
+    win->_scroll = bf;
+
+    return OK;
+}
+
+int raw_output(bool bf)
+{
+    PDC_LOG(("raw_output() - called\n"));
+
+    SP->raw_out = bf;
+
+    return OK;
+}
diff --git a/apps/lib/curses/pdcurses/pdcurses/overlay.c b/apps/lib/curses/pdcurses/pdcurses/overlay.c
new file mode 100644
index 0000000..f9bba50
--- /dev/null
+++ b/apps/lib/curses/pdcurses/pdcurses/overlay.c
@@ -0,0 +1,256 @@
+/* Public Domain Curses */
+
+#include <curspriv.h>
+
+RCSID("$Id: overlay.c,v 1.36 2008/07/14 12:35:23 wmcbrine Exp $")
+
+/*man-start**************************************************************
+
+  Name:                                                         overlay
+
+  Synopsis:
+        int overlay(const WINDOW *src_w, WINDOW *dst_w)
+        int overwrite(const WINDOW *src_w, WINDOW *dst_w)
+        int copywin(const WINDOW *src_w, WINDOW *dst_w, int src_tr,
+                    int src_tc, int dst_tr, int dst_tc, int dst_br,
+                    int dst_bc, bool overlay)
+
+  Description:
+        overlay() and overwrite() copy all the text from src_w into
+        dst_w. The windows need not be the same size. Those characters
+        in the source window that intersect with the destination window
+        are copied, so that the characters appear in the same physical
+        position on the screen. The difference between the two functions
+        is that overlay() is non-destructive (blanks are not copied)
+        while overwrite() is destructive (blanks are copied).
+
+        copywin() is similar, but doesn't require that the two windows
+        overlap. The arguments src_tc and src_tr specify the top left
+        corner of the region to be copied. dst_tc, dst_tr, dst_br, and
+        dst_bc specify the region within the destination window to copy
+        to. The argument "overlay", if TRUE, indicates that the copy is
+        done non-destructively (as in overlay()); blanks in the source
+        window are not copied to the destination window. When overlay is
+        FALSE, blanks are copied.
+
+  Return Value:
+        All functions return OK on success and ERR on error.
+
+  Portability                                X/Open    BSD    SYS V
+        overlay                                 Y       Y       Y
+        overwrite                               Y       Y       Y
+        copywin                                 Y       -      3.0
+
+**man-end****************************************************************/
+
+/* Thanks to Andreas Otte <venn@@uni-paderborn.de> for the 
+   corrected overlay()/overwrite() behavior. */
+
+static int _copy_win(const WINDOW *src_w, WINDOW *dst_w, int src_tr,
+                     int src_tc, int src_br, int src_bc, int dst_tr,
+                     int dst_tc, bool overlay)
+{
+    int col, line, y1, fc, *minchng, *maxchng;
+    chtype *w1ptr, *w2ptr;
+
+    int lc = 0;
+    int xdiff = src_bc - src_tc;
+    int ydiff = src_br - src_tr;
+
+    if (!src_w || !dst_w)
+        return ERR;
+
+    minchng = dst_w->_firstch;
+    maxchng = dst_w->_lastch;
+
+    for (y1 = 0; y1 < dst_tr; y1++)
+    {
+        minchng++;
+        maxchng++;
+    }
+
+    for (line = 0; line < ydiff; line++)
+    {
+        w1ptr = src_w->_y[line + src_tr] + src_tc;
+        w2ptr = dst_w->_y[line + dst_tr] + dst_tc;
+
+        fc = _NO_CHANGE;
+
+        for (col = 0; col < xdiff; col++)
+        {
+            if ((*w1ptr) != (*w2ptr) &&
+                !((*w1ptr & A_CHARTEXT) == ' ' && overlay))
+            {
+                *w2ptr = *w1ptr;
+
+                if (fc == _NO_CHANGE)
+                    fc = col + dst_tc;
+            
+                lc = col + dst_tc;
+            }
+
+            w1ptr++;
+            w2ptr++;
+        }
+
+        if (*minchng == _NO_CHANGE)
+        {
+            *minchng = fc;
+            *maxchng = lc;
+        }
+        else if (fc != _NO_CHANGE)
+        {
+            if (fc < *minchng)
+                *minchng = fc;
+            if (lc > *maxchng)
+                *maxchng = lc;
+        }
+
+        minchng++;
+        maxchng++;
+    }
+
+    return OK;
+}
+
+int overlay(const WINDOW *src_w, WINDOW *dst_w)
+{
+    int first_line, first_col, last_line, last_col;
+    int src_start_x, src_start_y, dst_start_x, dst_start_y;
+    int xdiff, ydiff;
+
+    PDC_LOG(("overlay() - called\n"));
+
+    if (!src_w || !dst_w)
+        return ERR;
+
+    first_col = max(dst_w->_begx, src_w->_begx);
+    first_line = max(dst_w->_begy, src_w->_begy);
+
+    last_col = min(src_w->_begx + src_w->_maxx, dst_w->_begx + dst_w->_maxx);
+    last_line = min(src_w->_begy + src_w->_maxy, dst_w->_begy + dst_w->_maxy);
+
+    /* determine the overlapping region of the two windows in real 
+       coordinates */
+
+    /* if no overlapping region, do nothing */
+
+    if ((last_col < first_col) || (last_line < first_line))
+        return OK;
+
+    /* size of overlapping region */
+
+    xdiff = last_col - first_col;
+    ydiff = last_line - first_line;
+
+    if (src_w->_begx <= dst_w->_begx)
+    {
+        src_start_x = dst_w->_begx - src_w->_begx;
+        dst_start_x = 0;
+    }
+    else
+    {
+        dst_start_x = src_w->_begx - dst_w->_begx;
+        src_start_x = 0;
+    }
+
+    if (src_w->_begy <= dst_w->_begy)
+    {
+        src_start_y = dst_w->_begy - src_w->_begy;
+        dst_start_y = 0;
+    }
+    else
+    {
+        dst_start_y = src_w->_begy - dst_w->_begy;
+        src_start_y = 0;
+    }
+
+    return _copy_win(src_w, dst_w, src_start_y, src_start_x,
+                     src_start_y + ydiff, src_start_x + xdiff,
+                     dst_start_y, dst_start_x, TRUE);
+}
+
+int overwrite(const WINDOW *src_w, WINDOW *dst_w)
+{
+    int first_line, first_col, last_line, last_col;
+    int src_start_x, src_start_y, dst_start_x, dst_start_y;
+    int xdiff, ydiff;
+
+    PDC_LOG(("overwrite() - called\n"));
+
+    if (!src_w || !dst_w)
+        return ERR;
+
+    first_col = max(dst_w->_begx, src_w->_begx);
+    first_line = max(dst_w->_begy, src_w->_begy);
+
+    last_col = min(src_w->_begx + src_w->_maxx, dst_w->_begx + dst_w->_maxx);
+    last_line = min(src_w->_begy + src_w->_maxy, dst_w->_begy + dst_w->_maxy);
+
+    /* determine the overlapping region of the two windows in real 
+       coordinates */
+
+    /* if no overlapping region, do nothing */
+
+    if ((last_col < first_col) || (last_line < first_line))
+        return OK;
+
+    /* size of overlapping region */
+
+    xdiff = last_col - first_col;
+    ydiff = last_line - first_line;
+
+    if (src_w->_begx <= dst_w->_begx)
+    {
+        src_start_x = dst_w->_begx - src_w->_begx;
+        dst_start_x = 0;
+    }
+    else
+    {
+        dst_start_x = src_w->_begx - dst_w->_begx;
+        src_start_x = 0;
+    }
+
+    if (src_w->_begy <= dst_w->_begy)
+    {
+        src_start_y = dst_w->_begy - src_w->_begy;
+        dst_start_y = 0;
+    }
+    else
+    {
+        dst_start_y = src_w->_begy - dst_w->_begy;
+        src_start_y = 0;
+    }
+
+    return _copy_win(src_w, dst_w, src_start_y, src_start_x,
+                     src_start_y + ydiff, src_start_x + xdiff,
+                     dst_start_y, dst_start_x, FALSE);
+}
+
+int copywin(const WINDOW *src_w, WINDOW *dst_w, int src_tr, int src_tc,
+            int dst_tr, int dst_tc, int dst_br, int dst_bc, int overlay)
+{
+    int src_end_x, src_end_y;
+    int src_rows, src_cols, dst_rows, dst_cols;
+    int min_rows, min_cols;
+
+    PDC_LOG(("copywin() - called\n"));
+
+    if (!src_w || !dst_w || dst_w == curscr || dst_br > dst_w->_maxy
+        || dst_bc > dst_w->_maxx || dst_tr < 0 || dst_tc < 0)
+        return ERR;
+
+    src_rows = src_w->_maxy - src_tr;
+    src_cols = src_w->_maxx - src_tc;
+    dst_rows = dst_br - dst_tr + 1;
+    dst_cols = dst_bc - dst_tc + 1;
+
+    min_rows = min(src_rows, dst_rows);
+    min_cols = min(src_cols, dst_cols);
+
+    src_end_y = src_tr + min_rows;
+    src_end_x = src_tc + min_cols;
+
+    return _copy_win(src_w, dst_w, src_tr, src_tc, src_end_y, src_end_x,
+                     dst_tr, dst_tc, overlay);
+}
diff --git a/apps/lib/curses/pdcurses/pdcurses/pad.c b/apps/lib/curses/pdcurses/pdcurses/pad.c
new file mode 100644
index 0000000..ccc5db2
--- /dev/null
+++ b/apps/lib/curses/pdcurses/pdcurses/pad.c
@@ -0,0 +1,259 @@
+/* Public Domain Curses */
+
+#include <curspriv.h>
+
+RCSID("$Id: pad.c,v 1.50 2008/07/14 12:22:13 wmcbrine Exp $")
+
+/*man-start**************************************************************
+
+  Name:                                                         pad
+
+  Synopsis:
+        WINDOW *newpad(int nlines, int ncols);
+        WINDOW *subpad(WINDOW *orig, int nlines, int ncols,
+                       int begy, int begx);
+        int prefresh(WINDOW *win, int py, int px, int sy1, int sx1,
+                     int sy2, int sx2);
+        int pnoutrefresh(WINDOW *w, int py, int px, int sy1, int sx1,
+                         int sy2, int sx2);
+        int pechochar(WINDOW *pad, chtype ch);
+        int pecho_wchar(WINDOW *pad, const cchar_t *wch);
+
+  Description:
+        A pad is a special kind of window, which is not restricted by
+        the screen size, and is not necessarily associated with a
+        particular part of the screen.  You can use a pad when you need
+        a large window, and only a part of the window will be on the
+        screen at one time.  Pads are not refreshed automatically (e.g.,
+        from scrolling or echoing of input).  You can't call wrefresh()
+        with a pad as an argument; use prefresh() or pnoutrefresh()
+        instead.  Note that these routines require additional parameters
+        to specify the part of the pad to be displayed, and the location
+        to use on the screen.
+
+        newpad() creates a new pad data structure.  
+
+        subpad() creates a new sub-pad within a pad, at position (begy,
+        begx), with dimensions of nlines lines and ncols columns. This 
+        position is relative to the pad, and not to the screen as with 
+        subwin.  Changes to either the parent pad or sub-pad will affect 
+        both.  When using sub-pads, you may need to call touchwin() 
+        before calling prefresh().
+
+        pnoutrefresh() copies the specified pad to the virtual screen.
+
+        prefresh() calls pnoutrefresh(), followed by doupdate().
+
+        These routines are analogous to wnoutrefresh() and wrefresh().
+        (py, px) specifies the upper left corner of the part of the pad
+        to be displayed; (sy1, sx1) and (sy2, sx2) describe the screen 
+        rectangle that will contain the selected part of the pad.
+
+        pechochar() is functionally equivalent to addch() followed by
+        a call to prefresh(), with the last-used coordinates and
+        dimensions. pecho_wchar() is the wide-character version.
+
+  Return Value:
+        All functions return OK on success and ERR on error.
+
+  Portability                                X/Open    BSD    SYS V
+        newpad                                  Y       -       Y
+        subpad                                  Y       -       Y
+        prefresh                                Y       -       Y
+        pnoutrefresh                            Y       -       Y
+        pechochar                               Y       -      3.0
+        pecho_wchar                             Y
+
+**man-end****************************************************************/
+
+#include <string.h>
+
+/* save values for pechochar() */
+
+static int save_pminrow, save_pmincol;
+static int save_sminrow, save_smincol, save_smaxrow, save_smaxcol;
+
+WINDOW *newpad(int nlines, int ncols)
+{
+    WINDOW *win;
+
+    PDC_LOG(("newpad() - called: lines=%d cols=%d\n", nlines, ncols));
+
+    if ( !(win = PDC_makenew(nlines, ncols, -1, -1))
+        || !(win = PDC_makelines(win)) )
+        return (WINDOW *)NULL;
+
+    werase(win);
+
+    win->_flags = _PAD;
+
+    /* save default values in case pechochar() is the first call to 
+       prefresh(). */
+
+    save_pminrow = 0;
+    save_pmincol = 0;
+    save_sminrow = 0;
+    save_smincol = 0;
+    save_smaxrow = min(LINES, nlines) - 1;
+    save_smaxcol = min(COLS, ncols) - 1;
+
+    return win;
+}
+
+WINDOW *subpad(WINDOW *orig, int nlines, int ncols, int begy, int begx)
+{
+    WINDOW *win;
+    int i;
+    int j = begy;
+    int k = begx;
+
+    PDC_LOG(("subpad() - called: lines=%d cols=%d begy=%d begx=%d\n",
+             nlines, ncols, begy, begx));
+
+    if (!orig || !(orig->_flags & _PAD))
+        return (WINDOW *)NULL;
+
+    /* make sure window fits inside the original one */
+
+    if ((begy < orig->_begy) || (begx < orig->_begx) ||
+        (begy + nlines) > (orig->_begy + orig->_maxy) ||
+        (begx + ncols)  > (orig->_begx + orig->_maxx))
+        return (WINDOW *)NULL;
+
+    if (!nlines) 
+        nlines = orig->_maxy - 1 - j;
+
+    if (!ncols) 
+        ncols = orig->_maxx - 1 - k;
+
+    if ( !(win = PDC_makenew(nlines, ncols, begy, begx)) )
+        return (WINDOW *)NULL;
+
+    /* initialize window variables */
+
+    win->_attrs = orig->_attrs;
+    win->_leaveit = orig->_leaveit;
+    win->_scroll = orig->_scroll;
+    win->_nodelay = orig->_nodelay;
+    win->_use_keypad = orig->_use_keypad;
+    win->_parent = orig;
+
+    for (i = 0; i < nlines; i++)
+        win->_y[i] = (orig->_y[j++]) + k;
+
+    win->_flags = _SUBPAD;
+
+    /* save default values in case pechochar() is the first call
+       to prefresh(). */
+
+    save_pminrow = 0;
+    save_pmincol = 0;
+    save_sminrow = 0;
+    save_smincol = 0;
+    save_smaxrow = min(LINES, nlines) - 1;
+    save_smaxcol = min(COLS, ncols) - 1;
+
+    return win;
+}
+
+int prefresh(WINDOW *win, int py, int px, int sy1, int sx1, int sy2, int sx2)
+{
+    PDC_LOG(("prefresh() - called\n"));
+
+    if (pnoutrefresh(win, py, px, sy1, sx1, sy2, sx2) == ERR)
+        return ERR;
+
+    doupdate();
+    return OK;
+}
+
+int pnoutrefresh(WINDOW *w, int py, int px, int sy1, int sx1, int sy2, int sx2)
+{
+    int num_cols;
+    int sline = sy1;
+    int pline = py;
+
+    PDC_LOG(("pnoutrefresh() - called\n"));
+
+    if (!w || !(w->_flags & (_PAD|_SUBPAD)) || (sy2 >= LINES) || (sy2 >= COLS))
+        return ERR;
+
+    if (py < 0)
+        py = 0;
+    if (px < 0)
+        px = 0;
+    if (sy1 < 0)
+        sy1 = 0;
+    if (sx1 < 0)
+        sx1 = 0;
+
+    if (sy2 < sy1 || sx2 < sx1)
+        return ERR;
+
+    num_cols = min((sx2 - sx1 + 1), (w->_maxx - px));
+
+    while (sline <= sy2)
+    {
+        if (pline < w->_maxy)
+        {
+            memcpy(curscr->_y[sline] + sx1, w->_y[pline] + px,
+                   num_cols * sizeof(chtype));
+
+            if ((curscr->_firstch[sline] == _NO_CHANGE) 
+                || (curscr->_firstch[sline] > sx1))
+                curscr->_firstch[sline] = sx1;
+
+            if (sx2 > curscr->_lastch[sline])
+                curscr->_lastch[sline] = sx2;
+
+            w->_firstch[pline] = _NO_CHANGE; /* updated now */
+            w->_lastch[pline] = _NO_CHANGE;  /* updated now */
+        }
+
+        sline++;
+        pline++;
+    }
+
+    if (w->_clear)
+    {
+        w->_clear = FALSE;
+        curscr->_clear = TRUE;
+    }
+
+    /* position the cursor to the pad's current position if possible -- 
+       is the pad current position going to end up displayed? if not, 
+       then don't move the cursor; if so, move it to the correct place */
+
+    if (!w->_leaveit && w->_cury >= py && w->_curx >= px &&
+         w->_cury <= py + (sy2 - sy1) && w->_curx <= px + (sx2 - sx1))
+    {
+        curscr->_cury = (w->_cury - py) + sy1;
+        curscr->_curx = (w->_curx - px) + sx1;
+    }
+
+    return OK;
+}
+
+int pechochar(WINDOW *pad, chtype ch)
+{
+    PDC_LOG(("pechochar() - called\n"));
+
+    if (waddch(pad, ch) == ERR)
+        return ERR;
+
+    return prefresh(pad, save_pminrow, save_pmincol, save_sminrow, 
+                    save_smincol, save_smaxrow, save_smaxcol);
+}
+
+#ifdef PDC_WIDE
+int pecho_wchar(WINDOW *pad, const cchar_t *wch)
+{
+    PDC_LOG(("pecho_wchar() - called\n"));
+
+    if (!wch || (waddch(pad, *wch) == ERR))
+        return ERR;
+
+    return prefresh(pad, save_pminrow, save_pmincol, save_sminrow, 
+                    save_smincol, save_smaxrow, save_smaxcol);
+}
+#endif
diff --git a/apps/lib/curses/pdcurses/pdcurses/panel.c b/apps/lib/curses/pdcurses/pdcurses/panel.c
new file mode 100644
index 0000000..77028c6
--- /dev/null
+++ b/apps/lib/curses/pdcurses/pdcurses/panel.c
@@ -0,0 +1,630 @@
+/* Public Domain Curses */
+
+#include <curspriv.h>
+
+RCSID("$Id: panel.c,v 1.8 2008/07/14 12:35:23 wmcbrine Exp $")
+
+/*man-start**************************************************************
+
+  Name:                                                         panel
+
+  Synopsis:
+        int bottom_panel(PANEL *pan);
+        int del_panel(PANEL *pan);
+        int hide_panel(PANEL *pan);
+        int move_panel(PANEL *pan, int starty, int startx);
+        PANEL *new_panel(WINDOW *win);
+        PANEL *panel_above(const PANEL *pan);
+        PANEL *panel_below(const PANEL *pan);
+        int panel_hidden(const PANEL *pan);
+        const void *panel_userptr(const PANEL *pan);
+        WINDOW *panel_window(const PANEL *pan);
+        int replace_panel(PANEL *pan, WINDOW *win);
+        int set_panel_userptr(PANEL *pan, const void *uptr);
+        int show_panel(PANEL *pan);
+        int top_panel(PANEL *pan);
+        void update_panels(void);
+
+  Description:
+        The panel library is built using the curses library, and any
+        program using panels routines must call one of the curses
+        initialization routines such as initscr(). A program using these
+        routines must be linked with the panels and curses libraries.
+        The header <panel.h> includes the header <curses.h>.
+
+        The panels package gives the applications programmer a way to
+        have depth relationships between curses windows; a curses window
+        is associated with every panel. The panels routines allow curses
+        windows to overlap without making visible the overlapped
+        portions of underlying windows. The initial curses window,
+        stdscr, lies beneath all panels. The set of currently visible
+        panels is the 'deck' of panels.
+
+        The panels package allows the applications programmer to create
+        panels, fetch and set their associated windows, shuffle panels
+        in the deck, and manipulate panels in other ways.
+
+        bottom_panel() places pan at the bottom of the deck. The size, 
+        location and contents of the panel are unchanged.
+
+        del_panel() deletes pan, but not its associated winwow.
+
+        hide_panel() removes a panel from the deck and thus hides it 
+        from view.
+
+        move_panel() moves the curses window associated with pan, so 
+        that its upper lefthand corner is at the supplied coordinates. 
+        (Do not use mvwin() on the window.)
+
+        new_panel() creates a new panel associated with win and returns 
+        the panel pointer. The new panel is placed at the top of the 
+        deck.
+
+        panel_above() returns a pointer to the panel in the deck above 
+        pan, or NULL if pan is the top panel. If the value of pan passed 
+        is NULL, this function returns a pointer to the bottom panel in 
+        the deck.
+
+        panel_below() returns a pointer to the panel in the deck below 
+        pan, or NULL if pan is the bottom panel. If the value of pan 
+        passed is NULL, this function returns a pointer to the top panel 
+        in the deck.
+
+        panel_hidden() returns OK if pan is hidden and ERR if it is not.
+
+        panel_userptr() - Each panel has a user pointer available for 
+        maintaining relevant information. This function returns a 
+        pointer to that information previously set up by 
+        set_panel_userptr().
+
+        panel_window() returns a pointer to the curses window associated 
+        with the panel.
+
+        replace_panel() replaces the current window of pan with win.
+
+        set_panel_userptr() - Each panel has a user pointer available 
+        for maintaining relevant information. This function sets the 
+        value of that information.
+
+        show_panel() makes a previously hidden panel visible and places 
+        it back in the deck on top.
+
+        top_panel() places pan on the top of the deck. The size, 
+        location and contents of the panel are unchanged.
+
+        update_panels() refreshes the virtual screen to reflect the 
+        depth relationships between the panels in the deck. The user 
+        must use doupdate() to refresh the physical screen.
+
+  Return Value:
+        Each routine that returns a pointer to an object returns NULL if 
+        an error occurs. Each panel routine that returns an integer, 
+        returns OK if it executes successfully and ERR if it does not.
+
+  Portability                                X/Open    BSD    SYS V
+        bottom_panel                            -       -       Y
+        del_panel                               -       -       Y
+        hide_panel                              -       -       Y
+        move_panel                              -       -       Y
+        new_panel                               -       -       Y
+        panel_above                             -       -       Y
+        panel_below                             -       -       Y
+        panel_hidden                            -       -       Y
+        panel_userptr                           -       -       Y
+        panel_window                            -       -       Y
+        replace_panel                           -       -       Y
+        set_panel_userptr                       -       -       Y
+        show_panel                              -       -       Y
+        top_panel                               -       -       Y
+        update_panels                           -       -       Y
+
+  Credits:
+        Original Author - Warren Tucker <wht@n4hgf.mt-park.ga.us>
+
+**man-end****************************************************************/
+
+#include <panel.h>
+#include <stdlib.h>
+
+PANEL *_bottom_panel = (PANEL *)0;
+PANEL *_top_panel = (PANEL *)0;
+PANEL _stdscr_pseudo_panel = { (WINDOW *)0 };
+
+#ifdef PANEL_DEBUG
+
+static void dPanel(char *text, PANEL *pan)
+{
+    PDC_LOG(("%s id=%s b=%s a=%s y=%d x=%d", text, pan->user,
+             pan->below ? pan->below->user : "--",
+             pan->above ? pan->above->user : "--",
+             pan->wstarty, pan->wstartx));
+}
+
+static void dStack(char *fmt, int num, PANEL *pan)
+{
+    char s80[80];
+
+    sprintf(s80, fmt, num, pan);
+    PDC_LOG(("%s b=%s t=%s", s80, _bottom_panel ? _bottom_panel->user : "--",
+             _top_panel    ? _top_panel->user    : "--"));
+
+    if (pan)
+        PDC_LOG(("pan id=%s", pan->user));
+
+    pan = _bottom_panel;
+
+    while (pan)
+    {
+        dPanel("stk", pan);
+        pan = pan->above;
+    }
+}
+
+/* debugging hook for wnoutrefresh */
+
+static void Wnoutrefresh(PANEL *pan)
+{
+    dPanel("wnoutrefresh", pan);
+    wnoutrefresh(pan->win);
+}
+
+static void Touchpan(PANEL *pan)
+{
+    dPanel("Touchpan", pan);
+    touchwin(pan->win);
+}
+
+static void Touchline(PANEL *pan, int start, int count)
+{
+    char s80[80];
+
+    sprintf(s80, "Touchline s=%d c=%d", start, count);
+    dPanel(s80, pan);
+    touchline(pan->win, start, count);
+}
+
+#else   /* PANEL_DEBUG */
+
+#define dPanel(text, pan)
+#define dStack(fmt, num, pan)
+#define Wnoutrefresh(pan) wnoutrefresh((pan)->win)
+#define Touchpan(pan) touchwin((pan)->win)
+#define Touchline(pan, start, count) touchline((pan)->win, start, count)
+
+#endif  /* PANEL_DEBUG */
+
+static bool _panels_overlapped(PANEL *pan1, PANEL *pan2)
+{
+    if (!pan1 || !pan2)
+        return FALSE;
+
+    return ((pan1->wstarty >= pan2->wstarty && pan1->wstarty < pan2->wendy)
+         || (pan2->wstarty >= pan1->wstarty && pan2->wstarty < pan1->wendy))
+        && ((pan1->wstartx >= pan2->wstartx && pan1->wstartx < pan2->wendx)
+         || (pan2->wstartx >= pan1->wstartx && pan2->wstartx < pan1->wendx));
+}
+
+static void _free_obscure(PANEL *pan)
+{
+    PANELOBS *tobs = pan->obscure;  /* "this" one */
+    PANELOBS *nobs;                 /* "next" one */
+
+    while (tobs)
+    {
+        nobs = tobs->above;
+        free((char *)tobs);
+        tobs = nobs;
+    }
+    pan->obscure = (PANELOBS *)0;
+}
+
+static void _override(PANEL *pan, int show)
+{
+    int y;
+    PANEL *pan2;
+    PANELOBS *tobs = pan->obscure;      /* "this" one */
+
+    if (show == 1)
+        Touchpan(pan);
+    else if (!show)
+    {
+        Touchpan(pan);
+        Touchpan(&_stdscr_pseudo_panel);
+    }
+    else if (show == -1)
+        while (tobs && (tobs->pan != pan))
+            tobs = tobs->above;
+
+    while (tobs)
+    {
+        if ((pan2 = tobs->pan) != pan)
+            for (y = pan->wstarty; y < pan->wendy; y++)
+                if ((y >= pan2->wstarty) && (y < pan2->wendy) &&
+                   ((is_linetouched(pan->win, y - pan->wstarty)) ||
+                    (is_linetouched(stdscr, y))))
+                    Touchline(pan2, y - pan2->wstarty, 1);
+
+        tobs = tobs->above;
+    }
+}
+
+static void _calculate_obscure(void)
+{
+    PANEL *pan, *pan2;
+    PANELOBS *tobs;     /* "this" one */
+    PANELOBS *lobs;     /* last one */
+
+    pan = _bottom_panel;
+
+    while (pan)
+    {
+        if (pan->obscure)
+            _free_obscure(pan);
+
+        lobs = (PANELOBS *)0;
+        pan2 = _bottom_panel;
+
+        while (pan2)
+        {
+            if (_panels_overlapped(pan, pan2))
+            {
+                if ((tobs = malloc(sizeof(PANELOBS))) == NULL)
+                    return;
+
+                tobs->pan = pan2;
+                dPanel("obscured", pan2);
+                tobs->above = (PANELOBS *)0;
+
+                if (lobs)
+                    lobs->above = tobs;
+                else
+                    pan->obscure = tobs;
+
+                lobs  = tobs;
+            }
+
+            pan2 = pan2->above;
+        }
+
+        _override(pan, 1);
+        pan = pan->above;
+    }
+}
+
+/* check to see if panel is in the stack */
+
+static bool _panel_is_linked(const PANEL *pan)
+{
+    PANEL *pan2 = _bottom_panel;
+
+    while (pan2)
+    {
+        if (pan2 == pan)
+            return TRUE;
+
+        pan2 = pan2->above;
+    }
+
+    return FALSE;
+}
+
+/* link panel into stack at top */
+
+static void _panel_link_top(PANEL *pan)
+{
+#ifdef PANEL_DEBUG
+    dStack("<lt%d>", 1, pan);
+    if (_panel_is_linked(pan))
+        return;
+#endif
+    pan->above = (PANEL *)0;
+    pan->below = (PANEL *)0;
+
+    if (_top_panel)
+    {
+        _top_panel->above = pan;
+        pan->below = _top_panel;
+    }
+
+    _top_panel = pan;
+
+    if (!_bottom_panel)
+        _bottom_panel = pan;
+
+    _calculate_obscure();
+    dStack("<lt%d>", 9, pan);
+}
+
+/* link panel into stack at bottom */
+
+static void _panel_link_bottom(PANEL *pan)
+{
+#ifdef PANEL_DEBUG
+    dStack("<lb%d>", 1, pan);
+    if (_panel_is_linked(pan))
+        return;
+#endif
+    pan->above = (PANEL *)0;
+    pan->below = (PANEL *)0;
+
+    if (_bottom_panel)
+    {
+        _bottom_panel->below = pan;
+        pan->above = _bottom_panel;
+    }
+
+    _bottom_panel = pan;
+
+    if (!_top_panel)
+        _top_panel = pan;
+
+    _calculate_obscure();
+    dStack("<lb%d>", 9, pan);
+}
+
+static void _panel_unlink(PANEL *pan)
+{
+    PANEL *prev;
+    PANEL *next;
+
+#ifdef PANEL_DEBUG
+    dStack("<u%d>", 1, pan);
+    if (!_panel_is_linked(pan))
+        return;
+#endif
+    _override(pan, 0);
+    _free_obscure(pan);
+
+    prev = pan->below;
+    next = pan->above;
+
+    /* if non-zero, we will not update the list head */
+
+    if (prev)
+    {
+        prev->above = next;
+        if(next)
+            next->below = prev;
+    }
+    else if (next)
+        next->below = prev;
+
+    if (pan == _bottom_panel)
+        _bottom_panel = next;
+
+    if (pan == _top_panel)
+        _top_panel = prev;
+
+    _calculate_obscure();
+
+    pan->above = (PANEL *)0;
+    pan->below = (PANEL *)0;
+    dStack("<u%d>", 9, pan);
+
+}
+
+/************************************************************************
+ *   The following are the public functions for the panels library.     *
+ ************************************************************************/
+
+int bottom_panel(PANEL *pan)
+{
+    if (!pan)
+        return ERR;
+
+    if (pan == _bottom_panel)
+        return OK;
+
+    if (_panel_is_linked(pan))
+        hide_panel(pan);
+
+    _panel_link_bottom(pan);
+
+    return OK;
+}
+
+int del_panel(PANEL *pan)
+{
+    if (pan)
+    {
+        if (_panel_is_linked(pan))
+            hide_panel(pan);
+
+        free((char *)pan);
+        return OK;
+    }
+
+    return ERR;
+}
+
+int hide_panel(PANEL *pan)
+{
+    if (!pan)
+        return ERR;
+
+    if (!_panel_is_linked(pan))
+    {
+        pan->above = (PANEL *)0;
+        pan->below = (PANEL *)0;
+        return ERR;
+    }
+
+    _panel_unlink(pan);
+
+    return OK;
+}
+
+int move_panel(PANEL *pan, int starty, int startx)
+{
+    WINDOW *win;
+    int maxy, maxx;
+
+    if (!pan)
+        return ERR;
+
+    if (_panel_is_linked(pan))
+        _override(pan, 0);
+
+    win = pan->win;
+
+    if (mvwin(win, starty, startx) == ERR)
+        return ERR;
+
+    getbegyx(win, pan->wstarty, pan->wstartx);
+    getmaxyx(win, maxy, maxx);
+    pan->wendy = pan->wstarty + maxy;
+    pan->wendx = pan->wstartx + maxx;
+
+    if (_panel_is_linked(pan))
+        _calculate_obscure();
+
+    return OK;
+}
+
+PANEL *new_panel(WINDOW *win)
+{
+    PANEL *pan = malloc(sizeof(PANEL));
+
+    if (!_stdscr_pseudo_panel.win)
+    {
+        _stdscr_pseudo_panel.win = stdscr;
+        _stdscr_pseudo_panel.wstarty = 0;
+        _stdscr_pseudo_panel.wstartx = 0;
+        _stdscr_pseudo_panel.wendy = LINES;
+        _stdscr_pseudo_panel.wendx = COLS;
+        _stdscr_pseudo_panel.user = "stdscr";
+        _stdscr_pseudo_panel.obscure = (PANELOBS *)0;
+    }
+
+    if (pan)
+    {
+        int maxy, maxx;
+
+        pan->win = win;
+        pan->above = (PANEL *)0;
+        pan->below = (PANEL *)0;
+        getbegyx(win, pan->wstarty, pan->wstartx);
+        getmaxyx(win, maxy, maxx);
+        pan->wendy = pan->wstarty + maxy;
+        pan->wendx = pan->wstartx + maxx;
+#ifdef PANEL_DEBUG
+        pan->user = "new";
+#else
+        pan->user = (char *)0;
+#endif
+        pan->obscure = (PANELOBS *)0;
+        show_panel(pan);
+    }
+
+    return pan;
+}
+
+PANEL *panel_above(const PANEL *pan)
+{
+    return pan ? pan->above : _bottom_panel;
+}
+
+PANEL *panel_below(const PANEL *pan)
+{
+    return pan ? pan->below : _top_panel;
+}
+
+int panel_hidden(const PANEL *pan)
+{
+    if (!pan)
+        return ERR;
+
+    return _panel_is_linked(pan) ? ERR : OK;
+}
+
+const void *panel_userptr(const PANEL *pan)
+{
+    return pan ? pan->user : NULL;
+}
+
+WINDOW *panel_window(const PANEL *pan)
+{
+    PDC_LOG(("panel_window() - called\n"));
+
+    return pan->win;
+}
+
+int replace_panel(PANEL *pan, WINDOW *win)
+{
+    int maxy, maxx;
+
+    if (!pan)
+        return ERR;
+
+    if (_panel_is_linked(pan))
+        _override(pan, 0);
+
+    pan->win = win;
+    getbegyx(win, pan->wstarty, pan->wstartx);
+    getmaxyx(win, maxy, maxx);
+    pan->wendy = pan->wstarty + maxy;
+    pan->wendx = pan->wstartx + maxx;
+
+    if (_panel_is_linked(pan))
+        _calculate_obscure();
+
+    return OK;
+}
+
+int set_panel_userptr(PANEL *pan, const void *uptr)
+{
+    if (!pan)
+        return ERR;
+
+    pan->user = uptr;
+    return OK;
+}
+
+int show_panel(PANEL *pan)
+{
+    if (!pan)
+        return ERR;
+
+    if (pan == _top_panel)
+        return OK;
+
+    if (_panel_is_linked(pan))
+        hide_panel(pan);
+
+    _panel_link_top(pan);
+
+    return OK;
+}
+
+int top_panel(PANEL *pan)
+{
+    return show_panel(pan);
+}
+
+void update_panels(void)
+{
+    PANEL *pan;
+
+    PDC_LOG(("update_panels() - called\n"));
+
+    pan = _bottom_panel;
+
+    while (pan)
+    {
+        _override(pan, -1);
+        pan = pan->above;
+    }
+
+    if (is_wintouched(stdscr))
+        Wnoutrefresh(&_stdscr_pseudo_panel);
+    
+    pan = _bottom_panel;
+
+    while (pan)
+    {
+        if (is_wintouched(pan->win) || !pan->above)
+            Wnoutrefresh(pan);
+
+        pan = pan->above;
+    }
+}
diff --git a/apps/lib/curses/pdcurses/pdcurses/printw.c b/apps/lib/curses/pdcurses/pdcurses/printw.c
new file mode 100644
index 0000000..9be0c5f
--- /dev/null
+++ b/apps/lib/curses/pdcurses/pdcurses/printw.c
@@ -0,0 +1,123 @@
+/* Public Domain Curses */
+
+#include <curspriv.h>
+
+RCSID("$Id: printw.c,v 1.40 2008/07/13 16:08:18 wmcbrine Exp $")
+
+/*man-start**************************************************************
+
+  Name:                                                         printw
+
+  Synopsis:
+        int printw(const char *fmt, ...);
+        int wprintw(WINDOW *win, const char *fmt, ...);
+        int mvprintw(int y, int x, const char *fmt, ...);
+        int mvwprintw(WINDOW *win, int y, int x, const char *fmt,...);
+        int vwprintw(WINDOW *win, const char *fmt, va_list varglist);
+        int vw_printw(WINDOW *win, const char *fmt, va_list varglist);
+
+  Description:
+        The printw() functions add a formatted string to the window at 
+        the current or specified cursor position. The format strings are 
+        the same as used in the standard C library's printf(). (printw() 
+        can be used as a drop-in replacement for printf().)
+
+  Return Value:
+        All functions return the number of characters printed, or 
+        ERR on error.
+
+  Portability                                X/Open    BSD    SYS V
+        printw                                  Y       Y       Y
+        wprintw                                 Y       Y       Y
+        mvprintw                                Y       Y       Y
+        mvwprintw                               Y       Y       Y
+        vwprintw                                Y       -      4.0
+        vw_printw                               Y
+
+**man-end****************************************************************/
+
+#include <string.h>
+
+int vwprintw(WINDOW *win, const char *fmt, va_list varglist)
+{
+    char printbuf[513];
+    int len;
+
+    PDC_LOG(("vwprintw() - called\n"));
+
+#ifdef HAVE_VSNPRINTF
+    len = vsnprintf(printbuf, 512, fmt, varglist);
+#else
+    len = vsprintf(printbuf, fmt, varglist);
+#endif
+    return (waddstr(win, printbuf) == ERR) ? ERR : len;
+}
+
+int printw(const char *fmt, ...)
+{
+    va_list args;
+    int retval;
+
+    PDC_LOG(("printw() - called\n"));
+
+    va_start(args, fmt);
+    retval = vwprintw(stdscr, fmt, args);
+    va_end(args);
+
+    return retval;
+}
+
+int wprintw(WINDOW *win, const char *fmt, ...)
+{
+    va_list args;
+    int retval;
+
+    PDC_LOG(("wprintw() - called\n"));
+
+    va_start(args, fmt);
+    retval = vwprintw(win, fmt, args);
+    va_end(args);
+
+    return retval;
+}
+
+int mvprintw(int y, int x, const char *fmt, ...)
+{
+    va_list args;
+    int retval;
+
+    PDC_LOG(("mvprintw() - called\n"));
+
+    if (move(y, x) == ERR)
+        return ERR;
+
+    va_start(args, fmt);
+    retval = vwprintw(stdscr, fmt, args);
+    va_end(args);
+
+    return retval;
+}
+
+int mvwprintw(WINDOW *win, int y, int x, const char *fmt, ...)
+{
+    va_list args;
+    int retval;
+
+    PDC_LOG(("mvwprintw() - called\n"));
+
+    if (wmove(win, y, x) == ERR)
+        return ERR;
+
+    va_start(args, fmt);
+    retval = vwprintw(win, fmt, args);
+    va_end(args);
+
+    return retval;
+}
+
+int vw_printw(WINDOW *win, const char *fmt, va_list varglist)
+{
+    PDC_LOG(("vw_printw() - called\n"));
+
+    return vwprintw(win, fmt, varglist);
+}
diff --git a/apps/lib/curses/pdcurses/pdcurses/refresh.c b/apps/lib/curses/pdcurses/pdcurses/refresh.c
new file mode 100644
index 0000000..0b8e1ca
--- /dev/null
+++ b/apps/lib/curses/pdcurses/pdcurses/refresh.c
@@ -0,0 +1,276 @@
+/* Public Domain Curses */
+
+#include <curspriv.h>
+
+RCSID("$Id: refresh.c,v 1.56 2008/07/13 16:08:18 wmcbrine Exp $")
+
+/*man-start**************************************************************
+
+  Name:                                                         refresh
+
+  Synopsis:
+        int refresh(void);
+        int wrefresh(WINDOW *win);
+        int wnoutrefresh(WINDOW *win);
+        int doupdate(void);
+        int redrawwin(WINDOW *win);
+        int wredrawln(WINDOW *win, int beg_line, int num_lines);
+
+  Description:
+        wrefresh() copies the named window to the physical terminal 
+        screen, taking into account what is already there in order to 
+        optimize cursor movement. refresh() does the same, using stdscr. 
+        These routines must be called to get any output on the terminal, 
+        as other routines only manipulate data structures. Unless 
+        leaveok() has been enabled, the physical cursor of the terminal 
+        is left at the location of the window's cursor.
+
+        wnoutrefresh() and doupdate() allow multiple updates with more 
+        efficiency than wrefresh() alone. wrefresh() works by first 
+        calling wnoutrefresh(), which copies the named window to the 
+        virtual screen.  It then calls doupdate(), which compares the 
+        virtual screen to the physical screen and does the actual 
+        update. A series of calls to wrefresh() will result in 
+        alternating calls to wnoutrefresh() and doupdate(), causing 
+        several bursts of output to the screen.  By first calling 
+        wnoutrefresh() for each window, it is then possible to call 
+        doupdate() only once.
+
+        In PDCurses, redrawwin() is equivalent to touchwin(), and 
+        wredrawln() is the same as touchline(). In some other curses 
+        implementations, there's a subtle distinction, but it has no 
+        meaning in PDCurses.
+
+  Return Value:
+        All functions return OK on success and ERR on error.
+
+  Portability                                X/Open    BSD    SYS V
+        refresh                                 Y       Y       Y
+        wrefresh                                Y       Y       Y
+        wnoutrefresh                            Y       Y       Y
+        doupdate                                Y       Y       Y
+        redrawwin                               Y       -      4.0
+        wredrawln                               Y       -      4.0
+
+**man-end****************************************************************/
+
+#include <string.h>
+
+int wnoutrefresh(WINDOW *win)
+{
+    int begy, begx;     /* window's place on screen   */
+    int i, j;
+
+    PDC_LOG(("wnoutrefresh() - called: win=%p\n", win));
+
+    if ( !win || (win->_flags & (_PAD|_SUBPAD)) )
+        return ERR;
+
+    begy = win->_begy;
+    begx = win->_begx;
+
+    for (i = 0, j = begy; i < win->_maxy; i++, j++)
+    {
+        if (win->_firstch[i] != _NO_CHANGE)
+        {
+            chtype *src = win->_y[i];
+            chtype *dest = curscr->_y[j] + begx;
+
+            int first = win->_firstch[i]; /* first changed */
+            int last = win->_lastch[i];   /* last changed */
+
+            /* ignore areas on the outside that are marked as changed, 
+               but really aren't */
+
+            while (first <= last && src[first] == dest[first])
+                first++;
+
+            while (last >= first && src[last] == dest[last])
+                last--;
+
+            /* if any have really changed... */
+
+            if (first <= last)
+            {
+                memcpy(dest + first, src + first,
+                       (last - first + 1) * sizeof(chtype));
+
+                first += begx; 
+                last += begx;
+
+                if (first < curscr->_firstch[j] ||
+                    curscr->_firstch[j] == _NO_CHANGE)
+                    curscr->_firstch[j] = first;
+
+                if (last > curscr->_lastch[j])
+                    curscr->_lastch[j] = last;
+            }
+
+            win->_firstch[i] = _NO_CHANGE;  /* updated now */
+        }
+
+        win->_lastch[i] = _NO_CHANGE;       /* updated now */
+    }
+
+    if (win->_clear)
+        win->_clear = FALSE;
+
+    if (!win->_leaveit)
+    {
+        curscr->_cury = win->_cury + begy;
+        curscr->_curx = win->_curx + begx;
+    }
+
+    return OK;
+}
+
+int doupdate(void)
+{
+    int y;
+    bool clearall;
+
+    PDC_LOG(("doupdate() - called\n"));
+
+    if (!curscr)
+        return ERR;
+
+    if (isendwin())         /* coming back after endwin() called */
+    {
+        reset_prog_mode();
+        clearall = TRUE;
+        SP->alive = TRUE;   /* so isendwin() result is correct */
+    }
+    else
+        clearall = curscr->_clear;
+
+    for (y = 0; y < SP->lines; y++)
+    {
+        PDC_LOG(("doupdate() - Transforming line %d of %d: %s\n",
+                 y, SP->lines, (curscr->_firstch[y] != _NO_CHANGE) ?
+                 "Yes" : "No"));
+
+        if (clearall || curscr->_firstch[y] != _NO_CHANGE)
+        {
+            int first, last;
+
+            chtype *src = curscr->_y[y];
+            chtype *dest = pdc_lastscr->_y[y];
+
+            if (clearall)
+            {
+                first = 0;
+                last = COLS - 1;
+            }
+            else
+            {
+                first = curscr->_firstch[y];
+                last = curscr->_lastch[y];
+            }
+
+            while (first <= last)
+            {
+                int len = 0;
+
+                /* build up a run of changed cells; if two runs are
+                   separated by a single unchanged cell, ignore the
+                   break */
+
+                if (clearall)
+                    len = last - first + 1;
+                else
+                    while (first + len <= last &&
+                           (src[first + len] != dest[first + len] ||
+                            (len && first + len < last &&
+                             src[first + len + 1] != dest[first + len + 1])
+                           )
+                          )
+                        len++;
+
+                /* update the screen, and pdc_lastscr */
+
+                if (len)
+                {
+                    PDC_transform_line(y, first, len, src + first);
+                    memcpy(dest + first, src + first, len * sizeof(chtype));
+                    first += len;
+                }
+
+                /* skip over runs of unchanged cells */
+
+                while (first <= last && src[first] == dest[first])
+                    first++;
+            }
+
+            curscr->_firstch[y] = _NO_CHANGE;
+            curscr->_lastch[y] = _NO_CHANGE;
+        }
+    }
+
+    curscr->_clear = FALSE;
+
+    if (SP->visibility)
+        PDC_gotoyx(curscr->_cury, curscr->_curx);
+
+    SP->cursrow = curscr->_cury;
+    SP->curscol = curscr->_curx;
+
+    return OK;
+}
+
+int wrefresh(WINDOW *win)
+{
+    bool save_clear;
+
+    PDC_LOG(("wrefresh() - called\n"));
+
+    if ( !win || (win->_flags & (_PAD|_SUBPAD)) )
+        return ERR;
+
+    save_clear = win->_clear;
+
+    if (win == curscr)
+        curscr->_clear = TRUE;
+    else
+        wnoutrefresh(win);
+
+    if (save_clear && win->_maxy == SP->lines && win->_maxx == SP->cols)
+        curscr->_clear = TRUE;
+
+    return doupdate();
+}
+
+int refresh(void)
+{
+    PDC_LOG(("refresh() - called\n"));
+
+    return wrefresh(stdscr);
+}
+
+int wredrawln(WINDOW *win, int start, int num)
+{
+    int i;
+
+    PDC_LOG(("wredrawln() - called: win=%p start=%d num=%d\n",
+        win, start, num));
+
+    if (!win || start > win->_maxy || start + num > win->_maxy)
+        return ERR;
+
+    for (i = start; i < start + num; i++)
+    {
+        win->_firstch[i] = 0;
+        win->_lastch[i] = win->_maxx - 1;
+    }
+
+    return OK;
+}
+
+int redrawwin(WINDOW *win)
+{
+    PDC_LOG(("redrawwin() - called: win=%p\n", win));
+
+    if (!win)
+        return ERR;
+
+    return wredrawln(win, 0, win->_maxy);
+}
diff --git a/apps/lib/curses/pdcurses/pdcurses/scanw.c b/apps/lib/curses/pdcurses/pdcurses/scanw.c
new file mode 100644
index 0000000..af2bcb9
--- /dev/null
+++ b/apps/lib/curses/pdcurses/pdcurses/scanw.c
@@ -0,0 +1,575 @@
+/* Public Domain Curses */
+
+#include <curspriv.h>
+
+RCSID("$Id: scanw.c,v 1.42 2008/07/14 12:22:13 wmcbrine Exp $")
+
+/*man-start**************************************************************
+
+  Name:                                                         scanw
+
+  Synopsis:
+        int scanw(const char *fmt, ...);
+        int wscanw(WINDOW *win, const char *fmt, ...);
+        int mvscanw(int y, int x, const char *fmt, ...);
+        int mvwscanw(WINDOW *win, int y, int x, const char *fmt, ...);
+        int vwscanw(WINDOW *win, const char *fmt, va_list varglist);
+        int vw_scanw(WINDOW *win, const char *fmt, va_list varglist);
+
+  Description:
+        These routines correspond to the standard C library's scanf()
+        family. Each gets a string from the window via wgetnstr(), and
+        uses the resulting line as input for the scan.
+
+  Return Value:
+        On successful completion, these functions return the number of
+        items successfully matched.  Otherwise they return ERR.
+
+  Portability                                X/Open    BSD    SYS V
+        scanw                                   Y       Y       Y
+        wscanw                                  Y       Y       Y
+        mvscanw                                 Y       Y       Y
+        mvwscanw                                Y       Y       Y
+        vwscanw                                 Y       -      4.0
+        vw_scanw                                Y
+
+**man-end****************************************************************/
+
+#include <string.h>
+
+#ifndef HAVE_VSSCANF
+# include <stdlib.h>
+# include <ctype.h>
+# include <limits.h>
+
+static int _pdc_vsscanf(const char *, const char *, va_list);
+
+# define vsscanf _pdc_vsscanf
+#endif
+
+int vwscanw(WINDOW *win, const char *fmt, va_list varglist)
+{
+    char scanbuf[256];
+
+    PDC_LOG(("vwscanw() - called\n"));
+
+    if (wgetnstr(win, scanbuf, 255) == ERR)
+        return ERR;
+
+    return vsscanf(scanbuf, fmt, varglist);
+}
+
+int scanw(const char *fmt, ...)
+{
+    va_list args;
+    int retval;
+
+    PDC_LOG(("scanw() - called\n"));
+
+    va_start(args, fmt);
+    retval = vwscanw(stdscr, fmt, args);
+    va_end(args);
+
+    return retval;
+}
+
+int wscanw(WINDOW *win, const char *fmt, ...)
+{
+    va_list args;
+    int retval;
+
+    PDC_LOG(("wscanw() - called\n"));
+
+    va_start(args, fmt);
+    retval = vwscanw(win, fmt, args);
+    va_end(args);
+
+    return retval;
+}
+
+int mvscanw(int y, int x, const char *fmt, ...)
+{
+    va_list args;
+    int retval;
+
+    PDC_LOG(("mvscanw() - called\n"));
+
+    if (move(y, x) == ERR)
+        return ERR;
+
+    va_start(args, fmt);
+    retval = vwscanw(stdscr, fmt, args);
+    va_end(args);
+
+    return retval;
+}
+
+int mvwscanw(WINDOW *win, int y, int x, const char *fmt, ...)
+{
+    va_list args;
+    int retval;
+
+    PDC_LOG(("mvscanw() - called\n"));
+
+    if (wmove(win, y, x) == ERR)
+        return ERR;
+
+    va_start(args, fmt);
+    retval = vwscanw(win, fmt, args);
+    va_end(args);
+
+    return retval;
+}
+
+int vw_scanw(WINDOW *win, const char *fmt, va_list varglist)
+{
+    PDC_LOG(("vw_scanw() - called\n"));
+
+    return vwscanw(win, fmt, varglist);
+}
+
+#ifndef HAVE_VSSCANF
+
+/* _pdc_vsscanf() - Internal routine to parse and format an input 
+   buffer. It scans a series of input fields; each field is formatted 
+   according to a supplied format string and the formatted input is 
+   stored in the variable number of addresses passed. Returns the number 
+   of input fields or EOF on error.
+
+   Don't compile this unless required. Some compilers (at least Borland 
+   C++ 3.0) have to link with math libraries due to the use of floats.
+
+   Based on vsscanf.c and input.c from emx 0.8f library source, 
+   Copyright (c) 1990-1992 by Eberhard Mattes, who has kindly agreed to 
+   its inclusion in PDCurses. */
+
+#define WHITE(x) ((x) == ' ' || (x) == '\t' || (x) == '\n')
+
+#define NEXT(x) \
+        do { \
+            x = *buf++; \
+            if (!x) \
+               return (count ? count : EOF); \
+            ++chars; \
+           } while (0)
+
+#define UNGETC() \
+        do { \
+            --buf; --chars; \
+           } while (0)
+
+static int _pdc_vsscanf(const char *buf, const char *fmt, va_list arg_ptr)
+{
+    int count, chars, c, width, radix, d, i;
+    int *int_ptr;
+    long *long_ptr;
+    short *short_ptr;
+    char *char_ptr;
+    unsigned char f;
+    char neg, assign, ok, size;
+    long n;
+    char map[256], end;
+    double dx, dd, *dbl_ptr;
+    float *flt_ptr;
+    int exp;
+    char eneg;
+
+    count = 0;
+    chars = 0;
+    c = 0;
+    while ((f = *fmt) != 0)
+    {
+        if (WHITE(f))
+        {
+            do
+            {
+                ++fmt;
+                f = *fmt;
+            }
+            while (WHITE(f));
+            do
+            {
+                c = *buf++;
+                if (!c)
+                {
+                    if (!f || count)
+                        return count;
+                    else
+                        return EOF;
+                } else
+                    ++chars;
+            }
+            while (WHITE(c));
+            UNGETC();
+        } else if (f != '%')
+        {
+            NEXT(c);
+            if (c != f)
+                return count;
+            ++fmt;
+        } else
+        {
+            assign = TRUE;
+            width = INT_MAX;
+            char_ptr = NULL;
+            ++fmt;
+            if (*fmt == '*')
+            {
+                assign = FALSE;
+                ++fmt;
+            }
+            if (isdigit(*fmt))
+            {
+                width = 0;
+                while (isdigit(*fmt))
+                    width = width * 10 + (*fmt++ - '0');
+                if (!width)
+                    width = INT_MAX;
+            }
+            size = 0;
+            if (*fmt == 'h' || *fmt == 'l')
+                size = *fmt++;
+            f = *fmt;
+            switch (f)
+            {
+            case 'c':
+                if (width == INT_MAX)
+                    width = 1;
+                if (assign)
+                    char_ptr = va_arg(arg_ptr, char *);
+                while (width > 0)
+                {
+                    --width;
+                    NEXT(c);
+                    if (assign)
+                    {
+                        *char_ptr++ = (char) c;
+                        ++count;
+                    }
+                }
+                break;
+            case '[':
+                memset(map, 0, 256);
+                end = 0;
+                ++fmt;
+                if (*fmt == '^')
+                {
+                    ++fmt;
+                    end = 1;
+                }
+                i = 0;
+                for (;;)
+                {
+                    f = (unsigned char) *fmt;
+                    switch (f)
+                    {
+                    case 0:
+                        /* avoid skipping past 0 */
+                        --fmt;
+                        NEXT(c);
+                        goto string;
+                    case ']':
+                        if (i > 0)
+                        {
+                            NEXT(c);
+                            goto string;
+                        }
+                        /* no break */
+                    default:
+                        if (fmt[1] == '-' && fmt[2]
+                            && f < (unsigned char)fmt[2])
+                        {
+                            memset(map + f, 1, (unsigned char)fmt[2] - f);
+                            fmt += 2;
+                        }
+                        else
+                            map[f] = 1;
+                        break;
+                    }
+                    ++fmt;
+                    ++i;
+                }
+            case 's':
+                memset(map, 0, 256);
+                map[' '] = 1;
+                map['\n'] = 1;
+                map['\r'] = 1;
+                map['\t'] = 1;
+                end = 1;
+                do
+                {
+                    NEXT(c);
+                }
+                while (WHITE(c));
+            string:
+                if (assign)
+                    char_ptr = va_arg(arg_ptr, char *);
+                while (width > 0 && map[(unsigned char) c] != end)
+                {
+                    --width;
+                    if (assign)
+                        *char_ptr++ = (char) c;
+                    c = *buf++;
+                    if (!c)
+                        break;
+                    else
+                        ++chars;
+                }
+                if (assign)
+                {
+                    *char_ptr = 0;
+                    ++count;
+                }
+                if (!c)
+                    return count;
+                else
+                    UNGETC();
+                break;
+            case 'f':
+            case 'e':
+            case 'E':
+            case 'g':
+            case 'G':
+                neg = ok = FALSE;
+                dx = 0.0;
+                do
+                {
+                    NEXT(c);
+                }
+                while (WHITE(c));
+                if (c == '+')
+                {
+                    NEXT(c);
+                    --width;
+                } else if (c == '-')
+                {
+                    neg = TRUE;
+                    NEXT(c);
+                    --width;
+                }
+                while (width > 0 && isdigit(c))
+                {
+                    --width;
+                    dx = dx * 10.0 + (double) (c - '0');
+                    ok = TRUE;
+                    c = *buf++;
+                    if (!c)
+                        break;
+                    else
+                        ++chars;
+                }
+                if (width > 0 && c == '.')
+                {
+                    --width;
+                    dd = 10.0;
+                    NEXT(c);
+                    while (width > 0 && isdigit(c))
+                    {
+                        --width;
+                        dx += (double) (c - '0') / dd;
+                        dd *= 10.0;
+                        ok = TRUE;
+                        c = *buf++;
+                        if (!c)
+                            break;
+                        else
+                            ++chars;
+                    }
+                }
+                if (!ok)
+                    return count;
+                if (width > 0 && (c == 'e' || c == 'E'))
+                {
+                    eneg = FALSE;
+                    exp = 0;
+                    NEXT(c);
+                    --width;
+                    if (width > 0 && c == '+')
+                    {
+                        NEXT(c);
+                        --width;
+                    } else if (width > 0 && c == '-')
+                    {
+                        eneg = TRUE;
+                        NEXT(c);
+                        --width;
+                    }
+                    if (!(width > 0 && isdigit(c)))
+                    {
+                        UNGETC();
+                        return count;
+                    }
+                    while (width > 0 && isdigit(c))
+                    {
+                        --width;
+                        exp = exp * 10 + (c - '0');
+                        c = *buf++;
+                        if (!c)
+                            break;
+                        else
+                            ++chars;
+                    }
+                    if (eneg)
+                        exp = -exp;
+                    while (exp > 0)
+                    {
+                        dx *= 10.0;
+                        --exp;
+                    }
+                    while (exp < 0)
+                    {
+                        dx /= 10.0;
+                        ++exp;
+                    }
+                }
+                if (assign)
+                {
+                    if (neg)
+                        dx = -dx;
+                    if (size == 'l')
+                    {
+                        dbl_ptr = va_arg(arg_ptr, double *);
+                        *dbl_ptr = dx;
+                    }
+                    else
+                    {
+                        flt_ptr = va_arg(arg_ptr, float *);
+                        *flt_ptr = (float)dx;
+                    }
+                    ++count;
+                }
+                if (!c)
+                    return count;
+                else
+                    UNGETC();
+                break;
+            case 'i':
+                neg = FALSE;
+                radix = 10;
+                do
+                {
+                    NEXT(c);
+                }
+                while (WHITE(c));
+                if (!(width > 0 && c == '0'))
+                    goto scan_complete_number;
+                NEXT(c);
+                --width;
+                if (width > 0 && (c == 'x' || c == 'X'))
+                {
+                    NEXT(c);
+                    radix = 16;
+                    --width;
+                }
+                else if (width > 0 && (c >= '0' && c <= '7'))
+                    radix = 8;
+                goto scan_unsigned_number;
+            case 'd':
+            case 'u':
+            case 'o':
+            case 'x':
+            case 'X':
+                do
+                {
+                    NEXT(c);
+                }
+                while (WHITE(c));
+                switch (f)
+                {
+                case 'o':
+                    radix = 8;
+                    break;
+                case 'x':
+                case 'X':
+                    radix = 16;
+                    break;
+                default:
+                    radix = 10;
+                    break;
+                }
+            scan_complete_number:
+                neg = FALSE;
+                if (width > 0 && c == '+')
+                {
+                    NEXT(c);
+                    --width;
+                }
+                else if (width > 0 && c == '-' && radix == 10)
+                {
+                    neg = TRUE;
+                    NEXT(c);
+                    --width;
+                }
+            scan_unsigned_number:
+                n = 0;
+                ok = FALSE;
+                while (width > 0)
+                {
+                    --width;
+                    if (isdigit(c))
+                        d = c - '0';
+                    else if (isupper(c))
+                        d = c - 'A' + 10;
+                    else if (islower(c))
+                        d = c - 'a' + 10;
+                    else
+                        break;
+                    if (d < 0 || d >= radix)
+                        break;
+                    ok = TRUE;
+                    n = n * radix + d;
+                    c = *buf++;
+                    if (!c)
+                        break;
+                    else
+                        ++chars;
+                }
+                if (!ok)
+                    return count;
+                if (assign)
+                {
+                    if (neg)
+                        n = -n;
+                    switch (size)
+                    {
+                    case 'h':
+                        short_ptr = va_arg(arg_ptr, short *);
+                        *short_ptr = (short) n;
+                        break;
+                    case 'l':
+                        long_ptr = va_arg(arg_ptr, long *);
+                        *long_ptr = (long) n;
+                        break;
+                    default:
+                        int_ptr = va_arg(arg_ptr, int *);
+                        *int_ptr = (int) n;
+                    }
+                    ++count;
+                }
+                if (!c)
+                    return count;
+                else
+                    UNGETC();
+                break;
+            case 'n':
+                if (assign)
+                {
+                    int_ptr = va_arg(arg_ptr, int *);
+                    *int_ptr = chars;
+                    ++count;
+                }
+                break;
+            default:
+                if (!f) /* % at end of string */
+                    return count;
+                NEXT(c);
+                if (c != f)
+                    return count;
+                break;
+            }
+            ++fmt;
+        }
+    }
+    return count;
+}
+#endif /* HAVE_VSSCANF */
diff --git a/apps/lib/curses/pdcurses/pdcurses/scr_dump.c b/apps/lib/curses/pdcurses/pdcurses/scr_dump.c
new file mode 100644
index 0000000..e02046e
--- /dev/null
+++ b/apps/lib/curses/pdcurses/pdcurses/scr_dump.c
@@ -0,0 +1,210 @@
+/* Public Domain Curses */
+
+#include <curspriv.h>
+
+RCSID("$Id: scr_dump.c,v 1.30 2008/07/13 16:08:18 wmcbrine Exp $")
+
+/*man-start**************************************************************
+
+  Name:                                                         scr_dump
+
+  Synopsis:
+        int putwin(WINDOW *win, FILE *filep);
+        WINDOW *getwin(FILE *filep);
+        int scr_dump(const char *filename);
+        int scr_init(const char *filename);
+        int scr_restore(const char *filename);
+        int scr_set(const char *filename);
+
+  Description:
+        getwin() reads window-related data previously stored in a file 
+        by putwin(). It then creates and initialises a new window using 
+        that data.
+
+        putwin() writes all data associated with a window into a file, 
+        using an unspecified format. This information can be retrieved 
+        later using getwin().
+
+        scr_dump() writes the current contents of the virtual screen to 
+        the file named by filename in an unspecified format.
+
+        scr_restore() function sets the virtual screen to the contents 
+        of the file named by filename, which must have been written 
+        using scr_dump(). The next refresh operation restores the screen 
+        to the way it looked in the dump file.
+
+        In PDCurses, scr_init() does nothing, and scr_set() is a synonym 
+        for scr_restore(). Also, scr_dump() and scr_restore() save and 
+        load from curscr. This differs from some other implementations, 
+        where scr_init() works with curscr, and scr_restore() works with 
+        newscr; but the effect should be the same. (PDCurses has no 
+        newscr.)
+
+  Return Value:
+        On successful completion, getwin() returns a pointer to the 
+        window it created. Otherwise, it returns a null pointer. Other 
+        functions return OK or ERR.
+
+  Portability                                X/Open    BSD    SYS V
+        putwin                                  Y
+        getwin                                  Y
+        scr_dump                                Y
+        scr_init                                Y
+        scr_restore                             Y
+        scr_set                                 Y
+
+**man-end****************************************************************/
+
+#include <stdlib.h>
+#include <string.h>
+
+#define DUMPVER 1   /* Should be updated whenever the WINDOW struct is
+                       changed */
+
+int putwin(WINDOW *win, FILE *filep)
+{
+    static const char *marker = "PDC";
+    static const unsigned char version = DUMPVER;
+
+    PDC_LOG(("putwin() - called\n"));
+
+    /* write the marker and the WINDOW struct */
+
+    if (filep && fwrite(marker, strlen(marker), 1, filep)
+              && fwrite(&version, 1, 1, filep)
+              && fwrite(win, sizeof(WINDOW), 1, filep))
+    {
+        int i;
+
+        /* write each line */
+
+        for (i = 0; i < win->_maxy && win->_y[i]; i++)
+            if (!fwrite(win->_y[i], win->_maxx * sizeof(chtype), 1, filep))
+                return ERR;
+
+        return OK;
+    }
+
+    return ERR;
+}
+
+WINDOW *getwin(FILE *filep)
+{
+    WINDOW *win;
+    char marker[4];
+    int i, nlines, ncols;
+
+    PDC_LOG(("getwin() - called\n"));
+
+    if ( !(win = malloc(sizeof(WINDOW))) )
+        return (WINDOW *)NULL;
+
+    /* check for the marker, and load the WINDOW struct */
+
+    if (!filep || !fread(marker, 4, 1, filep) || strncmp(marker, "PDC", 3)
+        || marker[3] != DUMPVER || !fread(win, sizeof(WINDOW), 1, filep))
+    {
+        free(win);
+        return (WINDOW *)NULL;
+    }
+
+    nlines = win->_maxy;
+    ncols = win->_maxx;
+
+    /* allocate the line pointer array */
+
+    if ( !(win->_y = malloc(nlines * sizeof(chtype *))) )
+    {
+        free(win);
+        return (WINDOW *)NULL;
+    }
+
+    /* allocate the minchng and maxchng arrays */
+
+    if ( !(win->_firstch = malloc(nlines * sizeof(int))) )
+    {
+        free(win->_y);
+        free(win);
+        return (WINDOW *)NULL;
+    }
+
+    if ( !(win->_lastch = malloc(nlines * sizeof(int))) )
+    {
+        free(win->_firstch);
+        free(win->_y);
+        free(win);
+        return (WINDOW *)NULL;
+    }
+
+    /* allocate the lines */
+
+    if ( !(win = PDC_makelines(win)) )
+        return (WINDOW *)NULL;
+
+    /* read them */
+
+    for (i = 0; i < nlines; i++)
+    {
+        if (!fread(win->_y[i], ncols * sizeof(chtype), 1, filep))
+        {
+            delwin(win);
+            return (WINDOW *)NULL;
+        }
+    }
+
+    touchwin(win);
+
+    return win;
+}
+
+int scr_dump(const char *filename)
+{
+    FILE *filep;
+
+    PDC_LOG(("scr_dump() - called: filename %s\n", filename));
+
+    if (filename && (filep = fopen(filename, "wb")) != NULL)
+    {
+        int result = putwin(curscr, filep);
+        fclose(filep);
+        return result;
+    }
+
+    return ERR;
+}
+
+int scr_init(const char *filename)
+{
+    PDC_LOG(("scr_init() - called: filename %s\n", filename));
+
+    return OK;
+}
+
+int scr_restore(const char *filename)
+{
+    FILE *filep;
+
+    PDC_LOG(("scr_restore() - called: filename %s\n", filename));
+
+    if (filename && (filep = fopen(filename, "rb")) != NULL)
+    {
+        WINDOW *replacement = getwin(filep);
+        fclose(filep);
+
+        if (replacement)
+        {
+            int result = overwrite(replacement, curscr);
+            delwin(replacement);
+            return result;
+        }
+    }
+
+    return ERR;
+}
+
+int scr_set(const char *filename)
+{
+    PDC_LOG(("scr_set() - called: filename %s\n", filename));
+
+    return scr_restore(filename);
+}
diff --git a/apps/lib/curses/pdcurses/pdcurses/scroll.c b/apps/lib/curses/pdcurses/pdcurses/scroll.c
new file mode 100644
index 0000000..c53e295
--- /dev/null
+++ b/apps/lib/curses/pdcurses/pdcurses/scroll.c
@@ -0,0 +1,98 @@
+/* Public Domain Curses */
+
+#include <curspriv.h>
+
+RCSID("$Id: scroll.c,v 1.36 2008/07/13 16:08:18 wmcbrine Exp $")
+
+/*man-start**************************************************************
+
+  Name:                                                         scroll
+
+  Synopsis:
+        int scroll(WINDOW *win);
+        int scrl(int n);
+        int wscrl(WINDOW *win, int n);
+
+  Description:
+        scroll() causes the window to scroll up one line.  This involves 
+        moving the lines in the window data strcture.
+ 
+        With a positive n, scrl() and wscrl() scroll the window up n 
+        lines (line i + n becomes i); otherwise they scroll the window 
+        down n lines.
+ 
+        For these functions to work, scrolling must be enabled via 
+        scrollok(). Note also that scrolling is not allowed if the 
+        supplied window is a pad.
+
+  Return Value:
+        All functions return OK on success and ERR on error.
+
+  Portability                                X/Open    BSD    SYS V
+        scroll                                  Y       Y       Y
+        scrl                                    Y       -      4.0
+        wscrl                                   Y       -      4.0
+
+**man-end****************************************************************/
+
+int wscrl(WINDOW *win, int n)
+{
+    int i, l, dir, start, end;
+    chtype blank, *temp;
+
+    /* Check if window scrolls. Valid for window AND pad */
+
+    if (!win || !win->_scroll || !n)
+        return ERR;
+
+    blank = win->_bkgd;
+
+    if (n > 0)
+    {
+        start = win->_tmarg;
+        end = win->_bmarg;
+        dir = 1;
+    }
+    else
+    {
+        start = win->_bmarg;
+        end = win->_tmarg;
+        dir = -1;
+    }
+
+    for (l = 0; l < (n * dir); l++) 
+    {
+        temp = win->_y[start];
+
+        /* re-arrange line pointers */
+
+        for (i = start; i != end; i += dir)
+            win->_y[i] = win->_y[i + dir];
+
+        win->_y[end] = temp;
+
+        /* make a blank line */
+
+        for (i = 0; i < win->_maxx; i++)
+            *temp++ = blank;
+    }
+
+    touchline(win, win->_tmarg, win->_bmarg - win->_tmarg + 1);
+
+    PDC_sync(win);
+    return OK;
+}
+
+int scrl(int n)
+{
+    PDC_LOG(("scrl() - called\n"));
+
+    return wscrl(stdscr, n);
+}
+
+int scroll(WINDOW *win)
+{
+    PDC_LOG(("scroll() - called\n"));
+
+    return wscrl(win, 1);
+}
diff --git a/apps/lib/curses/pdcurses/pdcurses/slk.c b/apps/lib/curses/pdcurses/pdcurses/slk.c
new file mode 100644
index 0000000..f97f406
--- /dev/null
+++ b/apps/lib/curses/pdcurses/pdcurses/slk.c
@@ -0,0 +1,643 @@
+/* Public Domain Curses */
+
+#include <curspriv.h>
+
+RCSID("$Id: slk.c,v 1.61 2008/07/13 16:08:18 wmcbrine Exp $")
+
+/*man-start**************************************************************
+
+  Name:                                                         slk
+
+  Synopsis:
+        int slk_init(int fmt);
+        int slk_set(int labnum, const char *label, int justify);
+        int slk_refresh(void);
+        int slk_noutrefresh(void);
+        char *slk_label(int labnum);
+        int slk_clear(void);
+        int slk_restore(void);
+        int slk_touch(void);
+        int slk_attron(const chtype attrs);
+        int slk_attr_on(const attr_t attrs, void *opts);
+        int slk_attrset(const chtype attrs);
+        int slk_attr_set(const attr_t attrs, short color_pair, void *opts);
+        int slk_attroff(const chtype attrs);
+        int slk_attr_off(const attr_t attrs, void *opts);
+        int slk_color(short color_pair);
+
+        int slk_wset(int labnum, const wchar_t *label, int justify);
+
+        int PDC_mouse_in_slk(int y, int x);
+        void PDC_slk_free(void);
+        void PDC_slk_initialize(void);
+
+        wchar_t *slk_wlabel(int labnum)
+
+  Description:
+        These functions manipulate a window that contain Soft Label Keys 
+        (SLK). To use the SLK functions, a call to slk_init() must be 
+        made BEFORE initscr() or newterm(). slk_init() removes 1 or 2 
+        lines from the useable screen, depending on the format selected.
+
+        The line(s) removed from the screen are used as a separate 
+        window, in which SLKs are displayed.
+
+        slk_init() requires a single parameter which describes the 
+        format of the SLKs as follows:
+ 
+                0       3-2-3 format
+                1       4-4 format
+                2       4-4-4 format (ncurses extension)
+                3       4-4-4 format with index line (ncurses extension)
+                        2 lines used
+                55      5-5 format (pdcurses format)
+
+        slk_refresh(), slk_noutrefresh() and slk_touch() are analogous
+        to refresh(), noutrefresh() and touch().
+
+  Return Value:
+        All functions return OK on success and ERR on error.
+
+  Portability                                X/Open    BSD    SYS V
+        slk_init                                Y       -       Y
+        slk_set                                 Y       -       Y
+        slk_refresh                             Y       -       Y
+        slk_noutrefresh                         Y       -       Y
+        slk_label                               Y       -       Y
+        slk_clear                               Y       -       Y
+        slk_restore                             Y       -       Y
+        slk_touch                               Y       -       Y
+        slk_attron                              Y       -       Y
+        slk_attrset                             Y       -       Y
+        slk_attroff                             Y       -       Y
+        slk_attr_on                             Y
+        slk_attr_set                            Y
+        slk_attr_off                            Y
+        slk_wset                                Y
+        PDC_mouse_in_slk                        -       -       -
+        PDC_slk_free                            -       -       -
+        PDC_slk_initialize                      -       -       -
+        slk_wlabel                              -       -       -
+
+**man-end****************************************************************/
+
+#include <stdlib.h>
+
+enum { LABEL_NORMAL = 8, LABEL_EXTENDED = 10, LABEL_NCURSES_EXTENDED = 12 };
+
+static int label_length = 0;
+static int labels = 0;
+static int label_fmt = 0;
+static int label_line = 0;
+static bool hidden = FALSE;
+
+static struct SLK {
+    chtype label[32];
+    int len;
+    int format;
+    int start_col;
+} *slk = (struct SLK *)NULL;
+
+/* slk_init() is the slk initialization routine.
+   This must be called before initscr().
+
+   label_fmt = 0, 1 or 55.
+       0 = 3-2-3 format
+       1 = 4 - 4 format
+       2 = 4-4-4 format (ncurses extension for PC 12 function keys)
+       3 = 4-4-4 format (ncurses extension for PC 12 function keys -
+    with index line)
+      55 = 5 - 5 format (extended for PC, 10 function keys) */
+
+int slk_init(int fmt)
+{
+    PDC_LOG(("slk_init() - called\n"));
+
+    if (SP)
+        return ERR;
+
+    switch (fmt) 
+    {
+    case 0:  /* 3 - 2 - 3 */
+        labels = LABEL_NORMAL;
+        break;
+
+    case 1:   /* 4 - 4 */
+        labels = LABEL_NORMAL;
+        break;
+
+    case 2:   /* 4 4 4 */
+        labels = LABEL_NCURSES_EXTENDED;
+        break;
+
+    case 3:   /* 4 4 4  with index */
+        labels = LABEL_NCURSES_EXTENDED;
+        break;
+
+    case 55:  /* 5 - 5 */
+        labels = LABEL_EXTENDED;
+        break;
+
+    default:
+        return ERR;
+    }
+
+    label_fmt = fmt;
+
+    slk = calloc(labels, sizeof(struct SLK));
+
+    if (!slk)
+        labels = 0;
+
+    return slk ? OK : ERR;
+}
+
+/* draw a single button */
+
+static void _drawone(int num)
+{
+    int i, col, slen;
+
+    if (hidden)
+        return;
+
+    slen = slk[num].len;
+
+    switch (slk[num].format)
+    {
+    case 0:  /* LEFT */
+        col = 0;
+        break;
+
+    case 1:  /* CENTER */
+        col = (label_length - slen) / 2;
+
+        if (col + slen > label_length)
+            --col;
+        break;
+
+    default:  /* RIGHT */
+        col = label_length - slen;
+    }
+
+    wmove(SP->slk_winptr, label_line, slk[num].start_col);
+
+    for (i = 0; i < label_length; ++i)
+        waddch(SP->slk_winptr, (i >= col && i < (col + slen)) ?
+               slk[num].label[i - col] : ' ');
+}
+
+/* redraw each button */
+
+static void _redraw(void)
+{
+    int i;
+
+    for (i = 0; i < labels; ++i)
+        _drawone(i);
+}
+
+/* slk_set() Used to set a slk label to a string.
+
+   labnum  = 1 - 8 (or 10) (number of the label)
+   label   = string (8 or 7 bytes total), or NULL
+   justify = 0 : left, 1 : center, 2 : right  */
+
+int slk_set(int labnum, const char *label, int justify)
+{
+#ifdef PDC_WIDE
+    wchar_t wlabel[32];
+
+    PDC_mbstowcs(wlabel, label, 31);
+    return slk_wset(labnum, wlabel, justify);
+#else
+    PDC_LOG(("slk_set() - called\n"));
+
+    if (labnum < 1 || labnum > labels || justify < 0 || justify > 2)
+        return ERR;
+
+    labnum--;
+
+    if (!label || !(*label)) 
+    {
+        /* Clear the label */
+
+        *slk[labnum].label = 0;
+        slk[labnum].format = 0;
+        slk[labnum].len = 0;
+    }
+    else
+    {
+        int i, j = 0;
+
+        /* Skip leading spaces */
+
+        while (label[j] == ' ')
+            j++;
+
+        /* Copy it */
+
+        for (i = 0; i < label_length; i++)
+        {
+            chtype ch = label[i + j];
+
+            slk[labnum].label[i] = ch;
+
+            if (!ch)
+                break;
+        }
+
+        /* Drop trailing spaces */
+
+        while ((i + j) && (label[i + j - 1] == ' '))
+            i--;
+
+        slk[labnum].label[i] = 0;
+        slk[labnum].format = justify;
+        slk[labnum].len = i;
+    }
+
+    _drawone(labnum);
+
+    return OK;
+#endif
+}
+
+int slk_refresh(void)
+{
+    PDC_LOG(("slk_refresh() - called\n"));
+
+    return (slk_noutrefresh() == ERR) ? ERR : doupdate();
+}
+
+int slk_noutrefresh(void)
+{
+    PDC_LOG(("slk_noutrefresh() - called\n"));
+
+    return wnoutrefresh(SP->slk_winptr);
+}
+
+char *slk_label(int labnum)
+{
+    static char temp[33];
+#ifdef PDC_WIDE
+    wchar_t *wtemp = slk_wlabel(labnum);
+
+    PDC_wcstombs(temp, wtemp, 32);
+#else
+    chtype *p;
+    int i;
+
+    PDC_LOG(("slk_label() - called\n"));
+
+    if (labnum < 1 || labnum > labels)
+        return (char *)0;
+
+    for (i = 0, p = slk[labnum - 1].label; *p; i++)
+        temp[i] = *p++;
+
+    temp[i] = '\0';
+#endif
+    return temp;
+}
+
+int slk_clear(void)
+{
+    PDC_LOG(("slk_clear() - called\n"));
+
+    hidden = TRUE;
+    werase(SP->slk_winptr);
+    return wrefresh(SP->slk_winptr);
+}
+
+int slk_restore(void)
+{
+    PDC_LOG(("slk_restore() - called\n"));
+
+    hidden = FALSE;
+    _redraw();
+    return wrefresh(SP->slk_winptr);
+}
+
+int slk_touch(void)
+{
+    PDC_LOG(("slk_touch() - called\n"));
+
+    return touchwin(SP->slk_winptr);
+}
+
+int slk_attron(const chtype attrs)
+{
+    int rc;
+
+    PDC_LOG(("slk_attron() - called\n"));
+
+    rc = wattron(SP->slk_winptr, attrs);
+    _redraw();
+
+    return rc;
+}
+
+int slk_attr_on(const attr_t attrs, void *opts)
+{
+    PDC_LOG(("slk_attr_on() - called\n"));
+
+    return slk_attron(attrs);
+}
+
+int slk_attroff(const chtype attrs)
+{
+    int rc;
+
+    PDC_LOG(("slk_attroff() - called\n"));
+
+    rc = wattroff(SP->slk_winptr, attrs);
+    _redraw();
+
+    return rc;
+}
+
+int slk_attr_off(const attr_t attrs, void *opts)
+{
+    PDC_LOG(("slk_attr_off() - called\n"));
+
+    return slk_attroff(attrs);
+}
+
+int slk_attrset(const chtype attrs)
+{
+    int rc;
+
+    PDC_LOG(("slk_attrset() - called\n"));
+
+    rc = wattrset(SP->slk_winptr, attrs);
+    _redraw();
+
+    return rc;
+}
+
+int slk_color(short color_pair)
+{
+    int rc;
+
+    PDC_LOG(("slk_color() - called\n"));
+
+    rc = wcolor_set(SP->slk_winptr, color_pair, NULL);
+    _redraw();
+
+    return rc;
+}
+
+int slk_attr_set(const attr_t attrs, short color_pair, void *opts)
+{
+    PDC_LOG(("slk_attr_set() - called\n"));
+
+    return slk_attrset(attrs | COLOR_PAIR(color_pair));
+}
+
+static void _slk_calc(void)
+{
+    int i, center, col = 0;
+    label_length = COLS / labels;
+
+    if (label_length > 31)
+        label_length = 31;
+
+    switch (label_fmt)
+    {
+    case 0:     /* 3 - 2 - 3 F-Key layout */
+
+        --label_length;
+
+        slk[0].start_col = col;
+        slk[1].start_col = (col += label_length);
+        slk[2].start_col = (col += label_length);
+
+        center = COLS / 2;
+
+        slk[3].start_col = center - label_length + 1;
+        slk[4].start_col = center + 1;
+
+        col = COLS - (label_length * 3) + 1;
+
+        slk[5].start_col = col;
+        slk[6].start_col = (col += label_length);
+        slk[7].start_col = (col += label_length);
+        break;
+
+    case 1:     /* 4 - 4 F-Key layout */
+
+        for (i = 0; i < 8; i++)
+        {
+            slk[i].start_col = col;
+            col += label_length;
+
+            if (i == 3)
+                col = COLS - (label_length * 4) + 1; 
+        }
+
+        break;
+
+    case 2:     /* 4 4 4 F-Key layout */
+    case 3:     /* 4 4 4 F-Key layout with index */
+
+        for (i = 0; i < 4; i++)
+        {
+            slk[i].start_col = col;
+            col += label_length;
+        }
+
+        center = COLS/2;
+
+        slk[4].start_col = center - (label_length * 2) + 1;
+        slk[5].start_col = center - label_length - 1;
+        slk[6].start_col = center + 1;
+        slk[7].start_col = center + label_length + 1;
+
+        col = COLS - (label_length * 4) + 1;
+
+        for (i = 8; i < 12; i++)
+        {
+            slk[i].start_col = col;
+            col += label_length;
+        }
+
+        break;
+
+    default:    /* 5 - 5 F-Key layout */
+
+        for (i = 0; i < 10; i++)
+        {
+            slk[i].start_col = col;
+            col += label_length;
+
+            if (i == 4)
+                col = COLS - (label_length * 5) + 1;
+        }
+    }
+
+    --label_length;
+
+    /* make sure labels are all in window */
+
+    _redraw();
+}
+
+void PDC_slk_initialize(void)
+{
+    if (slk)
+    {
+        if (label_fmt == 3)
+        {
+            SP->slklines = 2;
+            label_line = 1;
+        }
+        else
+            SP->slklines = 1;
+
+        if (!SP->slk_winptr)
+        {
+            if ( !(SP->slk_winptr = newwin(SP->slklines, COLS, 
+                                           LINES - SP->slklines, 0)) )
+                return;
+
+            wattrset(SP->slk_winptr, A_REVERSE);
+        }
+
+        _slk_calc();
+
+        /* if we have an index line, display it now */
+
+        if (label_fmt == 3)
+        {
+            chtype save_attr;
+            int i;
+
+            save_attr = SP->slk_winptr->_attrs;
+            wattrset(SP->slk_winptr, A_NORMAL);
+            wmove(SP->slk_winptr, 0, 0);
+            whline(SP->slk_winptr, 0, COLS);
+
+            for (i = 0; i < labels; i++)
+                mvwprintw(SP->slk_winptr, 0, slk[i].start_col, "F%d", i + 1);
+
+            SP->slk_winptr->_attrs = save_attr;
+        }
+
+        touchwin(SP->slk_winptr);
+    }
+}
+
+void PDC_slk_free(void)
+{
+    if (slk)
+    {
+        if (SP->slk_winptr)
+        {
+            delwin(SP->slk_winptr);
+            SP->slk_winptr = (WINDOW *)NULL;
+        }
+
+        free(slk);
+        slk = (struct SLK *)NULL;
+
+        label_length = 0;
+        labels = 0;
+        label_fmt = 0;
+        label_line = 0;
+        hidden = FALSE;
+    }
+}
+
+int PDC_mouse_in_slk(int y, int x)
+{
+    int i;
+
+    PDC_LOG(("PDC_mouse_in_slk() - called: y->%d x->%d\n", y, x));
+
+    /* If the line on which the mouse was clicked is NOT the last line 
+       of the screen, we are not interested in it. */
+
+    if (!slk || !SP->slk_winptr || (y != SP->slk_winptr->_begy + label_line))
+        return 0;
+
+    for (i = 0; i < labels; i++)
+        if (x >= slk[i].start_col && x < (slk[i].start_col + label_length))
+            return i + 1;
+
+    return 0;
+}
+
+#ifdef PDC_WIDE
+int slk_wset(int labnum, const wchar_t *label, int justify)
+{
+    PDC_LOG(("slk_wset() - called\n"));
+
+    if (labnum < 1 || labnum > labels || justify < 0 || justify > 2)
+        return ERR;
+
+    labnum--;
+
+    if (!label || !(*label)) 
+    {
+        /* Clear the label */
+
+        *slk[labnum].label = 0;
+        slk[labnum].format = 0;
+        slk[labnum].len = 0;
+    }
+    else
+    {
+        int i, j = 0;
+
+        /* Skip leading spaces */
+
+        while (label[j] == L' ')
+            j++;
+
+        /* Copy it */
+
+        for (i = 0; i < label_length; i++)
+        {
+            chtype ch = label[i + j];
+
+            slk[labnum].label[i] = ch;
+
+            if (!ch)
+                break;
+        }
+
+        /* Drop trailing spaces */
+
+        while ((i + j) && (label[i + j - 1] == L' '))
+            i--;
+
+        slk[labnum].label[i] = 0;
+        slk[labnum].format = justify;
+        slk[labnum].len = i;
+    }
+
+    _drawone(labnum);
+
+    return OK;
+}
+
+wchar_t *slk_wlabel(int labnum)
+{
+    static wchar_t temp[33];
+    chtype *p;
+    int i;
+
+    PDC_LOG(("slk_wlabel() - called\n"));
+
+    if (labnum < 1 || labnum > labels)
+        return (wchar_t *)0;
+
+    for (i = 0, p = slk[labnum - 1].label; *p; i++)
+        temp[i] = *p++;
+
+    temp[i] = '\0';
+
+    return temp;
+}
+#endif
diff --git a/apps/lib/curses/pdcurses/pdcurses/term.h b/apps/lib/curses/pdcurses/pdcurses/term.h
new file mode 100644
index 0000000..ce6bc4f
--- /dev/null
+++ b/apps/lib/curses/pdcurses/pdcurses/term.h
@@ -0,0 +1,57 @@
+/* Public Domain Curses */
+
+/* $Id: term.h,v 1.16 2008/07/13 16:08:16 wmcbrine Exp $ */
+
+/* PDCurses doesn't operate with terminfo, but we need these functions for 
+   compatibility, to allow some things (notably, interface libraries for 
+   other languages) to be compiled. Anyone who tries to actually _use_ 
+   them will be disappointed, since they only return ERR. */
+
+#ifndef __PDCURSES_TERM_H__
+#define __PDCURSES_TERM_H__ 1
+
+#include <curses.h>
+
+#if defined(__cplusplus) || defined(__cplusplus__) || defined(__CPLUSPLUS)
+extern "C"
+{
+#endif
+
+typedef struct
+{
+    const char *_termname;
+} TERMINAL;
+
+#ifdef PDC_DLL_BUILD
+# ifndef CURSES_LIBRARY
+__declspec(dllimport)  TERMINAL *cur_term;
+# else
+__declspec(dllexport) extern TERMINAL *cur_term;
+# endif
+#else
+extern TERMINAL *cur_term;
+#endif
+
+int     del_curterm(TERMINAL *);
+int     putp(const char *);
+int     restartterm(const char *, int, int *);
+TERMINAL *set_curterm(TERMINAL *);
+int     setterm(const char *);
+int     setupterm(const char *, int, int *);
+int     tgetent(char *, const char *);
+int     tgetflag(const char *);
+int     tgetnum(const char *);
+char   *tgetstr(const char *, char **);
+char   *tgoto(const char *, int, int);
+int     tigetflag(const char *);
+int     tigetnum(const char *);
+char   *tigetstr(const char *);
+char   *tparm(const char *, long, long, long, long, long, 
+              long, long, long, long);
+int     tputs(const char *, int, int (*)(int));
+
+#if defined(__cplusplus) || defined(__cplusplus__) || defined(__CPLUSPLUS)
+}
+#endif
+
+#endif /* __PDCURSES_TERM_H__ */
diff --git a/apps/lib/curses/pdcurses/pdcurses/termattr.c b/apps/lib/curses/pdcurses/pdcurses/termattr.c
new file mode 100644
index 0000000..06e9ee8
--- /dev/null
+++ b/apps/lib/curses/pdcurses/pdcurses/termattr.c
@@ -0,0 +1,176 @@
+/* Public Domain Curses */
+
+#include <curspriv.h>
+
+RCSID("$Id: termattr.c,v 1.54 2008/07/13 16:08:18 wmcbrine Exp $")
+
+/*man-start**************************************************************
+
+  Name:                                                         termattr
+
+  Synopsis:
+        int baudrate(void);
+        char erasechar(void);
+        bool has_ic(void);
+        bool has_il(void);
+        char killchar(void);
+        char *longname(void);
+        chtype termattrs(void);
+        attr_t term_attrs(void);
+        char *termname(void);
+
+        int erasewchar(wchar_t *ch);
+        int killwchar(wchar_t *ch);
+
+        char wordchar(void);
+
+  Description:
+        baudrate() is supposed to return the output speed of the 
+        terminal. In PDCurses, it simply returns INT_MAX.
+
+        has_ic and has_il() return TRUE. These functions have meaning in 
+        some other implementations of curses.
+
+        erasechar() and killchar() return ^H and ^U, respectively -- the 
+        ERASE and KILL characters. In other curses implementations, 
+        these may vary by terminal type. erasewchar() and killwchar() 
+        are the wide-character versions; they take a pointer to a 
+        location in which to store the character, and return OK or ERR.
+
+        longname() returns a pointer to a static area containing a
+        verbose description of the current terminal. The maximum length
+        of the string is 128 characters.  It is defined only after the
+        call to initscr() or newterm().
+
+        termname() returns a pointer to a static area containing a
+        short description of the current terminal (14 characters).
+
+        termattrs() returns a logical OR of all video attributes
+        supported by the terminal.
+
+        wordchar() is a PDCurses extension of the concept behind the 
+        functions erasechar() and killchar(), returning the "delete 
+        word" character, ^W.
+
+  Portability                                X/Open    BSD    SYS V
+        baudrate                                Y       Y       Y
+        erasechar                               Y       Y       Y
+        has_ic                                  Y       Y       Y
+        has_il                                  Y       Y       Y
+        killchar                                Y       Y       Y
+        longname                                Y       Y       Y
+        termattrs                               Y       Y       Y
+        termname                                Y       Y       Y
+        erasewchar                              Y
+        killwchar                               Y
+        term_attrs                              Y
+        wordchar                                -       -       -
+
+**man-end****************************************************************/
+
+#include <string.h>
+#include <limits.h>
+
+int baudrate(void)
+{
+    PDC_LOG(("baudrate() - called\n"));
+
+    return INT_MAX;
+}
+
+char erasechar(void)
+{
+    PDC_LOG(("erasechar() - called\n"));
+
+    return _ECHAR;      /* character delete char (^H) */
+}
+
+bool has_ic(void)
+{
+    PDC_LOG(("has_ic() - called\n"));
+
+    return TRUE;
+}
+
+bool has_il(void)
+{
+    PDC_LOG(("has_il() - called\n"));
+
+    return TRUE;
+}
+
+char killchar(void)
+{
+    PDC_LOG(("killchar() - called\n"));
+
+    return _DLCHAR;     /* line delete char (^U) */
+}
+
+char *longname(void)
+{
+    PDC_LOG(("longname() - called\n"));
+
+    return ttytype + 9; /* skip "pdcurses|" */
+}
+
+chtype termattrs(void)
+{
+    chtype temp = A_BLINK | A_BOLD | A_INVIS | A_REVERSE | A_UNDERLINE;
+
+    /* note: blink is bold background on some platforms */
+
+    PDC_LOG(("termattrs() - called\n"));
+
+    if (!SP->mono)
+        temp |= A_COLOR;
+
+    return temp;
+}
+
+attr_t term_attrs(void)
+{
+    PDC_LOG(("term_attrs() - called\n"));
+
+    return WA_BLINK | WA_BOLD | WA_INVIS | WA_LEFT | WA_REVERSE | 
+           WA_RIGHT | WA_UNDERLINE;
+}
+
+char *termname(void)
+{
+    PDC_LOG(("termname() - called\n"));
+
+    return "pdcurses";
+}
+
+char wordchar(void)
+{
+    PDC_LOG(("wordchar() - called\n"));
+
+    return _DWCHAR;         /* word delete char */
+}
+
+#ifdef PDC_WIDE
+int erasewchar(wchar_t *ch)
+{
+    PDC_LOG(("erasewchar() - called\n"));
+
+    if (!ch)
+        return ERR;
+
+    *ch = (wchar_t)_ECHAR;
+
+    return OK;
+}
+
+int killwchar(wchar_t *ch)
+{
+    PDC_LOG(("killwchar() - called\n"));
+
+    if (!ch)
+        return ERR;
+
+    *ch = (wchar_t)_DLCHAR;
+
+    return OK;
+}
+#endif
diff --git a/apps/lib/curses/pdcurses/pdcurses/terminfo.c b/apps/lib/curses/pdcurses/pdcurses/terminfo.c
new file mode 100644
index 0000000..c099ada
--- /dev/null
+++ b/apps/lib/curses/pdcurses/pdcurses/terminfo.c
@@ -0,0 +1,215 @@
+/* Public Domain Curses */
+
+#include <curspriv.h>
+
+RCSID("$Id: terminfo.c,v 1.37 2008/07/21 12:29:20 wmcbrine Exp $")
+
+/*man-start**************************************************************
+
+  Name:                                                         terminfo
+
+  Synopsis:
+        int mvcur(int oldrow, int oldcol, int newrow, int newcol);
+        int vidattr(chtype attr);
+        int vid_attr(attr_t attr, short color_pair, void *opt);
+        int vidputs(chtype attr, int (*putfunc)(int));
+        int vid_puts(attr_t attr, short color_pair, void *opt,
+                int (*putfunc)(int));
+
+        int del_curterm(TERMINAL *);
+        int putp(const char *);
+        int restartterm(const char *, int, int *);
+        TERMINAL *set_curterm(TERMINAL *);
+        int setterm(const char *term);
+        int setupterm(const char *, int, int *);
+        int tgetent(char *, const char *);
+        int tgetflag(const char *);
+        int tgetnum(const char *);
+        char *tgetstr(const char *, char **);
+        char *tgoto(const char *, int, int);
+        int tigetflag(const char *);
+        int tigetnum(const char *);
+        char *tigetstr(const char *);
+        char *tparm(const char *,long, long, long, long, long, long,
+                long, long, long);
+        int tputs(const char *, int, int (*)(int));
+
+  Description:
+        mvcur() lets you move the physical cursor without updating any 
+        window cursor positions. It returns OK or ERR.
+
+        The rest of these functions are currently implemented as stubs, 
+        returning the appropriate errors and doing nothing else.
+
+  Portability                                X/Open    BSD    SYS V
+        mvcur                                   Y       Y       Y
+
+**man-end****************************************************************/
+
+#include <term.h>
+
+TERMINAL *cur_term = NULL;
+
+int mvcur(int oldrow, int oldcol, int newrow, int newcol)
+{
+    PDC_LOG(("mvcur() - called: oldrow %d oldcol %d newrow %d newcol %d\n",
+             oldrow, oldcol, newrow, newcol));
+
+    if ((newrow >= LINES) || (newcol >= COLS) || (newrow < 0) || (newcol < 0))
+        return ERR;
+
+    PDC_gotoyx(newrow, newcol);
+    SP->cursrow = newrow;
+    SP->curscol = newcol;
+
+    return OK;
+}
+
+int vidattr(chtype attr)
+{
+    PDC_LOG(("vidattr() - called: attr %d\n", attr));
+
+    return ERR;
+}
+
+int vid_attr(attr_t attr, short color_pair, void *opt)
+{
+    PDC_LOG(("vid_attr() - called\n"));
+
+    return ERR;
+}
+
+int vidputs(chtype attr, int (*putfunc)(int))
+{
+    PDC_LOG(("vidputs() - called: attr %d\n", attr));
+
+    return ERR;
+}
+
+int vid_puts(attr_t attr, short color_pair, void *opt, int (*putfunc)(int))
+{
+    PDC_LOG(("vid_puts() - called\n"));
+
+    return ERR;
+}
+
+int del_curterm(TERMINAL *oterm)
+{
+    PDC_LOG(("del_curterm() - called\n"));
+
+    return ERR;
+}
+
+int putp(const char *str)
+{
+    PDC_LOG(("putp() - called: str %s\n", str));
+
+    return ERR;
+}
+
+int restartterm(const char *term, int filedes, int *errret)
+{
+    PDC_LOG(("restartterm() - called\n"));
+
+    if (errret)
+        *errret = -1;
+
+    return ERR;
+}
+
+TERMINAL *set_curterm(TERMINAL *nterm)
+{
+    PDC_LOG(("set_curterm() - called\n"));
+
+    return (TERMINAL *)NULL;
+}
+
+int setterm(const char *term)
+{
+    PDC_LOG(("setterm() - called\n"));
+
+    return ERR;
+}
+
+int setupterm(const char *term, int filedes, int *errret)
+{
+    PDC_LOG(("setupterm() - called\n"));
+
+    if (errret)
+        *errret = -1;
+    else
+        fprintf(stderr, "There is no terminfo database\n");
+
+    return ERR;
+}
+
+int tgetent(char *bp, const char *name)
+{
+    PDC_LOG(("tgetent() - called: name %s\n", name));
+
+    return ERR;
+}
+
+int tgetflag(const char *id)
+{
+    PDC_LOG(("tgetflag() - called: id %s\n", id));
+
+    return ERR;
+}
+
+int tgetnum(const char *id)
+{
+    PDC_LOG(("tgetnum() - called: id %s\n", id));
+
+    return ERR;
+}
+
+char *tgetstr(const char *id, char **area)
+{
+    PDC_LOG(("tgetstr() - called: id %s\n", id));
+
+    return (char *)NULL;
+}
+
+char *tgoto(const char *cap, int col, int row)
+{
+    PDC_LOG(("tgoto() - called\n"));
+
+    return (char *)NULL;
+}
+
+int tigetflag(const char *capname)
+{
+    PDC_LOG(("tigetflag() - called: capname %s\n", capname));
+
+    return -1;
+}
+
+int tigetnum(const char *capname)
+{
+    PDC_LOG(("tigetnum() - called: capname %s\n", capname));
+
+    return -2;
+}
+
+char *tigetstr(const char *capname)
+{
+    PDC_LOG(("tigetstr() - called: capname %s\n", capname));
+
+    return (char *)(-1);
+}
+
+char *tparm(const char *cap, long p1, long p2, long p3, long p4,
+            long p5, long p6, long p7, long p8, long p9)
+{
+    PDC_LOG(("tparm() - called: cap %s\n", cap));
+
+    return (char *)NULL;
+}
+
+int tputs(const char *str, int affcnt, int (*putfunc)(int))
+{
+    PDC_LOG(("tputs() - called\n"));
+
+    return ERR;
+}
diff --git a/apps/lib/curses/pdcurses/pdcurses/touch.c b/apps/lib/curses/pdcurses/pdcurses/touch.c
new file mode 100644
index 0000000..9355aa1
--- /dev/null
+++ b/apps/lib/curses/pdcurses/pdcurses/touch.c
@@ -0,0 +1,160 @@
+/* Public Domain Curses */
+
+#include <curspriv.h>
+
+RCSID("$Id: touch.c,v 1.29 2008/07/13 16:08:18 wmcbrine Exp $")
+
+/*man-start**************************************************************
+
+  Name:                                                         touch
+
+  Synopsis:
+        int touchwin(WINDOW *win);
+        int touchline(WINDOW *win, int start, int count);
+        int untouchwin(WINDOW *win);
+        int wtouchln(WINDOW *win, int y, int n, int changed);
+        bool is_linetouched(WINDOW *win, int line);
+        bool is_wintouched(WINDOW *win);
+
+  Description:
+        touchwin() and touchline() throw away all information about 
+        which parts of the window have been touched, pretending that the 
+        entire window has been drawn on.  This is sometimes necessary 
+        when using overlapping windows, since a change to one window 
+        will affect the other window, but the records of which lines 
+        have been changed in the other window will not reflect the 
+        change.
+
+        untouchwin() marks all lines in the window as unchanged since 
+        the last call to wrefresh().
+
+        wtouchln() makes n lines in the window, starting at line y, look 
+        as if they have (changed == 1) or have not (changed == 0) been 
+        changed since the last call to wrefresh().
+
+        is_linetouched() returns TRUE if the specified line in the 
+        specified window has been changed since the last call to 
+        wrefresh().
+
+        is_wintouched() returns TRUE if the specified window 
+        has been changed since the last call to wrefresh().
+
+  Return Value:
+        All functions return OK on success and ERR on error except
+        is_wintouched() and is_linetouched().
+
+  Portability                                X/Open    BSD    SYS V
+        touchwin                                Y       Y       Y
+        touchline                               Y       -      3.0
+        untouchwin                              Y       -      4.0
+        wtouchln                                Y       Y       Y
+        is_linetouched                          Y       -      4.0
+        is_wintouched                           Y       -      4.0
+
+**man-end****************************************************************/
+
+int touchwin(WINDOW *win)
+{
+    int i;
+
+    PDC_LOG(("touchwin() - called: Win=%x\n", win));
+
+    if (!win)
+        return ERR;
+
+    for (i = 0; i < win->_maxy; i++)
+    {
+        win->_firstch[i] = 0;
+        win->_lastch[i] = win->_maxx - 1;
+    }
+
+    return OK;
+}
+
+int touchline(WINDOW *win, int start, int count)
+{
+    int i;
+
+    PDC_LOG(("touchline() - called: win=%p start %d count %d\n",
+             win, start, count));
+
+    if (!win || start > win->_maxy || start + count > win->_maxy)
+        return ERR;
+
+    for (i = start; i < start + count; i++)
+    {
+        win->_firstch[i] = 0;
+        win->_lastch[i] = win->_maxx - 1;
+    }
+
+    return OK;
+}
+
+int untouchwin(WINDOW *win)
+{
+    int i;
+
+    PDC_LOG(("untouchwin() - called: win=%p", win));
+
+    if (!win)
+        return ERR;
+
+    for (i = 0; i < win->_maxy; i++)
+    {
+        win->_firstch[i] = _NO_CHANGE;
+        win->_lastch[i] = _NO_CHANGE;
+    }
+
+    return OK;
+}
+
+int wtouchln(WINDOW *win, int y, int n, int changed)
+{
+    int i;
+
+    PDC_LOG(("wtouchln() - called: win=%p y=%d n=%d changed=%d\n",
+             win, y, n, changed));
+
+    if (!win || y > win->_maxy || y + n > win->_maxy)
+        return ERR;
+
+    for (i = y; i < y + n; i++)
+    {
+        if (changed)
+        {
+            win->_firstch[i] = 0;
+            win->_lastch[i] = win->_maxx - 1;
+        }
+        else 
+        {
+            win->_firstch[i] = _NO_CHANGE;
+            win->_lastch[i] = _NO_CHANGE;
+        }
+    }
+
+    return OK;
+}
+
+bool is_linetouched(WINDOW *win, int line)
+{
+    PDC_LOG(("is_linetouched() - called: win=%p line=%d\n", win, line));
+
+    if (!win || line > win->_maxy || line < 0)
+        return FALSE;
+
+    return (win->_firstch[line] != _NO_CHANGE) ? TRUE : FALSE;
+}
+
+bool is_wintouched(WINDOW *win)
+{
+    int i;
+
+    PDC_LOG(("is_wintouched() - called: win=%p\n", win));
+
+    if (win)
+        for (i = 0; i < win->_maxy; i++)
+            if (win->_firstch[i] != _NO_CHANGE)
+                return TRUE;
+
+    return FALSE;
+}
diff --git a/apps/lib/curses/pdcurses/pdcurses/util.c b/apps/lib/curses/pdcurses/pdcurses/util.c
new file mode 100644
index 0000000..f0673fc
--- /dev/null
+++ b/apps/lib/curses/pdcurses/pdcurses/util.c
@@ -0,0 +1,309 @@
+/* Public Domain Curses */
+
+#include <curspriv.h>
+
+RCSID("$Id: util.c,v 1.71 2008/07/13 16:08:18 wmcbrine Exp $")
+
+/*man-start**************************************************************
+
+  Name:                                                         util
+
+  Synopsis:
+        char *unctrl(chtype c);
+        void filter(void);
+        void use_env(bool x);
+        int delay_output(int ms);
+
+        int getcchar(const cchar_t *wcval, wchar_t *wch, attr_t *attrs,
+                     short *color_pair, void *opts);
+        int setcchar(cchar_t *wcval, const wchar_t *wch, const attr_t attrs,
+                     short color_pair, const void *opts);
+        wchar_t *wunctrl(cchar_t *wc);
+
+        int PDC_mbtowc(wchar_t *pwc, const char *s, size_t n);
+        size_t PDC_mbstowcs(wchar_t *dest, const char *src, size_t n);
+        size_t PDC_wcstombs(char *dest, const wchar_t *src, size_t n);
+
+  Description:
+        unctrl() expands the text portion of the chtype c into a 
+        printable string. Control characters are changed to the "^X" 
+        notation; others are passed through. wunctrl() is the wide- 
+        character version of the function.
+
+        filter() and use_env() are no-ops in PDCurses.
+
+        delay_output() inserts an ms millisecond pause in output.
+
+        getcchar() works in two modes: When wch is not NULL, it reads 
+        the cchar_t pointed to by wcval and stores the attributes in 
+        attrs, the color pair in color_pair, and the text in the
+        wide-character string wch. When wch is NULL, getcchar() merely 
+        returns the number of wide characters in wcval. In either mode, 
+        the opts argument is unused.
+
+        setcchar constructs a cchar_t at wcval from the wide-character 
+        text at wch, the attributes in attr and the color pair in 
+        color_pair. The opts argument is unused.
+
+        Currently, the length returned by getcchar() is always 1 or 0.
+        Similarly, setcchar() will only take the first wide character
+        from wch, and ignore any others that it "should" take (i.e.,
+        combining characters). Nor will it correctly handle any 
+        character outside the basic multilingual plane (UCS-2).
+
+  Return Value:
+        unctrl() and wunctrl() return NULL on failure. delay_output() 
+        always returns OK.
+
+        getcchar() returns the number of wide characters wcval points to 
+        when wch is NULL; when it's not, getcchar() returns OK or ERR. 
+
+        setcchar() returns OK or ERR.
+
+  Portability                                X/Open    BSD    SYS V
+        unctrl                                  Y       Y       Y
+        filter                                  Y       -      3.0
+        use_env                                 Y       -      4.0
+        delay_output                            Y       Y       Y
+        getcchar                                Y
+        setcchar                                Y
+        wunctrl                                 Y
+        PDC_mbtowc                              -       -       -
+        PDC_mbstowcs                            -       -       -
+        PDC_wcstombs                            -       -       -
+
+**man-end****************************************************************/
+
+#ifdef PDC_WIDE
+# ifdef PDC_FORCE_UTF8
+#  include <string.h>
+# else
+#  include <stdlib.h>
+# endif
+#endif
+
+char *unctrl(chtype c)
+{
+    static char strbuf[3] = {0, 0, 0};
+
+    chtype ic;
+
+    PDC_LOG(("unctrl() - called\n"));
+
+    ic = c & A_CHARTEXT;
+
+    if (ic >= 0x20 && ic != 0x7f)       /* normal characters */
+    {
+        strbuf[0] = (char)ic;
+        strbuf[1] = '\0';
+        return strbuf;
+    }
+
+    strbuf[0] = '^';            /* '^' prefix */
+
+    if (ic == 0x7f)             /* 0x7f == DEL */
+        strbuf[1] = '?';
+    else                    /* other control */
+        strbuf[1] = (char)(ic + '@');
+
+    return strbuf;
+}
+
+void filter(void)
+{
+    PDC_LOG(("filter() - called\n"));
+}
+
+void use_env(bool x)
+{
+    PDC_LOG(("use_env() - called: x %d\n", x));
+}
+
+int delay_output(int ms)
+{
+    PDC_LOG(("delay_output() - called: ms %d\n", ms));
+
+    return napms(ms);
+}
+
+#ifdef PDC_WIDE
+int getcchar(const cchar_t *wcval, wchar_t *wch, attr_t *attrs,
+             short *color_pair, void *opts)
+{
+    if (!wcval)
+        return ERR;
+
+    if (wch)
+    {
+        if (!attrs || !color_pair)
+            return ERR;
+
+        *wch = (*wcval & A_CHARTEXT);
+        *attrs = (*wcval & (A_ATTRIBUTES & ~A_COLOR));
+        *color_pair = PAIR_NUMBER(*wcval & A_COLOR);
+
+        if (*wch)
+            *++wch = L'\0';
+
+        return OK;
+    }
+    else
+        return ((*wcval & A_CHARTEXT) != L'\0');
+}
+
+int setcchar(cchar_t *wcval, const wchar_t *wch, const attr_t attrs,
+             short color_pair, const void *opts)
+{
+    if (!wcval || !wch)
+        return ERR;
+
+    *wcval = *wch | attrs | COLOR_PAIR(color_pair);
+
+    return OK;
+}
+
+wchar_t *wunctrl(cchar_t *wc)
+{
+    static wchar_t strbuf[3] = {0, 0, 0};
+
+    cchar_t ic;
+
+    PDC_LOG(("wunctrl() - called\n"));
+
+    ic = *wc & A_CHARTEXT;
+
+    if (ic >= 0x20 && ic != 0x7f)       /* normal characters */
+    {
+        strbuf[0] = (wchar_t)ic;
+        strbuf[1] = L'\0';
+        return strbuf;
+    }
+
+    strbuf[0] = '^';            /* '^' prefix */
+
+    if (ic == 0x7f)             /* 0x7f == DEL */
+        strbuf[1] = '?';
+    else                    /* other control */
+        strbuf[1] = (wchar_t)(ic + '@');
+
+    return strbuf;
+}
+
+int PDC_mbtowc(wchar_t *pwc, const char *s, size_t n)
+{
+# ifdef PDC_FORCE_UTF8
+    wchar_t key;
+    int i = -1;
+    const unsigned char *string;
+
+    if (!s || (n < 1))
+        return -1;
+
+    if (!*s)
+        return 0;
+
+    string = (const unsigned char *)s;
+
+    key = string[0];
+
+    /* Simplistic UTF-8 decoder -- only does the BMP, minimal validation */
+
+    if (key & 0x80)
+    {
+        if ((key & 0xe0) == 0xc0)
+        {
+            if (1 < n)
+            {
+                key = ((key & 0x1f) << 6) | (string[1] & 0x3f);
+                i = 2;
+            }
+        }
+        else if ((key & 0xe0) == 0xe0)
+        {
+            if (2 < n)
+            {
+                key = ((key & 0x0f) << 12) | ((string[1] & 0x3f) << 6) |
+                      (string[2] & 0x3f);
+                i = 3;
+            }
+        }
+    }
+    else
+        i = 1;
+
+    if (i)
+        *pwc = key;
+
+    return i;
+# else
+    return mbtowc(pwc, s, n);
+# endif
+}
+
+size_t PDC_mbstowcs(wchar_t *dest, const char *src, size_t n)
+{
+# ifdef PDC_FORCE_UTF8
+    size_t i = 0, len;
+
+    if (!src || !dest)
+        return 0;
+
+    len = strlen(src);
+
+    while (*src && i < n)
+    {
+        int retval = PDC_mbtowc(dest + i, src, len);
+
+        if (retval < 1)
+            return -1;
+
+        src += retval;
+        len -= retval;
+        i++;
+    }
+# else
+    size_t i = mbstowcs(dest, src, n);
+# endif
+    dest[i] = 0;
+    return i;
+}
+
+size_t PDC_wcstombs(char *dest, const wchar_t *src, size_t n)
+{
+# ifdef PDC_FORCE_UTF8
+    size_t i = 0;
+
+    if (!src || !dest)
+        return 0;
+
+    while (*src && i < n)
+    {
+        chtype code = *src++;
+
+        if (code < 0x80)
+        {
+            dest[i] = code;
+            i++;
+        }
+        else
+            if (code < 0x800)
+            {
+                dest[i] = ((code & 0x07c0) >> 6) | 0xc0;
+                dest[i + 1] = (code & 0x003f) | 0x80;
+                i += 2;
+            }
+            else
+            {
+                dest[i] = ((code & 0xf000) >> 12) | 0xe0;
+                dest[i + 1] = ((code & 0x0fc0) >> 6) | 0x80;
+                dest[i + 2] = (code & 0x003f) | 0x80;
+                i += 3;
+            }
+    }
+# else
+    size_t i = wcstombs(dest, src, n);
+# endif
+    dest[i] = '\0';
+    return i;
+}
+#endif
diff --git a/apps/lib/curses/pdcurses/pdcurses/window.c b/apps/lib/curses/pdcurses/pdcurses/window.c
new file mode 100644
index 0000000..dbfd584
--- /dev/null
+++ b/apps/lib/curses/pdcurses/pdcurses/window.c
@@ -0,0 +1,562 @@
+/* Public Domain Curses */
+
+#include <curspriv.h>
+
+RCSID("$Id: window.c,v 1.62 2008/07/13 16:08:18 wmcbrine Exp $")
+
+/*man-start**************************************************************
+
+  Name:                                                         window
+
+  Synopsis:
+        WINDOW *newwin(int nlines, int ncols, int begy, int begx);
+        WINDOW *derwin(WINDOW* orig, int nlines, int ncols,
+                int begy, int begx);
+        WINDOW *subwin(WINDOW* orig, int nlines, int ncols,
+                int begy, int begx);
+        WINDOW *dupwin(WINDOW *win);
+        int delwin(WINDOW *win);
+        int mvwin(WINDOW *win, int y, int x);
+        int mvderwin(WINDOW *win, int pary, int parx);
+        int syncok(WINDOW *win, bool bf);
+        void wsyncup(WINDOW *win);
+        void wcursyncup(WINDOW *win);
+        void wsyncdown(WINDOW *win);
+
+        WINDOW *resize_window(WINDOW *win, int nlines, int ncols);
+        int wresize(WINDOW *win, int nlines, int ncols);
+        WINDOW *PDC_makelines(WINDOW *win);
+        WINDOW *PDC_makenew(int nlines, int ncols, int begy, int begx);
+        void PDC_sync(WINDOW *win);
+
+  Description:
+        newwin() creates a new window with the given number of lines,
+        nlines and columns, ncols. The upper left corner of the window
+        is at line begy, column begx. If nlines is zero, it defaults to
+        LINES - begy; ncols to COLS - begx. Create a new full-screen
+        window by calling newwin(0, 0, 0, 0).
+
+        delwin() deletes the named window, freeing all associated 
+        memory. In the case of overlapping windows, subwindows should be 
+        deleted before the main window.
+
+        mvwin() moves the window so that the upper left-hand corner is
+        at position (y,x). If the move would cause the window to be off
+        the screen, it is an error and the window is not moved. Moving
+        subwindows is allowed.
+
+        subwin() creates a new subwindow within a window.  The
+        dimensions of the subwindow are nlines lines and ncols columns.
+        The subwindow is at position (begy, begx) on the screen.  This
+        position is relative to the screen, and not to the window orig.
+        Changes made to either window will affect both.  When using this
+        routine, you will often need to call touchwin() before calling
+        wrefresh().
+
+        derwin() is the same as subwin(), except that begy and begx are
+        relative to the origin of the window orig rather than the
+        screen.  There is no difference between subwindows and derived
+        windows.
+
+        mvderwin() moves a derived window (or subwindow) inside its
+        parent window.  The screen-relative parameters of the window are
+        not changed.  This routine is used to display different parts of
+        the parent window at the same physical position on the screen.
+
+        dupwin() creates an exact duplicate of the window win.
+
+        wsyncup() causes a touchwin() of all of the window's parents.
+
+        If wsyncok() is called with a second argument of TRUE, this
+        causes a wsyncup() to be called every time the window is
+        changed.
+
+        wcursyncup() causes the current cursor position of all of a
+        window's ancestors to reflect the current cursor position of the
+        current window.
+
+        wsyncdown() causes a touchwin() of the current window if any of
+        its parent's windows have been touched.
+
+        resize_window() allows the user to resize an existing window. It 
+        returns the pointer to the new window, or NULL on failure.
+
+        wresize() is an ncurses-compatible wrapper for resize_window().
+        Note that, unlike ncurses, it will NOT process any subwindows of
+        the window. (However, you still can call it _on_ subwindows.) It 
+        returns OK or ERR.
+
+        PDC_makenew() allocates all data for a new WINDOW * except the
+        actual lines themselves. If it's unable to allocate memory for
+        the window structure, it will free all allocated memory and
+        return a NULL pointer.
+
+        PDC_makelines() allocates the memory for the lines.
+
+        PDC_sync() handles wrefresh() and wsyncup() calls when a window
+        is changed.
+
+  Return Value:
+        newwin(), subwin(), derwin() and dupwin() return a pointer
+        to the new window, or NULL on failure. delwin(), mvwin(),
+        mvderwin() and syncok() return OK or ERR. wsyncup(),
+        wcursyncup() and wsyncdown() return nothing.
+
+  Errors:
+        It is an error to call resize_window() before calling initscr().
+        Also, an error will be generated if we fail to create a newly
+        sized replacement window for curscr, or stdscr. This could
+        happen when increasing the window size. NOTE: If this happens,
+        the previously successfully allocated windows are left alone;
+        i.e., the resize is NOT cancelled for those windows.
+
+  Portability                                X/Open    BSD    SYS V
+        newwin                                  Y       Y       Y
+        delwin                                  Y       Y       Y
+        mvwin                                   Y       Y       Y
+        subwin                                  Y       Y       Y
+        derwin                                  Y       -       Y
+        mvderwin                                Y       -       Y
+        dupwin                                  Y       -      4.0
+        wsyncup                                 Y       -      4.0
+        syncok                                  Y       -      4.0
+        wcursyncup                              Y       -      4.0
+        wsyncdown                               Y       -      4.0
+        resize_window                           -       -       -
+        wresize                                 -       -       -
+        PDC_makelines                           -       -       -
+        PDC_makenew                             -       -       -
+        PDC_sync                                -       -       -
+
+**man-end****************************************************************/
+
+#include <stdlib.h>
+
+WINDOW *PDC_makenew(int nlines, int ncols, int begy, int begx)
+{
+    WINDOW *win;
+
+    PDC_LOG(("PDC_makenew() - called: lines %d cols %d begy %d begx %d\n",
+             nlines, ncols, begy, begx));
+
+    /* allocate the window structure itself */
+
+    if ((win = calloc(1, sizeof(WINDOW))) == (WINDOW *)NULL)
+        return win;
+
+    /* allocate the line pointer array */
+
+    if ((win->_y = malloc(nlines * sizeof(chtype *))) == NULL)
+    {
+        free(win);
+        return (WINDOW *)NULL;
+    }
+
+    /* allocate the minchng and maxchng arrays */
+
+    if ((win->_firstch = malloc(nlines * sizeof(int))) == NULL)
+    {
+        free(win->_y);
+        free(win);
+        return (WINDOW *)NULL;
+    }
+
+    if ((win->_lastch = malloc(nlines * sizeof(int))) == NULL)
+    {
+        free(win->_firstch);
+        free(win->_y);
+        free(win);
+        return (WINDOW *)NULL;
+    }
+
+    /* initialize window variables */
+
+    win->_maxy = nlines;  /* real max screen size */
+    win->_maxx = ncols;   /* real max screen size */
+    win->_begy = begy;
+    win->_begx = begx;
+    win->_bkgd = ' ';     /* wrs 4/10/93 -- initialize background to blank */
+    win->_clear = (bool) ((nlines == LINES) && (ncols == COLS));
+    win->_bmarg = nlines - 1;
+    win->_parx = win->_pary = -1;
+
+    /* init to say window all changed */
+
+    touchwin(win);
+
+    return win;
+}
+
+WINDOW *PDC_makelines(WINDOW *win)
+{
+    int i, j, nlines, ncols;
+
+    PDC_LOG(("PDC_makelines() - called: lines %d cols %d\n", nlines, ncols));
+
+    if (!win)
+        return (WINDOW *)NULL;
+
+    nlines = win->_maxy;
+    ncols = win->_maxx;
+
+    for (i = 0; i < nlines; i++)
+    {
+        if ((win->_y[i] = malloc(ncols * sizeof(chtype))) == NULL)
+        {
+            /* if error, free all the data */
+
+            for (j = 0; j < i; j++)
+                free(win->_y[j]);
+
+            free(win->_firstch);
+            free(win->_lastch);
+            free(win->_y);
+            free(win);
+
+            return (WINDOW *)NULL;
+        }
+    }
+
+    return win;
+}
+
+void PDC_sync(WINDOW *win)
+{
+    PDC_LOG(("PDC_sync() - called:\n"));
+
+    if (win->_immed)
+        wrefresh(win);
+    if (win->_sync)
+        wsyncup(win);
+}
+
+WINDOW *newwin(int nlines, int ncols, int begy, int begx)
+{
+    WINDOW *win;
+
+    PDC_LOG(("newwin() - called:lines=%d cols=%d begy=%d begx=%d\n",
+             nlines, ncols, begy, begx));
+
+    if (!nlines)
+        nlines = LINES - begy;
+    if (!ncols)
+        ncols  = COLS  - begx;
+
+    if ( (begy + nlines > SP->lines || begx + ncols > SP->cols)
+        || !(win = PDC_makenew(nlines, ncols, begy, begx))
+        || !(win = PDC_makelines(win)) )
+        return (WINDOW *)NULL;
+
+    werase(win);
+
+    return win;
+}
+
+int delwin(WINDOW *win)
+{
+    int i;
+
+    PDC_LOG(("delwin() - called\n"));
+
+    if (!win)
+        return ERR;
+
+    /* subwindows use parents' lines */
+
+    if (!(win->_flags & (_SUBWIN|_SUBPAD)))
+        for (i = 0; i < win->_maxy && win->_y[i]; i++)
+            if (win->_y[i])
+                free(win->_y[i]);
+
+    free(win->_firstch);
+    free(win->_lastch);
+    free(win->_y);
+    free(win);
+
+    return OK;
+}
+
+int mvwin(WINDOW *win, int y, int x)
+{
+    PDC_LOG(("mvwin() - called\n"));
+
+    if (!win || (y + win->_maxy > LINES || y < 0)
+             || (x + win->_maxx > COLS || x < 0))
+        return ERR;
+
+    win->_begy = y;
+    win->_begx = x;
+    touchwin(win);
+
+    return OK;
+}
+
+WINDOW *subwin(WINDOW *orig, int nlines, int ncols, int begy, int begx)
+{
+    WINDOW *win;
+    int i;
+    int j = begy - orig->_begy;
+    int k = begx - orig->_begx;
+
+    PDC_LOG(("subwin() - called: lines %d cols %d begy %d begx %d\n",
+             nlines, ncols, begy, begx));
+
+    /* make sure window fits inside the original one */
+
+    if (!orig || (begy < orig->_begy) || (begx < orig->_begx) ||
+        (begy + nlines) > (orig->_begy + orig->_maxy) ||
+        (begx + ncols) > (orig->_begx + orig->_maxx))
+        return (WINDOW *)NULL;
+
+    if (!nlines)
+        nlines = orig->_maxy - 1 - j;
+    if (!ncols)
+        ncols  = orig->_maxx - 1 - k;
+
+    if ( !(win = PDC_makenew(nlines, ncols, begy, begx)) )
+        return (WINDOW *)NULL;
+
+    /* initialize window variables */
+
+    win->_attrs = orig->_attrs;
+    win->_bkgd = orig->_bkgd;
+    win->_leaveit = orig->_leaveit;
+    win->_scroll = orig->_scroll;
+    win->_nodelay = orig->_nodelay;
+    win->_use_keypad = orig->_use_keypad;
+    win->_immed = orig->_immed;
+    win->_sync = orig->_sync;
+    win->_pary = j;
+    win->_parx = k;
+    win->_parent = orig;
+
+    for (i = 0; i < nlines; i++, j++)
+        win->_y[i] = orig->_y[j] + k;
+
+    win->_flags |= _SUBWIN;
+
+    return win;
+}
+
+WINDOW *derwin(WINDOW *orig, int nlines, int ncols, int begy, int begx)
+{
+    return subwin(orig, nlines, ncols, begy + orig->_begy, begx + orig->_begx);
+}
+
+int mvderwin(WINDOW *win, int pary, int parx)
+{
+    int i, j;
+    WINDOW *mypar;
+
+    if (!win || !(win->_parent))
+        return ERR;
+
+    mypar = win->_parent;
+
+    if (pary < 0 || parx < 0 || (pary + win->_maxy) > mypar->_maxy ||
+                                (parx + win->_maxx) > mypar->_maxx)
+        return ERR;
+
+    j = pary;
+
+    for (i = 0; i < win->_maxy; i++)
+        win->_y[i] = (mypar->_y[j++]) + parx;
+
+    win->_pary = pary;
+    win->_parx = parx;
+
+    return OK;
+}
+
+WINDOW *dupwin(WINDOW *win)
+{
+    WINDOW *new;
+    chtype *ptr, *ptr1;
+    int nlines, ncols, begy, begx, i;
+
+    if (!win)
+        return (WINDOW *)NULL;
+
+    nlines = win->_maxy;
+    ncols = win->_maxx;
+    begy = win->_begy;
+    begx = win->_begx;
+
+    if ( !(new = PDC_makenew(nlines, ncols, begy, begx))
+        || !(new = PDC_makelines(new)) )
+        return (WINDOW *)NULL;
+
+    /* copy the contents of win into new */
+
+    for (i = 0; i < nlines; i++)
+    {
+        for (ptr = new->_y[i], ptr1 = win->_y[i];
+             ptr < new->_y[i] + ncols; ptr++, ptr1++)
+            *ptr = *ptr1;
+
+        new->_firstch[i] = 0;
+        new->_lastch[i] = ncols - 1;
+    }
+
+    new->_curx = win->_curx;
+    new->_cury = win->_cury;
+    new->_maxy = win->_maxy;
+    new->_maxx = win->_maxx;
+    new->_begy = win->_begy;
+    new->_begx = win->_begx;
+    new->_flags = win->_flags;
+    new->_attrs = win->_attrs;
+    new->_clear = win->_clear;
+    new->_leaveit = win->_leaveit;
+    new->_scroll = win->_scroll;
+    new->_nodelay = win->_nodelay;
+    new->_use_keypad = win->_use_keypad;
+    new->_tmarg = win->_tmarg;
+    new->_bmarg = win->_bmarg;
+    new->_parx = win->_parx;
+    new->_pary = win->_pary;
+    new->_parent = win->_parent;
+    new->_bkgd = win->_bkgd;
+    new->_flags = win->_flags;
+
+    return new;
+}
+
+WINDOW *resize_window(WINDOW *win, int nlines, int ncols)
+{
+    WINDOW *new;
+    int i, save_cury, save_curx, new_begy, new_begx;
+
+    PDC_LOG(("resize_window() - called: nlines %d ncols %d\n",
+             nlines, ncols));
+
+    if (!win)
+        return (WINDOW *)NULL;
+
+    if (win->_flags & _SUBPAD)
+    {
+        if ( !(new = subpad(win->_parent, nlines, ncols,
+                            win->_begy, win->_begx)) )
+            return (WINDOW *)NULL;
+    }
+    else if (win->_flags & _SUBWIN)
+    {
+        if ( !(new = subwin(win->_parent, nlines, ncols,
+                            win->_begy, win->_begx)) )
+            return (WINDOW *)NULL;
+    }
+    else
+    {
+        if (win == SP->slk_winptr)
+        {
+            new_begy = SP->lines - SP->slklines;
+            new_begx = 0;
+        }
+        else
+        {
+            new_begy = win->_begy;
+            new_begx = win->_begx;
+        }
+
+        if ( !(new = PDC_makenew(nlines, ncols, new_begy, new_begx)) )
+            return (WINDOW *)NULL;
+    }
+
+    save_curx = min(win->_curx, new->_maxx);
+    save_cury = min(win->_cury, new->_maxy);
+
+    if (!(win->_flags & (_SUBPAD|_SUBWIN)))
+    {
+        if ( !(new = PDC_makelines(new)) )
+            return (WINDOW *)NULL;
+
+        werase(new);
+
+        copywin(win, new, 0, 0, 0, 0, min(win->_maxy, new->_maxy) - 1,
+                min(win->_maxx, new->_maxx) - 1, FALSE);
+
+        for (i = 0; i < win->_maxy && win->_y[i]; i++)
+            if (win->_y[i])
+                free(win->_y[i]);
+    }
+
+    new->_flags = win->_flags;
+    new->_attrs = win->_attrs;
+    new->_clear = win->_clear;
+    new->_leaveit = win->_leaveit;
+    new->_scroll = win->_scroll;
+    new->_nodelay = win->_nodelay;
+    new->_use_keypad = win->_use_keypad;
+    new->_tmarg = (win->_tmarg > new->_maxy - 1) ? 0 : win->_tmarg;
+    new->_bmarg = (win->_bmarg == win->_maxy - 1) ?
+                  new->_maxy - 1 : min(win->_bmarg, (new->_maxy - 1));
+    new->_parent = win->_parent;
+    new->_immed = win->_immed;
+    new->_sync = win->_sync;
+    new->_bkgd = win->_bkgd;
+
+    new->_curx = save_curx;
+    new->_cury = save_cury;
+
+    free(win->_firstch);
+    free(win->_lastch);
+    free(win->_y);
+
+    *win = *new;
+    free(new);
+
+    return win;
+}
+
+int wresize(WINDOW *win, int nlines, int ncols)
+{
+    return (resize_window(win, nlines, ncols) ? OK : ERR);
+}
+
+void wsyncup(WINDOW *win)
+{
+    WINDOW *tmp;
+
+    PDC_LOG(("wsyncup() - called\n"));
+
+    for (tmp = win; tmp; tmp = tmp->_parent)
+        touchwin(tmp);
+}
+
+int syncok(WINDOW *win, bool bf)
+{
+    PDC_LOG(("syncok() - called\n"));
+
+    if (!win)
+        return ERR;
+
+    win->_sync = bf;
+
+    return OK;
+}
+
+void wcursyncup(WINDOW *win)
+{
+    WINDOW *tmp;
+
+    PDC_LOG(("wcursyncup() - called\n"));
+
+    for (tmp = win; tmp && tmp->_parent; tmp = tmp->_parent)
+        wmove(tmp->_parent, tmp->_pary + tmp->_cury, tmp->_parx + tmp->_curx);
+}
+
+void wsyncdown(WINDOW *win)
+{
+    WINDOW *tmp;
+
+    PDC_LOG(("wsyncdown() - called\n"));
+
+    for (tmp = win; tmp; tmp = tmp->_parent)
+    {
+        if (is_wintouched(tmp))
+        {
+            touchwin(win);
+            break;
+        }
+    }
+}
-- 
1.7.10.4


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH 14/20] app: add test curses
  2013-03-06  9:29 ` [PATCH 01/20] Makefile: x_flags prepare for apps support Jean-Christophe PLAGNIOL-VILLARD
                     ` (11 preceding siblings ...)
  2013-03-06  9:29   ` [PATCH 13/20] app: curses: add pdcurses Jean-Christophe PLAGNIOL-VILLARD
@ 2013-03-06  9:29   ` Jean-Christophe PLAGNIOL-VILLARD
  2013-03-06  9:29   ` [PATCH 15/20] app: pdcurses: add libmenu Jean-Christophe PLAGNIOL-VILLARD
                     ` (5 subsequent siblings)
  18 siblings, 0 replies; 31+ messages in thread
From: Jean-Christophe PLAGNIOL-VILLARD @ 2013-03-06  9:29 UTC (permalink / raw)
  To: barebox

Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
---
 apps/Kconfig              |    4 ++
 apps/Makefile             |    3 +-
 apps/test_curses/Makefile |   11 +++
 apps/test_curses/main.c   |  172 +++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 188 insertions(+), 2 deletions(-)
 create mode 100644 apps/test_curses/Makefile
 create mode 100644 apps/test_curses/main.c

diff --git a/apps/Kconfig b/apps/Kconfig
index a025955..7c0b79e 100644
--- a/apps/Kconfig
+++ b/apps/Kconfig
@@ -41,4 +41,8 @@ endmenu
 config APP_EXAMPLE
 	bool "example"
 
+config APP_TEST_CURSES
+	bool "test curses"
+	select APP_LIB_CURSES
+
 endif
diff --git a/apps/Makefile b/apps/Makefile
index cce547e..3a222d3 100644
--- a/apps/Makefile
+++ b/apps/Makefile
@@ -6,8 +6,7 @@ APP_CPPFLAGS += $(APP_CPPFLAGS-y)
 export APP_CPPFLAGS
 
 apps-$(CONFIG_APP_EXAMPLE) += example
-
-apps-$(CONFIG_APP_EXAMPLE) += example
+apps-$(CONFIG_APP_TEST_CURSES) += test_curses
 
 $(obj)/application: $(apps-lds) $(apps-y)
 
diff --git a/apps/test_curses/Makefile b/apps/test_curses/Makefile
new file mode 100644
index 0000000..94207a1
--- /dev/null
+++ b/apps/test_curses/Makefile
@@ -0,0 +1,11 @@
+targets := test_curses.map
+
+# Make sure files are removed during clean
+extra-y       += test_curses.map
+
+app-y += main.o
+app-final-y = test_curses
+
+OBJCOPYFLAGS_test_curses.app = -O binary
+LDFLAGS_apps	:= -Map $(obj)/test_curses.map
+LDFLAGS_apps	+= -static --gc-sections
diff --git a/apps/test_curses/main.c b/apps/test_curses/main.c
new file mode 100644
index 0000000..54f08f2
--- /dev/null
+++ b/apps/test_curses/main.c
@@ -0,0 +1,172 @@
+/*
+ * This file is part of the bayou project.
+ *
+ * Copyright (C) 2008 Advanced Micro Devices, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+
+#include <string.h>
+#include <stdlib.h>
+#include <curses.h>
+
+#define SCREEN_Y LINES
+#define SCREEN_X COLS
+
+#define ARRAY_SIZE(arr)                (sizeof(arr) / sizeof((arr)[0]))
+
+static int menu_width = 0;
+static int m_entries = 4;
+static unsigned int selected = 0;
+static WINDOW *menuwin, *status;
+char *i_name[] = {"test0", "test1", "test2", "test3" };
+
+char *get_name(int i)
+{
+	return i_name[i];
+}
+
+void create_menu(void)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(i_name); i++) {
+		char *name = get_name(i);
+
+		if (strlen(name) > menu_width)
+			menu_width = strlen(name);
+	}
+
+	menu_width += 4;
+
+	if (menu_width < 30)
+		menu_width = 30;
+
+	menuwin = newwin(m_entries + 3, menu_width,
+			 (SCREEN_Y - (m_entries + 3)) / 2,
+			 (SCREEN_X - menu_width) / 2);
+
+}
+
+void draw_menu(void)
+{
+	int i;
+
+	wattrset(menuwin, COLOR_PAIR(3));
+	wbkgd(menuwin, COLOR_PAIR(3));
+	wclear(menuwin);
+	wborder(menuwin, ACS_VLINE, ACS_VLINE, ACS_HLINE, ACS_HLINE,
+		ACS_ULCORNER, ACS_URCORNER, ACS_LLCORNER, ACS_LRCORNER);
+
+	wattrset(menuwin, COLOR_PAIR(4) | A_BOLD);
+	mvwprintw(menuwin, 0, (menu_width - 17) / 2, " Chooser ");
+
+	wattrset(menuwin, COLOR_PAIR(3));
+
+	for (i = 0; i < m_entries; i++) {
+		char *name = get_name(i);
+		int col = (menu_width - (2 + strlen(name))) / 2;
+
+		if (i == selected)
+			wattrset(menuwin, COLOR_PAIR(5) | A_BOLD);
+		else
+			wattrset(menuwin, COLOR_PAIR(3));
+
+		mvwprintw(menuwin, 2 + i, col, name);
+	}
+
+
+	wclear(status);
+
+	mvwprintw(status, 0, (SCREEN_X - 10) / 2, "test");
+
+	wrefresh(menuwin);
+	wrefresh(status);
+}
+
+#if 0
+#define debug(fmt, arg...) debug(fmt, ##arg)
+#else
+#define debug(fmt, arg...)
+#endif
+
+void loop(void)
+{
+	int key;
+
+	while (1) {
+		key = getch();
+
+		debug("loop key = 0x%x\n", key);
+
+		if (key == ERR)
+			continue;
+
+		debug("loop key = 0x%x\n", key);
+
+		if (key == 'q') {
+			clear();
+			refresh();
+			endwin();
+			exit(0);
+		}
+		else if (key == KEY_DOWN)
+			selected = (selected + 1) % m_entries;
+		else if (key == KEY_UP)
+			selected = (selected - 1) % m_entries;
+		else if (key == KEY_ENTER) {
+			clear();
+			refresh();
+			endwin();
+			exit(0);
+		} else
+			continue;
+
+		draw_menu();
+	}
+}
+
+int main(int argc, char **argv)
+{
+	initscr();
+
+	start_color();			/* Start color 			*/
+	clear();
+	keypad(stdscr, TRUE);
+	curs_set(0);
+
+	init_pair(1, COLOR_WHITE, COLOR_RED);
+	init_pair(2, COLOR_BLACK, COLOR_WHITE);
+	init_pair(3, COLOR_BLACK, COLOR_WHITE);
+	init_pair(4, COLOR_CYAN, COLOR_WHITE);
+	init_pair(5, COLOR_WHITE, COLOR_RED);
+
+	wattrset(stdscr, COLOR_PAIR(1));
+	wbkgd(stdscr, COLOR_PAIR(1));
+	wclear(stdscr);
+
+	status = newwin(1, SCREEN_X, SCREEN_Y - 1, 0);
+	wattrset(status, COLOR_PAIR(2));
+	wbkgd(status, COLOR_PAIR(2));
+	wclear(status);
+
+	refresh();
+
+	create_menu();
+	draw_menu();
+
+	loop();
+
+	return EXIT_SUCCESS;
+}
-- 
1.7.10.4


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH 15/20] app: pdcurses: add libmenu
  2013-03-06  9:29 ` [PATCH 01/20] Makefile: x_flags prepare for apps support Jean-Christophe PLAGNIOL-VILLARD
                     ` (12 preceding siblings ...)
  2013-03-06  9:29   ` [PATCH 14/20] app: add test curses Jean-Christophe PLAGNIOL-VILLARD
@ 2013-03-06  9:29   ` Jean-Christophe PLAGNIOL-VILLARD
  2013-03-06  9:29   ` [PATCH 16/20] app: pdcurses: add libform Jean-Christophe PLAGNIOL-VILLARD
                     ` (4 subsequent siblings)
  18 siblings, 0 replies; 31+ messages in thread
From: Jean-Christophe PLAGNIOL-VILLARD @ 2013-03-06  9:29 UTC (permalink / raw)
  To: barebox

Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
---
 apps/lib/curses/Kconfig                        |    4 +
 apps/lib/curses/pdcurses/Makefile.include      |    1 +
 apps/lib/curses/pdcurses/include/nc_alloc.h    |    4 +
 apps/lib/curses/pdcurses/include/ncurses_cfg.h |   40 ++
 apps/lib/curses/pdcurses/menu/Makefile         |   26 ++
 apps/lib/curses/pdcurses/menu/READ.ME          |   42 ++
 apps/lib/curses/pdcurses/menu/eti.h            |   54 +++
 apps/lib/curses/pdcurses/menu/m_attribs.c      |  144 ++++++
 apps/lib/curses/pdcurses/menu/m_cursor.c       |  112 +++++
 apps/lib/curses/pdcurses/menu/m_driver.c       |  556 ++++++++++++++++++++++
 apps/lib/curses/pdcurses/menu/m_format.c       |  131 ++++++
 apps/lib/curses/pdcurses/menu/m_global.c       |  598 ++++++++++++++++++++++++
 apps/lib/curses/pdcurses/menu/m_hook.c         |  151 ++++++
 apps/lib/curses/pdcurses/menu/m_item_cur.c     |  113 +++++
 apps/lib/curses/pdcurses/menu/m_item_nam.c     |   72 +++
 apps/lib/curses/pdcurses/menu/m_item_new.c     |  275 +++++++++++
 apps/lib/curses/pdcurses/menu/m_item_opt.c     |  159 +++++++
 apps/lib/curses/pdcurses/menu/m_item_top.c     |  107 +++++
 apps/lib/curses/pdcurses/menu/m_item_use.c     |   76 +++
 apps/lib/curses/pdcurses/menu/m_item_val.c     |  104 +++++
 apps/lib/curses/pdcurses/menu/m_item_vis.c     |   68 +++
 apps/lib/curses/pdcurses/menu/m_items.c        |  110 +++++
 apps/lib/curses/pdcurses/menu/m_new.c          |  142 ++++++
 apps/lib/curses/pdcurses/menu/m_opts.c         |  183 ++++++++
 apps/lib/curses/pdcurses/menu/m_pad.c          |   95 ++++
 apps/lib/curses/pdcurses/menu/m_pattern.c      |  124 +++++
 apps/lib/curses/pdcurses/menu/m_post.c         |  377 +++++++++++++++
 apps/lib/curses/pdcurses/menu/m_req_name.c     |  125 +++++
 apps/lib/curses/pdcurses/menu/m_scale.c        |   76 +++
 apps/lib/curses/pdcurses/menu/m_spacing.c      |  113 +++++
 apps/lib/curses/pdcurses/menu/m_sub.c          |  100 ++++
 apps/lib/curses/pdcurses/menu/m_trace.c        |   77 +++
 apps/lib/curses/pdcurses/menu/m_userptr.c      |   76 +++
 apps/lib/curses/pdcurses/menu/m_win.c          |  100 ++++
 apps/lib/curses/pdcurses/menu/menu.h           |  261 +++++++++++
 apps/lib/curses/pdcurses/menu/menu.priv.h      |  157 +++++++
 apps/lib/curses/pdcurses/menu/mf_common.h      |   95 ++++
 37 files changed, 5048 insertions(+)
 create mode 100644 apps/lib/curses/pdcurses/include/nc_alloc.h
 create mode 100644 apps/lib/curses/pdcurses/include/ncurses_cfg.h
 create mode 100644 apps/lib/curses/pdcurses/menu/Makefile
 create mode 100644 apps/lib/curses/pdcurses/menu/READ.ME
 create mode 100644 apps/lib/curses/pdcurses/menu/eti.h
 create mode 100644 apps/lib/curses/pdcurses/menu/m_attribs.c
 create mode 100644 apps/lib/curses/pdcurses/menu/m_cursor.c
 create mode 100644 apps/lib/curses/pdcurses/menu/m_driver.c
 create mode 100644 apps/lib/curses/pdcurses/menu/m_format.c
 create mode 100644 apps/lib/curses/pdcurses/menu/m_global.c
 create mode 100644 apps/lib/curses/pdcurses/menu/m_hook.c
 create mode 100644 apps/lib/curses/pdcurses/menu/m_item_cur.c
 create mode 100644 apps/lib/curses/pdcurses/menu/m_item_nam.c
 create mode 100644 apps/lib/curses/pdcurses/menu/m_item_new.c
 create mode 100644 apps/lib/curses/pdcurses/menu/m_item_opt.c
 create mode 100644 apps/lib/curses/pdcurses/menu/m_item_top.c
 create mode 100644 apps/lib/curses/pdcurses/menu/m_item_use.c
 create mode 100644 apps/lib/curses/pdcurses/menu/m_item_val.c
 create mode 100644 apps/lib/curses/pdcurses/menu/m_item_vis.c
 create mode 100644 apps/lib/curses/pdcurses/menu/m_items.c
 create mode 100644 apps/lib/curses/pdcurses/menu/m_new.c
 create mode 100644 apps/lib/curses/pdcurses/menu/m_opts.c
 create mode 100644 apps/lib/curses/pdcurses/menu/m_pad.c
 create mode 100644 apps/lib/curses/pdcurses/menu/m_pattern.c
 create mode 100644 apps/lib/curses/pdcurses/menu/m_post.c
 create mode 100644 apps/lib/curses/pdcurses/menu/m_req_name.c
 create mode 100644 apps/lib/curses/pdcurses/menu/m_scale.c
 create mode 100644 apps/lib/curses/pdcurses/menu/m_spacing.c
 create mode 100644 apps/lib/curses/pdcurses/menu/m_sub.c
 create mode 100644 apps/lib/curses/pdcurses/menu/m_trace.c
 create mode 100644 apps/lib/curses/pdcurses/menu/m_userptr.c
 create mode 100644 apps/lib/curses/pdcurses/menu/m_win.c
 create mode 100644 apps/lib/curses/pdcurses/menu/menu.h
 create mode 100644 apps/lib/curses/pdcurses/menu/menu.priv.h
 create mode 100644 apps/lib/curses/pdcurses/menu/mf_common.h

diff --git a/apps/lib/curses/Kconfig b/apps/lib/curses/Kconfig
index 7852afb..5950385 100644
--- a/apps/lib/curses/Kconfig
+++ b/apps/lib/curses/Kconfig
@@ -18,4 +18,8 @@ config APP_LIB_PANEL
 	bool "panel"
 	depends on APP_LIB_PDCURSES
 
+config APP_LIB_MENU
+	bool "menu"
+	depends on APP_LIB_PDCURSES
+
 endif
diff --git a/apps/lib/curses/pdcurses/Makefile.include b/apps/lib/curses/pdcurses/Makefile.include
index 822f12f..7a0061e 100644
--- a/apps/lib/curses/pdcurses/Makefile.include
+++ b/apps/lib/curses/pdcurses/Makefile.include
@@ -1 +1,2 @@
 APP_CPPFLAGS-y += -I$(srctree)/apps/lib/curses/pdcurses/include/ -D_LP64=0
+APP_CPPFLAGS-$(CONFIG_APP_LIB_MENU) += -I$(srctree)/apps/lib/curses/pdcurses/menu
diff --git a/apps/lib/curses/pdcurses/include/nc_alloc.h b/apps/lib/curses/pdcurses/include/nc_alloc.h
new file mode 100644
index 0000000..95d41f9
--- /dev/null
+++ b/apps/lib/curses/pdcurses/include/nc_alloc.h
@@ -0,0 +1,4 @@
+#define typeMalloc(type,elts) (type *)malloc((elts)*sizeof(type))
+#define typeCalloc(type,elts) (type *)calloc((elts),sizeof(type))
+#define typeRealloc(type,elts,ptr) (type *)_nc_doalloc(ptr, (elts)*sizeof(type))
+
diff --git a/apps/lib/curses/pdcurses/include/ncurses_cfg.h b/apps/lib/curses/pdcurses/include/ncurses_cfg.h
new file mode 100644
index 0000000..c6184be
--- /dev/null
+++ b/apps/lib/curses/pdcurses/include/ncurses_cfg.h
@@ -0,0 +1,40 @@
+#define USE_RCS_IDS 0
+#define USE_WIDEC_SUPPORT 0
+#define NCURSES_SP_FUNCS 0
+#define DECL_ERRNO 0
+#define NCURSES_INTEROP_FUNCS 0
+
+#define NCURSES_API
+#define NCURSES_IMPEXP
+#define NCURSES_INLINE
+#define NCURSES_SP_DCLx
+#define NCURSES_SP_NAME(x) x
+#define NCURSES_EXPORT_VAR(x) x
+#define NCURSES_EXPORT(x) x
+
+#define SP_PARM SP
+#define CURRENT_SCREEN SP
+#define StdScreen(x) stdscr
+
+#define T(x)
+#define T_CALLED(x...)
+
+#define GCC_UNUSED __attribute__((unused))
+
+#define BLANK           (' '|A_NORMAL)
+#define ZEROS           ('\0'|A_NORMAL)
+#define ISBLANK	isblank
+
+#define ChCharOf(c)	((c) & (chtype)A_CHARTEXT)
+#define CharOf(c)	ChCharOf(c)
+
+#define WINDOW_ATTRS(x) ((x)->_attrs)
+#define IsValidScreen(x) 1
+
+#define returnCode return
+#define returnWin return
+#define returnCPtr return
+#define returnVoidPtr return
+#define returnPtr return
+#define returnAttr return
+#define returnBool return
diff --git a/apps/lib/curses/pdcurses/menu/Makefile b/apps/lib/curses/pdcurses/menu/Makefile
new file mode 100644
index 0000000..f45f385
--- /dev/null
+++ b/apps/lib/curses/pdcurses/menu/Makefile
@@ -0,0 +1,26 @@
+app-y += m_req_name.o
+app-y += m_item_nam.o
+app-y += m_pad.o
+app-y += m_cursor.o
+app-y += m_item_new.o
+app-y += m_attribs.o
+app-y += m_item_opt.o
+app-y += m_format.o
+app-y += m_post.o
+app-y += m_userptr.o
+app-y += m_item_cur.o
+app-y += m_driver.o
+app-y += m_sub.o
+app-y += m_win.o
+app-y += m_global.o
+app-y += m_item_vis.o
+app-y += m_new.o
+app-y += m_scale.o
+app-y += m_spacing.o
+app-y += m_opts.o
+app-y += m_pattern.o
+app-y += m_item_val.o
+app-y += m_hook.o
+app-y += m_item_use.o
+app-y += m_items.o
+app-y += m_item_top.o
diff --git a/apps/lib/curses/pdcurses/menu/READ.ME b/apps/lib/curses/pdcurses/menu/READ.ME
new file mode 100644
index 0000000..10ff5b0
--- /dev/null
+++ b/apps/lib/curses/pdcurses/menu/READ.ME
@@ -0,0 +1,42 @@
+-------------------------------------------------------------------------------
+-- Copyright (c) 1998-2003,2006 Free Software Foundation, Inc.               --
+--                                                                           --
+-- 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, distribute with modifications, sublicense, and/or sell copies --
+-- of the Software, and to permit persons to whom the Software is furnished  --
+-- to do so, subject to the following conditions:                            --
+--                                                                           --
+-- The above copyright notice and this permission notice shall be included   --
+-- in all copies or substantial portions of the Software.                    --
+--                                                                           --
+-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS   --
+-- OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF                --
+-- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN --
+-- NO EVENT SHALL THE ABOVE 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.                                    --
+--                                                                           --
+-- Except as contained in this notice, the name(s) of the above copyright    --
+-- holders shall not be used in advertising or otherwise to promote the      --
+-- sale, use or other dealings in this Software without prior written        --
+-- authorization.                                                            --
+-------------------------------------------------------------------------------
+-- $Id: READ.ME,v 1.9 2006/04/22 23:13:05 tom Exp $
+-------------------------------------------------------------------------------
+
+This is a clone of the menu library that is available with typical
+System V curses implementations (ETI).
+
+It is modelled after the documentation that comes for this library with
+a 386 based SVR4 implementation (ESIX).
+
+The development environment was and is an ELF based Linux system.
+
+For things that still need doing, see the TO-DO file in the top-level 
+directory.
+
+Juergen Pfeifer
diff --git a/apps/lib/curses/pdcurses/menu/eti.h b/apps/lib/curses/pdcurses/menu/eti.h
new file mode 100644
index 0000000..baa6190
--- /dev/null
+++ b/apps/lib/curses/pdcurses/menu/eti.h
@@ -0,0 +1,54 @@
+/****************************************************************************
+ * Copyright (c) 1998-2002,2003 Free Software Foundation, Inc.              *
+ *                                                                          *
+ * 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, distribute with modifications, sublicense, and/or sell       *
+ * copies of the Software, and to permit persons to whom the Software is    *
+ * furnished to do so, subject to the following conditions:                 *
+ *                                                                          *
+ * The above copyright notice and this permission notice shall be included  *
+ * in all copies or substantial portions of the Software.                   *
+ *                                                                          *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
+ * IN NO EVENT SHALL THE ABOVE 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.                               *
+ *                                                                          *
+ * Except as contained in this notice, the name(s) of the above copyright   *
+ * holders shall not be used in advertising or otherwise to promote the     *
+ * sale, use or other dealings in this Software without prior written       *
+ * authorization.                                                           *
+ ****************************************************************************/
+
+/****************************************************************************
+ *   Author:  Juergen Pfeifer, 1995,1997                                    *
+ ****************************************************************************/
+
+/* $Id: eti.h,v 1.8 2003/10/25 15:24:29 tom Exp $ */
+
+#ifndef NCURSES_ETI_H_incl
+#define NCURSES_ETI_H_incl 1
+
+#define	E_OK			(0)
+#define	E_SYSTEM_ERROR	 	(-1)
+#define	E_BAD_ARGUMENT	 	(-2)
+#define	E_POSTED	 	(-3)
+#define	E_CONNECTED	 	(-4)
+#define	E_BAD_STATE	 	(-5)
+#define	E_NO_ROOM	 	(-6)
+#define	E_NOT_POSTED		(-7)
+#define	E_UNKNOWN_COMMAND	(-8)
+#define	E_NO_MATCH		(-9)
+#define	E_NOT_SELECTABLE	(-10)
+#define	E_NOT_CONNECTED	        (-11)
+#define	E_REQUEST_DENIED	(-12)
+#define	E_INVALID_FIELD	        (-13)
+#define	E_CURRENT		(-14)
+
+#endif
diff --git a/apps/lib/curses/pdcurses/menu/m_attribs.c b/apps/lib/curses/pdcurses/menu/m_attribs.c
new file mode 100644
index 0000000..1ea5c7a
--- /dev/null
+++ b/apps/lib/curses/pdcurses/menu/m_attribs.c
@@ -0,0 +1,144 @@
+/****************************************************************************
+ * Copyright (c) 1998-2004,2010 Free Software Foundation, Inc.              *
+ *                                                                          *
+ * 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, distribute with modifications, sublicense, and/or sell       *
+ * copies of the Software, and to permit persons to whom the Software is    *
+ * furnished to do so, subject to the following conditions:                 *
+ *                                                                          *
+ * The above copyright notice and this permission notice shall be included  *
+ * in all copies or substantial portions of the Software.                   *
+ *                                                                          *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
+ * IN NO EVENT SHALL THE ABOVE 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.                               *
+ *                                                                          *
+ * Except as contained in this notice, the name(s) of the above copyright   *
+ * holders shall not be used in advertising or otherwise to promote the     *
+ * sale, use or other dealings in this Software without prior written       *
+ * authorization.                                                           *
+ ****************************************************************************/
+
+/****************************************************************************
+ *   Author:  Juergen Pfeifer, 1995,1997                                    *
+ ****************************************************************************/
+
+/***************************************************************************
+* Module m_attribs                                                         *
+* Control menus display attributes                                         *
+***************************************************************************/
+
+#include "menu.priv.h"
+
+MODULE_ID("$Id: m_attribs.c,v 1.16 2010/01/23 21:16:54 tom Exp $")
+
+/* Macro to redraw menu if it is posted and changed */
+#define Refresh_Menu(menu) \
+   if ( (menu) && ((menu)->status & _POSTED) )\
+   {\
+      _nc_Draw_Menu( menu );\
+      _nc_Show_Menu( menu );\
+   }
+
+/* "Template" macro to generate a function to set a menus attribute */
+#define GEN_MENU_ATTR_SET_FCT( name ) \
+NCURSES_IMPEXP int NCURSES_API set_menu_ ## name (MENU* menu, chtype attr) \
+{\
+  T((T_CALLED("set_menu_" #name "(%p,%s)"), menu, _traceattr(attr))); \
+   if (!(attr==A_NORMAL || (attr & A_ATTRIBUTES)==attr))\
+      RETURN(E_BAD_ARGUMENT);\
+   if (menu && ( menu -> name != attr))\
+     {\
+       (menu -> name) = attr;\
+       Refresh_Menu(menu);\
+     }\
+   Normalize_Menu( menu ) -> name = attr;\
+   RETURN(E_OK);\
+}
+
+/* "Template" macro to generate a function to get a menu's attribute */
+#define GEN_MENU_ATTR_GET_FCT( name ) \
+NCURSES_IMPEXP chtype NCURSES_API menu_ ## name (const MENU * menu)\
+{\
+   T((T_CALLED("menu_" #name "(%p)"), (const void *) menu));\
+   returnAttr(Normalize_Menu( menu ) -> name);\
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnmenu
+|   Function      :  int set_menu_fore(MENU *menu, chtype attr)
+|
+|   Description   :  Set the attribute for selectable items. In single-
+|                    valued menus this is used to highlight the current
+|                    item ((i.e. where the cursor is), in multi-valued
+|                    menus this is used to highlight the selected items.
+|
+|   Return Values :  E_OK              - success
+|                    E_BAD_ARGUMENT    - an invalid value has been passed
++--------------------------------------------------------------------------*/
+GEN_MENU_ATTR_SET_FCT(fore)
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnmenu
+|   Function      :  chtype menu_fore(const MENU* menu)
+|
+|   Description   :  Return the attribute used for selectable items that
+|                    are current (single-valued menu) or selected (multi-
+|                    valued menu).
+|
+|   Return Values :  Attribute value
++--------------------------------------------------------------------------*/
+GEN_MENU_ATTR_GET_FCT(fore)
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnmenu
+|   Function      :  int set_menu_back(MENU *menu, chtype attr)
+|
+|   Description   :  Set the attribute for selectable but not yet selected
+|                    items.
+|
+|   Return Values :  E_OK             - success
+|                    E_BAD_ARGUMENT   - an invalid value has been passed
++--------------------------------------------------------------------------*/
+GEN_MENU_ATTR_SET_FCT(back)
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnmenu
+|   Function      :  chtype menu_back(const MENU *menu)
+|
+|   Description   :  Return the attribute used for selectable but not yet
+|                    selected items.
+|
+|   Return Values :  Attribute value
++--------------------------------------------------------------------------*/
+GEN_MENU_ATTR_GET_FCT(back)
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnmenu
+|   Function      :  int set_menu_grey(MENU *menu, chtype attr)
+|
+|   Description   :  Set the attribute for unselectable items.
+|
+|   Return Values :  E_OK             - success
+|                    E_BAD_ARGUMENT   - an invalid value has been passed
++--------------------------------------------------------------------------*/
+GEN_MENU_ATTR_SET_FCT(grey)
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnmenu
+|   Function      :  chtype menu_grey(const MENU *menu)
+|
+|   Description   :  Return the attribute used for non-selectable items
+|
+|   Return Values :  Attribute value
++--------------------------------------------------------------------------*/
+GEN_MENU_ATTR_GET_FCT(grey)
+
+/* m_attribs.c ends here */
diff --git a/apps/lib/curses/pdcurses/menu/m_cursor.c b/apps/lib/curses/pdcurses/menu/m_cursor.c
new file mode 100644
index 0000000..9891de4
--- /dev/null
+++ b/apps/lib/curses/pdcurses/menu/m_cursor.c
@@ -0,0 +1,112 @@
+/****************************************************************************
+ * Copyright (c) 1998-2009,2010 Free Software Foundation, Inc.              *
+ *                                                                          *
+ * 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, distribute with modifications, sublicense, and/or sell       *
+ * copies of the Software, and to permit persons to whom the Software is    *
+ * furnished to do so, subject to the following conditions:                 *
+ *                                                                          *
+ * The above copyright notice and this permission notice shall be included  *
+ * in all copies or substantial portions of the Software.                   *
+ *                                                                          *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
+ * IN NO EVENT SHALL THE ABOVE 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.                               *
+ *                                                                          *
+ * Except as contained in this notice, the name(s) of the above copyright   *
+ * holders shall not be used in advertising or otherwise to promote the     *
+ * sale, use or other dealings in this Software without prior written       *
+ * authorization.                                                           *
+ ****************************************************************************/
+
+/****************************************************************************
+ *   Author:  Juergen Pfeifer, 1995,1997                                    *
+ ****************************************************************************/
+
+/***************************************************************************
+* Module m_cursor                                                          *
+* Correctly position a menu's cursor                                       *
+***************************************************************************/
+
+#include "menu.priv.h"
+
+MODULE_ID("$Id: m_cursor.c,v 1.22 2010/01/23 21:20:10 tom Exp $")
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnmenu
+|   Function      :  _nc_menu_cursor_pos
+|
+|   Description   :  Return position of logical cursor to current item
+|
+|   Return Values :  E_OK            - success
+|                    E_BAD_ARGUMENT  - invalid menu
+|                    E_NOT_POSTED    - Menu is not posted
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(int)
+_nc_menu_cursor_pos(const MENU * menu, const ITEM * item, int *pY, int *pX)
+{
+  if (!menu || !pX || !pY)
+    return (E_BAD_ARGUMENT);
+  else
+    {
+      if ((ITEM *) 0 == item)
+	item = menu->curitem;
+      assert(item != (ITEM *) 0);
+
+      if (!(menu->status & _POSTED))
+	return (E_NOT_POSTED);
+
+      *pX = item->x * (menu->spc_cols + menu->itemlen);
+      *pY = (item->y - menu->toprow) * menu->spc_rows;
+    }
+  return (E_OK);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnmenu
+|   Function      :  pos_menu_cursor
+|
+|   Description   :  Position logical cursor to current item in menu
+|
+|   Return Values :  E_OK            - success
+|                    E_BAD_ARGUMENT  - invalid menu
+|                    E_NOT_POSTED    - Menu is not posted
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(int)
+pos_menu_cursor(const MENU * menu)
+{
+  WINDOW *win, *sub;
+  int x = 0, y = 0;
+  int err = _nc_menu_cursor_pos(menu, (ITEM *) 0, &y, &x);
+
+  T((T_CALLED("pos_menu_cursor(%p)"), (const void *)menu));
+
+  if (E_OK == err)
+    {
+      win = Get_Menu_UserWin(menu);
+      sub = menu->usersub ? menu->usersub : win;
+      assert(win && sub);
+
+      if ((menu->opt & O_SHOWMATCH) && (menu->pindex > 0))
+	x += (menu->pindex + menu->marklen - 1);
+
+      wmove(sub, y, x);
+
+      if (win != sub)
+	{
+	  wcursyncup(sub);
+	  wsyncup(sub);
+	  untouchwin(sub);
+	}
+    }
+  RETURN(err);
+}
+
+/* m_cursor.c ends here */
diff --git a/apps/lib/curses/pdcurses/menu/m_driver.c b/apps/lib/curses/pdcurses/menu/m_driver.c
new file mode 100644
index 0000000..deeff47
--- /dev/null
+++ b/apps/lib/curses/pdcurses/menu/m_driver.c
@@ -0,0 +1,556 @@
+/****************************************************************************
+ * Copyright (c) 1998-2009,2010 Free Software Foundation, Inc.              *
+ *                                                                          *
+ * 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, distribute with modifications, sublicense, and/or sell       *
+ * copies of the Software, and to permit persons to whom the Software is    *
+ * furnished to do so, subject to the following conditions:                 *
+ *                                                                          *
+ * The above copyright notice and this permission notice shall be included  *
+ * in all copies or substantial portions of the Software.                   *
+ *                                                                          *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
+ * IN NO EVENT SHALL THE ABOVE 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.                               *
+ *                                                                          *
+ * Except as contained in this notice, the name(s) of the above copyright   *
+ * holders shall not be used in advertising or otherwise to promote the     *
+ * sale, use or other dealings in this Software without prior written       *
+ * authorization.                                                           *
+ ****************************************************************************/
+
+/****************************************************************************
+ *   Author:  Juergen Pfeifer, 1995,1997                                    *
+ ****************************************************************************/
+
+/***************************************************************************
+* Module m_driver                                                          *
+* Central dispatching routine                                              *
+***************************************************************************/
+
+#include "menu.priv.h"
+
+MODULE_ID("$Id: m_driver.c,v 1.29 2010/01/23 21:20:10 tom Exp $")
+
+/* Macros */
+
+/* Remove the last character from the match pattern buffer */
+#define Remove_Character_From_Pattern(menu) \
+  (menu)->pattern[--((menu)->pindex)] = '\0'
+
+/* Add a new character to the match pattern buffer */
+#define Add_Character_To_Pattern(menu,ch) \
+  { (menu)->pattern[((menu)->pindex)++] = (ch);\
+    (menu)->pattern[(menu)->pindex] = '\0'; }
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnmenu
+|   Function      :  static bool Is_Sub_String(
+|                           bool IgnoreCaseFlag,
+|                           const char *part,
+|                           const char *string)
+|
+|   Description   :  Checks whether or not part is a substring of string.
+|
+|   Return Values :  TRUE   - if it is a substring
+|                    FALSE  - if it is not a substring
++--------------------------------------------------------------------------*/
+static bool
+Is_Sub_String(
+	       bool IgnoreCaseFlag,
+	       const char *part,
+	       const char *string
+)
+{
+  assert(part && string);
+  if (IgnoreCaseFlag)
+    {
+      while (*string && *part)
+	{
+	  if (toupper(UChar(*string++)) != toupper(UChar(*part)))
+	    break;
+	  part++;
+	}
+    }
+  else
+    {
+      while (*string && *part)
+	if (*part != *string++)
+	  break;
+      part++;
+    }
+  return ((*part) ? FALSE : TRUE);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnmenu
+|   Function      :  int _nc_Match_Next_Character_In_Item_Name(
+|                           MENU *menu,
+|                           int  ch,
+|                           ITEM **item)
+|
+|   Description   :  This internal routine is called for a menu positioned
+|                    at an item with three different classes of characters:
+|                       - a printable character; the character is added to
+|                         the current pattern and the next item matching
+|                         this pattern is searched.
+|                       - NUL; the pattern stays as it is and the next item
+|                         matching the pattern is searched
+|                       - BS; the pattern stays as it is and the previous
+|                         item matching the pattern is searched
+|
+|                       The item parameter contains on call a pointer to
+|                       the item where the search starts. On return - if
+|                       a match was found - it contains a pointer to the
+|                       matching item.
+|
+|   Return Values :  E_OK        - an item matching the pattern was found
+|                    E_NO_MATCH  - nothing found
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(int)
+_nc_Match_Next_Character_In_Item_Name
+(MENU * menu, int ch, ITEM ** item)
+{
+  bool found = FALSE, passed = FALSE;
+  int idx, last;
+
+  T((T_CALLED("_nc_Match_Next_Character(%p,%d,%p)"),
+     (void *)menu, ch, (void *)item));
+
+  assert(menu && item && *item);
+  idx = (*item)->index;
+
+  if (ch && ch != BS)
+    {
+      /* if we become to long, we need no further checking : there can't be
+         a match ! */
+      if ((menu->pindex + 1) > menu->namelen)
+	RETURN(E_NO_MATCH);
+
+      Add_Character_To_Pattern(menu, ch);
+      /* we artificially position one item back, because in the do...while
+         loop we start with the next item. This means, that with a new
+         pattern search we always start the scan with the actual item. If
+         we do a NEXT_PATTERN oder PREV_PATTERN search, we start with the
+         one after or before the actual item. */
+      if (--idx < 0)
+	idx = menu->nitems - 1;
+    }
+
+  last = idx;			/* this closes the cycle */
+
+  do
+    {
+      if (ch == BS)
+	{			/* we have to go backward */
+	  if (--idx < 0)
+	    idx = menu->nitems - 1;
+	}
+      else
+	{			/* otherwise we always go forward */
+	  if (++idx >= menu->nitems)
+	    idx = 0;
+	}
+      if (Is_Sub_String((bool)((menu->opt & O_IGNORECASE) != 0),
+			menu->pattern,
+			menu->items[idx]->name.str)
+	)
+	found = TRUE;
+      else
+	passed = TRUE;
+    }
+  while (!found && (idx != last));
+
+  if (found)
+    {
+      if (!((idx == (*item)->index) && passed))
+	{
+	  *item = menu->items[idx];
+	  RETURN(E_OK);
+	}
+      /* This point is reached, if we fully cycled through the item list
+         and the only match we found is the starting item. With a NEXT_PATTERN
+         or PREV_PATTERN scan this means, that there was no additional match.
+         If we searched with an expanded new pattern, we should never reach
+         this point, because if the expanded pattern matches also the actual
+         item we will find it in the first attempt (passed==FALSE) and we
+         will never cycle through the whole item array.
+       */
+      assert(ch == 0 || ch == BS);
+    }
+  else
+    {
+      if (ch && ch != BS && menu->pindex > 0)
+	{
+	  /* if we had no match with a new pattern, we have to restore it */
+	  Remove_Character_From_Pattern(menu);
+	}
+    }
+  RETURN(E_NO_MATCH);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnmenu
+|   Function      :  int menu_driver(MENU* menu, int c)
+|
+|   Description   :  Central dispatcher for the menu. Translates the logical
+|                    request 'c' into a menu action.
+|
+|   Return Values :  E_OK            - success
+|                    E_BAD_ARGUMENT  - invalid menu pointer
+|                    E_BAD_STATE     - menu is in user hook routine
+|                    E_NOT_POSTED    - menu is not posted
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(int)
+menu_driver(MENU * menu, int c)
+{
+#define NAVIGATE(dir) \
+  if (!item->dir)\
+     result = E_REQUEST_DENIED;\
+  else\
+     item = item->dir
+
+  int result = E_OK;
+  ITEM *item;
+  int my_top_row, rdiff;
+
+  T((T_CALLED("menu_driver(%p,%d)"), (void *)menu, c));
+
+  if (!menu)
+    RETURN(E_BAD_ARGUMENT);
+
+  if (menu->status & _IN_DRIVER)
+    RETURN(E_BAD_STATE);
+  if (!(menu->status & _POSTED))
+    RETURN(E_NOT_POSTED);
+
+  item = menu->curitem;
+
+  my_top_row = menu->toprow;
+  assert(item);
+
+  if ((c > KEY_MAX) && (c <= MAX_MENU_COMMAND))
+    {
+      if (!((c == REQ_BACK_PATTERN)
+	    || (c == REQ_NEXT_MATCH) || (c == REQ_PREV_MATCH)))
+	{
+	  assert(menu->pattern);
+	  Reset_Pattern(menu);
+	}
+
+      switch (c)
+	{
+	case REQ_LEFT_ITEM:
+	    /*=================*/
+	  NAVIGATE(left);
+	  break;
+
+	case REQ_RIGHT_ITEM:
+	    /*==================*/
+	  NAVIGATE(right);
+	  break;
+
+	case REQ_UP_ITEM:
+	    /*===============*/
+	  NAVIGATE(up);
+	  break;
+
+	case REQ_DOWN_ITEM:
+	    /*=================*/
+	  NAVIGATE(down);
+	  break;
+
+	case REQ_SCR_ULINE:
+	    /*=================*/
+	  if (my_top_row == 0 || !(item->up))
+	    result = E_REQUEST_DENIED;
+	  else
+	    {
+	      --my_top_row;
+	      item = item->up;
+	    }
+	  break;
+
+	case REQ_SCR_DLINE:
+	    /*=================*/
+	  if ((my_top_row + menu->arows >= menu->rows) || !(item->down))
+	    {
+	      /* only if the menu has less items than rows, we can deny the
+	         request. Otherwise the epilogue of this routine adjusts the
+	         top row if necessary */
+	      result = E_REQUEST_DENIED;
+	    }
+	  else
+	    {
+	      my_top_row++;
+	      item = item->down;
+	    }
+	  break;
+
+	case REQ_SCR_DPAGE:
+	    /*=================*/
+	  rdiff = menu->rows - (menu->arows + my_top_row);
+	  if (rdiff > menu->arows)
+	    rdiff = menu->arows;
+	  if (rdiff <= 0)
+	    result = E_REQUEST_DENIED;
+	  else
+	    {
+	      my_top_row += rdiff;
+	      while (rdiff-- > 0 && item != 0 && item->down != 0)
+		item = item->down;
+	    }
+	  break;
+
+	case REQ_SCR_UPAGE:
+	    /*=================*/
+	  rdiff = (menu->arows < my_top_row) ? menu->arows : my_top_row;
+	  if (rdiff <= 0)
+	    result = E_REQUEST_DENIED;
+	  else
+	    {
+	      my_top_row -= rdiff;
+	      while (rdiff-- > 0 && item != 0 && item->up != 0)
+		item = item->up;
+	    }
+	  break;
+
+	case REQ_FIRST_ITEM:
+	    /*==================*/
+	  item = menu->items[0];
+	  break;
+
+	case REQ_LAST_ITEM:
+	    /*=================*/
+	  item = menu->items[menu->nitems - 1];
+	  break;
+
+	case REQ_NEXT_ITEM:
+	    /*=================*/
+	  if ((item->index + 1) >= menu->nitems)
+	    {
+	      if (menu->opt & O_NONCYCLIC)
+		result = E_REQUEST_DENIED;
+	      else
+		item = menu->items[0];
+	    }
+	  else
+	    item = menu->items[item->index + 1];
+	  break;
+
+	case REQ_PREV_ITEM:
+	    /*=================*/
+	  if (item->index <= 0)
+	    {
+	      if (menu->opt & O_NONCYCLIC)
+		result = E_REQUEST_DENIED;
+	      else
+		item = menu->items[menu->nitems - 1];
+	    }
+	  else
+	    item = menu->items[item->index - 1];
+	  break;
+
+	case REQ_TOGGLE_ITEM:
+	    /*===================*/
+	  if (menu->opt & O_ONEVALUE)
+	    {
+	      result = E_REQUEST_DENIED;
+	    }
+	  else
+	    {
+	      if (menu->curitem->opt & O_SELECTABLE)
+		{
+		  menu->curitem->value = !menu->curitem->value;
+		  Move_And_Post_Item(menu, menu->curitem);
+		  _nc_Show_Menu(menu);
+		}
+	      else
+		result = E_NOT_SELECTABLE;
+	    }
+	  break;
+
+	case REQ_CLEAR_PATTERN:
+	    /*=====================*/
+	  /* already cleared in prologue */
+	  break;
+
+	case REQ_BACK_PATTERN:
+	    /*====================*/
+	  if (menu->pindex > 0)
+	    {
+	      assert(menu->pattern);
+	      Remove_Character_From_Pattern(menu);
+	      pos_menu_cursor(menu);
+	    }
+	  else
+	    result = E_REQUEST_DENIED;
+	  break;
+
+	case REQ_NEXT_MATCH:
+	    /*==================*/
+	  assert(menu->pattern);
+	  if (menu->pattern[0])
+	    result = _nc_Match_Next_Character_In_Item_Name(menu, 0, &item);
+	  else
+	    {
+	      if ((item->index + 1) < menu->nitems)
+		item = menu->items[item->index + 1];
+	      else
+		{
+		  if (menu->opt & O_NONCYCLIC)
+		    result = E_REQUEST_DENIED;
+		  else
+		    item = menu->items[0];
+		}
+	    }
+	  break;
+
+	case REQ_PREV_MATCH:
+	    /*==================*/
+	  assert(menu->pattern);
+	  if (menu->pattern[0])
+	    result = _nc_Match_Next_Character_In_Item_Name(menu, BS, &item);
+	  else
+	    {
+	      if (item->index)
+		item = menu->items[item->index - 1];
+	      else
+		{
+		  if (menu->opt & O_NONCYCLIC)
+		    result = E_REQUEST_DENIED;
+		  else
+		    item = menu->items[menu->nitems - 1];
+		}
+	    }
+	  break;
+
+	default:
+	    /*======*/
+	  result = E_UNKNOWN_COMMAND;
+	  break;
+	}
+    }
+  else
+    {				/* not a command */
+      if (!(c & ~((int)MAX_REGULAR_CHARACTER)) && isprint(UChar(c)))
+	result = _nc_Match_Next_Character_In_Item_Name(menu, c, &item);
+#ifdef NCURSES_MOUSE_VERSION
+      else if (KEY_MOUSE == c)
+	{
+	  MEVENT event;
+	  WINDOW *uwin = Get_Menu_UserWin(menu);
+
+	  getmouse(&event);
+	  if ((event.bstate & (BUTTON1_CLICKED |
+			       BUTTON1_DOUBLE_CLICKED |
+			       BUTTON1_TRIPLE_CLICKED))
+	      && wenclose(uwin, event.y, event.x))
+	    {			/* we react only if the click was in the userwin, that means
+				 * inside the menu display area or at the decoration window.
+				 */
+	      WINDOW *sub = Get_Menu_Window(menu);
+	      int ry = event.y, rx = event.x;	/* screen coordinates */
+
+	      result = E_REQUEST_DENIED;
+	      if (mouse_trafo(&ry, &rx, FALSE))
+		{		/* rx, ry are now "curses" coordinates */
+		  if (ry < sub->_begy)
+		    {		/* we clicked above the display region; this is
+				 * interpreted as "scroll up" request
+				 */
+		      if (event.bstate & BUTTON1_CLICKED)
+			result = menu_driver(menu, REQ_SCR_ULINE);
+		      else if (event.bstate & BUTTON1_DOUBLE_CLICKED)
+			result = menu_driver(menu, REQ_SCR_UPAGE);
+		      else if (event.bstate & BUTTON1_TRIPLE_CLICKED)
+			result = menu_driver(menu, REQ_FIRST_ITEM);
+		      RETURN(result);
+		    }
+		  else if (ry > sub->_begy + sub->_maxy)
+		    {		/* we clicked below the display region; this is
+				 * interpreted as "scroll down" request
+				 */
+		      if (event.bstate & BUTTON1_CLICKED)
+			result = menu_driver(menu, REQ_SCR_DLINE);
+		      else if (event.bstate & BUTTON1_DOUBLE_CLICKED)
+			result = menu_driver(menu, REQ_SCR_DPAGE);
+		      else if (event.bstate & BUTTON1_TRIPLE_CLICKED)
+			result = menu_driver(menu, REQ_LAST_ITEM);
+		      RETURN(result);
+		    }
+		  else if (wenclose(sub, event.y, event.x))
+		    {		/* Inside the area we try to find the hit item */
+		      int i, x, y, err;
+
+		      ry = event.y;
+		      rx = event.x;
+		      if (wmouse_trafo(sub, &ry, &rx, FALSE))
+			{
+			  for (i = 0; i < menu->nitems; i++)
+			    {
+			      err = _nc_menu_cursor_pos(menu, menu->items[i],
+							&y, &x);
+			      if (E_OK == err)
+				{
+				  if ((ry == y) &&
+				      (rx >= x) &&
+				      (rx < x + menu->itemlen))
+				    {
+				      item = menu->items[i];
+				      result = E_OK;
+				      break;
+				    }
+				}
+			    }
+			  if (E_OK == result)
+			    {	/* We found an item, now we can handle the click.
+				 * A single click just positions the menu cursor
+				 * to the clicked item. A double click toggles
+				 * the item.
+				 */
+			      if (event.bstate & BUTTON1_DOUBLE_CLICKED)
+				{
+				  _nc_New_TopRow_and_CurrentItem(menu,
+								 my_top_row,
+								 item);
+				  menu_driver(menu, REQ_TOGGLE_ITEM);
+				  result = E_UNKNOWN_COMMAND;
+				}
+			    }
+			}
+		    }
+		}
+	    }
+	  else
+	    result = E_REQUEST_DENIED;
+	}
+#endif /* NCURSES_MOUSE_VERSION */
+      else
+	result = E_UNKNOWN_COMMAND;
+    }
+
+  if (E_OK == result)
+    {
+      /* Adjust the top row if it turns out that the current item unfortunately
+         doesn't appear in the menu window */
+      if (item->y < my_top_row)
+	my_top_row = item->y;
+      else if (item->y >= (my_top_row + menu->arows))
+	my_top_row = item->y - menu->arows + 1;
+
+      _nc_New_TopRow_and_CurrentItem(menu, my_top_row, item);
+
+    }
+
+  RETURN(result);
+}
+
+/* m_driver.c ends here */
diff --git a/apps/lib/curses/pdcurses/menu/m_format.c b/apps/lib/curses/pdcurses/menu/m_format.c
new file mode 100644
index 0000000..8e68a03
--- /dev/null
+++ b/apps/lib/curses/pdcurses/menu/m_format.c
@@ -0,0 +1,131 @@
+/****************************************************************************
+ * Copyright (c) 1998-2004,2010 Free Software Foundation, Inc.              *
+ *                                                                          *
+ * 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, distribute with modifications, sublicense, and/or sell       *
+ * copies of the Software, and to permit persons to whom the Software is    *
+ * furnished to do so, subject to the following conditions:                 *
+ *                                                                          *
+ * The above copyright notice and this permission notice shall be included  *
+ * in all copies or substantial portions of the Software.                   *
+ *                                                                          *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
+ * IN NO EVENT SHALL THE ABOVE 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.                               *
+ *                                                                          *
+ * Except as contained in this notice, the name(s) of the above copyright   *
+ * holders shall not be used in advertising or otherwise to promote the     *
+ * sale, use or other dealings in this Software without prior written       *
+ * authorization.                                                           *
+ ****************************************************************************/
+
+/****************************************************************************
+ *   Author:  Juergen Pfeifer, 1995,1997                                    *
+ ****************************************************************************/
+
+/***************************************************************************
+* Module m_format                                                          *
+* Set and get maximum numbers of rows and columns in menus                 *
+***************************************************************************/
+
+#include "menu.priv.h"
+
+MODULE_ID("$Id: m_format.c,v 1.16 2010/01/23 21:20:10 tom Exp $")
+
+#define minimum(a,b) ((a)<(b) ? (a): (b))
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnmenu
+|   Function      :  int set_menu_format(MENU *menu, int rows, int cols)
+|
+|   Description   :  Sets the maximum number of rows and columns of items
+|                    that may be displayed at one time on a menu. If the
+|                    menu contains more items than can be displayed at
+|                    once, the menu will be scrollable.
+|
+|   Return Values :  E_OK                   - success
+|                    E_BAD_ARGUMENT         - invalid values passed
+|                    E_NOT_CONNECTED        - there are no items connected
+|                    E_POSTED               - the menu is already posted
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(int)
+set_menu_format(MENU * menu, int rows, int cols)
+{
+  int total_rows, total_cols;
+
+  T((T_CALLED("set_menu_format(%p,%d,%d)"), (void *)menu, rows, cols));
+
+  if (rows < 0 || cols < 0)
+    RETURN(E_BAD_ARGUMENT);
+
+  if (menu)
+    {
+      if (menu->status & _POSTED)
+	RETURN(E_POSTED);
+
+      if (!(menu->items))
+	RETURN(E_NOT_CONNECTED);
+
+      if (rows == 0)
+	rows = menu->frows;
+      if (cols == 0)
+	cols = menu->fcols;
+
+      if (menu->pattern)
+	Reset_Pattern(menu);
+
+      menu->frows = rows;
+      menu->fcols = cols;
+
+      assert(rows > 0 && cols > 0);
+      total_rows = (menu->nitems - 1) / cols + 1;
+      total_cols = (menu->opt & O_ROWMAJOR) ?
+	minimum(menu->nitems, cols) :
+	(menu->nitems - 1) / total_rows + 1;
+
+      menu->rows = total_rows;
+      menu->cols = total_cols;
+      menu->arows = minimum(total_rows, rows);
+      menu->toprow = 0;
+      menu->curitem = *(menu->items);
+      assert(menu->curitem);
+      menu->status |= _LINK_NEEDED;
+      _nc_Calculate_Item_Length_and_Width(menu);
+    }
+  else
+    {
+      if (rows > 0)
+	_nc_Default_Menu.frows = rows;
+      if (cols > 0)
+	_nc_Default_Menu.fcols = cols;
+    }
+
+  RETURN(E_OK);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnmenu
+|   Function      :  void menu_format(const MENU *menu, int *rows, int *cols)
+|
+|   Description   :  Returns the maximum number of rows and columns that may
+|                    be displayed at one time on menu.
+|
+|   Return Values :  -
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(void)
+menu_format(const MENU * menu, int *rows, int *cols)
+{
+  if (rows)
+    *rows = Normalize_Menu(menu)->frows;
+  if (cols)
+    *cols = Normalize_Menu(menu)->fcols;
+}
+
+/* m_format.c ends here */
diff --git a/apps/lib/curses/pdcurses/menu/m_global.c b/apps/lib/curses/pdcurses/menu/m_global.c
new file mode 100644
index 0000000..73227f3
--- /dev/null
+++ b/apps/lib/curses/pdcurses/menu/m_global.c
@@ -0,0 +1,598 @@
+/****************************************************************************
+ * Copyright (c) 1998-2009,2010 Free Software Foundation, Inc.              *
+ *                                                                          *
+ * 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, distribute with modifications, sublicense, and/or sell       *
+ * copies of the Software, and to permit persons to whom the Software is    *
+ * furnished to do so, subject to the following conditions:                 *
+ *                                                                          *
+ * The above copyright notice and this permission notice shall be included  *
+ * in all copies or substantial portions of the Software.                   *
+ *                                                                          *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
+ * IN NO EVENT SHALL THE ABOVE 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.                               *
+ *                                                                          *
+ * Except as contained in this notice, the name(s) of the above copyright   *
+ * holders shall not be used in advertising or otherwise to promote the     *
+ * sale, use or other dealings in this Software without prior written       *
+ * authorization.                                                           *
+ ****************************************************************************/
+
+/****************************************************************************
+ *   Author:  Juergen Pfeifer, 1995,1997                                    *
+ ****************************************************************************/
+
+/***************************************************************************
+* Module m_global                                                          *
+* Globally used internal routines and the default menu and item structures *
+***************************************************************************/
+
+#include "menu.priv.h"
+
+MODULE_ID("$Id: m_global.c,v 1.25 2010/01/23 21:20:10 tom Exp $")
+
+static char mark[] = "-";
+/* *INDENT-OFF* */
+NCURSES_EXPORT_VAR(MENU) _nc_Default_Menu = {
+  16,				  /* Nr. of chars high */
+  1,				  /* Nr. of chars wide */
+  16,				  /* Nr. of items high */
+  1,			          /* Nr. of items wide */
+  16,				  /* Nr. of formatted items high */
+  1,				  /* Nr. of formatted items wide */
+  16,				  /* Nr. of items high (actual) */
+  0,				  /* length of widest name */
+  0,				  /* length of widest description */
+  1,				  /* length of mark */
+  1,				  /* length of one item */
+  1,                              /* Spacing for descriptor */
+  1,                              /* Spacing for columns */
+  1,                              /* Spacing for rows */
+  (char *)0,			  /* buffer used to store match chars */
+  0,				  /* Index into pattern buffer */
+  (WINDOW *)0,			  /* Window containing entire menu */
+  (WINDOW *)0,			  /* Portion of menu displayed */
+  (WINDOW *)0,			  /* User's window */
+  (WINDOW *)0,			  /* User's subwindow */
+  (ITEM **)0,			  /* List of items */
+  0,				  /* Total Nr. of items in menu */
+  (ITEM *)0,			  /* Current item */
+  0,				  /* Top row of menu */
+  (chtype)A_REVERSE,		  /* Attribute for selection */
+  (chtype)A_NORMAL,		  /* Attribute for nonselection */
+  (chtype)A_UNDERLINE,		  /* Attribute for inactive */
+  ' ',  			  /* Pad character */
+  (Menu_Hook)0,			  /* Menu init */
+  (Menu_Hook)0,			  /* Menu term */
+  (Menu_Hook)0,			  /* Item init */
+  (Menu_Hook)0,			  /* Item term */
+  (void *)0,			  /* userptr */
+  mark,				  /* mark */
+  ALL_MENU_OPTS,                  /* options */
+  0			          /* status */
+};
+
+NCURSES_EXPORT_VAR(ITEM) _nc_Default_Item = {
+  { (char *)0, 0 },		  /* name */
+  { (char *)0, 0 },		  /* description */
+  (MENU *)0,		          /* Pointer to parent menu */
+  (char *)0,			  /* Userpointer */
+  ALL_ITEM_OPTS,		  /* options */
+  0,				  /* Item Nr. */
+  0,				  /* y */
+  0,				  /* x */
+  FALSE,			  /* value */
+  (ITEM *)0,		          /* left */
+  (ITEM *)0,		          /* right */
+  (ITEM *)0,		          /* up */
+  (ITEM *)0		          /* down */
+  };
+/* *INDENT-ON* */
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnmenu
+|   Function      :  static void ComputeMaximum_NameDesc_Lenths(MENU *menu)
+|
+|   Description   :  Calculates the maximum name and description lengths
+|                    of the items connected to the menu
+|
+|   Return Values :  -
++--------------------------------------------------------------------------*/
+NCURSES_INLINE static void
+ComputeMaximum_NameDesc_Lengths(MENU * menu)
+{
+  unsigned MaximumNameLength = 0;
+  unsigned MaximumDescriptionLength = 0;
+  ITEM **items;
+  unsigned check;
+
+  assert(menu && menu->items);
+  for (items = menu->items; *items; items++)
+    {
+      check = _nc_Calculate_Text_Width(&((*items)->name));
+      if (check > MaximumNameLength)
+	MaximumNameLength = check;
+
+      check = _nc_Calculate_Text_Width(&((*items)->description));
+      if (check > MaximumDescriptionLength)
+	MaximumDescriptionLength = check;
+    }
+
+  menu->namelen = MaximumNameLength;
+  menu->desclen = MaximumDescriptionLength;
+  T(("ComputeMaximum_NameDesc_Lengths %d,%d", menu->namelen, menu->desclen));
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnmenu
+|   Function      :  static void ResetConnectionInfo(MENU *, ITEM **)
+|
+|   Description   :  Reset all informations in the menu and the items in
+|                    the item array that indicates a connection
+|
+|   Return Values :  -
++--------------------------------------------------------------------------*/
+NCURSES_INLINE static void
+ResetConnectionInfo(MENU * menu, ITEM ** items)
+{
+  ITEM **item;
+
+  assert(menu && items);
+  for (item = items; *item; item++)
+    {
+      (*item)->index = 0;
+      (*item)->imenu = (MENU *) 0;
+    }
+  if (menu->pattern)
+    free(menu->pattern);
+  menu->pattern = (char *)0;
+  menu->pindex = 0;
+  menu->items = (ITEM **) 0;
+  menu->nitems = 0;
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnmenu
+|   Function      :  bool _nc_Connect_Items(MENU *menu, ITEM **items)
+|
+|   Description   :  Connect the items in the item array to the menu.
+|                    Decorate all the items with a number and a backward
+|                    pointer to the menu.
+|
+|   Return Values :  TRUE       - successful connection
+|                    FALSE      - connection failed
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(bool)
+_nc_Connect_Items(MENU * menu, ITEM ** items)
+{
+  ITEM **item;
+  unsigned int ItemCount = 0;
+
+  if (menu && items)
+    {
+      for (item = items; *item; item++)
+	{
+	  if ((*item)->imenu)
+	    {
+	      /* if a item is already connected, reject connection */
+	      break;
+	    }
+	}
+      if (!(*item))
+	/* we reached the end, so there was no connected item */
+	{
+	  for (item = items; *item; item++)
+	    {
+	      if (menu->opt & O_ONEVALUE)
+		{
+		  (*item)->value = FALSE;
+		}
+	      (*item)->index = ItemCount++;
+	      (*item)->imenu = menu;
+	    }
+	}
+    }
+  else
+    return (FALSE);
+
+  if (ItemCount != 0)
+    {
+      menu->items = items;
+      menu->nitems = ItemCount;
+      ComputeMaximum_NameDesc_Lengths(menu);
+      if ((menu->pattern = typeMalloc(char, (unsigned)(1 + menu->namelen))))
+	{
+	  Reset_Pattern(menu);
+	  set_menu_format(menu, menu->frows, menu->fcols);
+	  menu->curitem = *items;
+	  menu->toprow = 0;
+	  return (TRUE);
+	}
+    }
+
+  /* If we fall through to this point, we have to reset all items connection
+     and inform about a reject connection */
+  ResetConnectionInfo(menu, items);
+  return (FALSE);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnmenu
+|   Function      :  void _nc_Disconnect_Items(MENU *menu)
+|
+|   Description   :  Disconnect the menus item array from the menu
+|
+|   Return Values :  -
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(void)
+_nc_Disconnect_Items(MENU * menu)
+{
+  if (menu && menu->items)
+    ResetConnectionInfo(menu, menu->items);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnmenu
+|   Function      :  int _nc_Calculate_Text_Width(const TEXT * item)
+|
+|   Description   :  Calculate the number of columns for a TEXT.
+|
+|   Return Values :  the width
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(int)
+_nc_Calculate_Text_Width(const TEXT * item /*FIXME: limit length */ )
+{
+#if USE_WIDEC_SUPPORT
+  int result = item->length;
+
+  T((T_CALLED("_nc_menu_text_width(%p)"), (const void *)item));
+  if (result != 0 && item->str != 0)
+    {
+      int count = mbstowcs(0, item->str, 0);
+      wchar_t *temp = 0;
+
+      if (count > 0
+	  && (temp = typeMalloc(wchar_t, 2 + count)) != 0)
+	{
+	  int n;
+
+	  result = 0;
+	  mbstowcs(temp, item->str, (unsigned)count);
+	  for (n = 0; n < count; ++n)
+	    {
+	      int test = wcwidth(temp[n]);
+
+	      if (test <= 0)
+		test = 1;
+	      result += test;
+	    }
+	  free(temp);
+	}
+    }
+  returnCode(result);
+#else
+  return item->length;
+#endif
+}
+
+/*
+ * Calculate the actual width of a menu entry for wide-characters.
+ */
+#if USE_WIDEC_SUPPORT
+static int
+calculate_actual_width(MENU * menu, bool name)
+{
+  int width = 0;
+  int check = 0;
+  ITEM **items;
+
+  assert(menu && menu->items);
+
+  if (menu->items != 0)
+    {
+      for (items = menu->items; *items; items++)
+	{
+	  if (name)
+	    {
+	      check = _nc_Calculate_Text_Width(&((*items)->name));
+	    }
+	  else
+	    {
+	      check = _nc_Calculate_Text_Width(&((*items)->description));
+	    }
+	  if (check > width)
+	    width = check;
+	}
+    }
+  else
+    {
+      width = (name ? menu->namelen : menu->desclen);
+    }
+
+  T(("calculate_actual_width %s = %d/%d",
+     name ? "name" : "desc",
+     width,
+     name ? menu->namelen : menu->desclen));
+  return width;
+}
+#else
+#define calculate_actual_width(menu, name) (name ? menu->namelen : menu->desclen)
+#endif
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnmenu
+|   Function      :  void _nc_Calculate_Item_Length_and_Width(MENU *menu)
+|
+|   Description   :  Calculate the length of an item and the width of the
+|                    whole menu.
+|
+|   Return Values :  -
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(void)
+_nc_Calculate_Item_Length_and_Width(MENU * menu)
+{
+  int l;
+
+  assert(menu);
+
+  menu->height = 1 + menu->spc_rows * (menu->arows - 1);
+
+  l = calculate_actual_width(menu, TRUE);
+  l += menu->marklen;
+
+  if ((menu->opt & O_SHOWDESC) && (menu->desclen > 0))
+    {
+      l += calculate_actual_width(menu, FALSE);
+      l += menu->spc_desc;
+    }
+
+  menu->itemlen = l;
+  l *= menu->cols;
+  l += (menu->cols - 1) * menu->spc_cols;	/* for the padding between the columns */
+  menu->width = l;
+
+  T(("_nc_CalculateItem_Length_and_Width columns %d, item %d, width %d",
+     menu->cols,
+     menu->itemlen,
+     menu->width));
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnmenu
+|   Function      :  void _nc_Link_Item(MENU *menu)
+|
+|   Description   :  Statically calculate for every item its four neighbors.
+|                    This depends on the orientation of the menu. This
+|                    static approach simplifies navigation in the menu a lot.
+|
+|   Return Values :  -
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(void)
+_nc_Link_Items(MENU * menu)
+{
+  if (menu && menu->items && *(menu->items))
+    {
+      int i, j;
+      ITEM *item;
+      int Number_Of_Items = menu->nitems;
+      int col = 0, row = 0;
+      int Last_in_Row;
+      int Last_in_Column;
+      bool cycle = (menu->opt & O_NONCYCLIC) ? FALSE : TRUE;
+
+      menu->status &= ~_LINK_NEEDED;
+
+      if (menu->opt & O_ROWMAJOR)
+	{
+	  int Number_Of_Columns = menu->cols;
+
+	  for (i = 0; i < Number_Of_Items; i++)
+	    {
+	      item = menu->items[i];
+
+	      Last_in_Row = row * Number_Of_Columns + (Number_Of_Columns - 1);
+
+	      item->left = (col) ?
+	      /* if we are not in the leftmost column, we can use the
+	         predecessor in the items array */
+		menu->items[i - 1] :
+		(cycle ? menu->items[(Last_in_Row >= Number_Of_Items) ?
+				     Number_Of_Items - 1 :
+				     Last_in_Row] :
+		 (ITEM *) 0);
+
+	      item->right = ((col < (Number_Of_Columns - 1)) &&
+			     ((i + 1) < Number_Of_Items)
+		)?
+		menu->items[i + 1] :
+		(cycle ? menu->items[row * Number_Of_Columns] :
+		 (ITEM *) 0
+		);
+
+	      Last_in_Column = (menu->rows - 1) * Number_Of_Columns + col;
+
+	      item->up = (row) ? menu->items[i - Number_Of_Columns] :
+		(cycle ? menu->items[(Last_in_Column >= Number_Of_Items) ?
+				     Number_Of_Items - 1 :
+				     Last_in_Column] :
+		 (ITEM *) 0);
+
+	      item->down = ((i + Number_Of_Columns) < Number_Of_Items)
+		?
+		menu->items[i + Number_Of_Columns] :
+		(cycle ? menu->items[(row + 1) < menu->rows ?
+				     Number_Of_Items - 1 : col] :
+		 (ITEM *) 0);
+	      item->x = col;
+	      item->y = row;
+	      if (++col == Number_Of_Columns)
+		{
+		  row++;
+		  col = 0;
+		}
+	    }
+	}
+      else
+	{
+	  int Number_Of_Rows = menu->rows;
+
+	  for (j = 0; j < Number_Of_Items; j++)
+	    {
+	      item = menu->items[i = (col * Number_Of_Rows + row)];
+
+	      Last_in_Column = (menu->cols - 1) * Number_Of_Rows + row;
+
+	      item->left = (col) ?
+		menu->items[i - Number_Of_Rows] :
+		(cycle ? (Last_in_Column >= Number_Of_Items) ?
+		 menu->items[Last_in_Column - Number_Of_Rows] :
+		 menu->items[Last_in_Column] :
+		 (ITEM *) 0);
+
+	      item->right = ((i + Number_Of_Rows) < Number_Of_Items)
+		?
+		menu->items[i + Number_Of_Rows] :
+		(cycle ? menu->items[row] : (ITEM *) 0);
+
+	      Last_in_Row = col * Number_Of_Rows + (Number_Of_Rows - 1);
+
+	      item->up = (row) ?
+		menu->items[i - 1] :
+		(cycle ?
+		 menu->items[(Last_in_Row >= Number_Of_Items) ?
+			     Number_Of_Items - 1 :
+			     Last_in_Row] :
+		 (ITEM *) 0);
+
+	      item->down = (row < (Number_Of_Rows - 1))
+		?
+		(menu->items[((i + 1) < Number_Of_Items) ?
+			     i + 1 :
+			     (col - 1) * Number_Of_Rows + row + 1]) :
+		(cycle ?
+		 menu->items[col * Number_Of_Rows] :
+		 (ITEM *) 0
+		);
+
+	      item->x = col;
+	      item->y = row;
+	      if ((++row) == Number_Of_Rows)
+		{
+		  col++;
+		  row = 0;
+		}
+	    }
+	}
+    }
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnmenu
+|   Function      :  void _nc_Show_Menu(const MENU* menu)
+|
+|   Description   :  Update the window that is associated with the menu
+|
+|   Return Values :  -
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(void)
+_nc_Show_Menu(const MENU * menu)
+{
+  WINDOW *win;
+  int maxy, maxx;
+
+  assert(menu);
+  if ((menu->status & _POSTED) && !(menu->status & _IN_DRIVER))
+    {
+      /* adjust the internal subwindow to start on the current top */
+      assert(menu->sub);
+      mvderwin(menu->sub, menu->spc_rows * menu->toprow, 0);
+      win = Get_Menu_Window(menu);
+
+      maxy = getmaxy(win);
+      maxx = getmaxx(win);
+
+      if (menu->height < maxy)
+	maxy = menu->height;
+      if (menu->width < maxx)
+	maxx = menu->width;
+
+      copywin(menu->sub, win, 0, 0, 0, 0, maxy - 1, maxx - 1, 0);
+      pos_menu_cursor(menu);
+    }
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnmenu
+|   Function      :  void _nc_New_TopRow_and_CurrentItem(
+|                            MENU *menu,
+|                            int new_toprow,
+|                            ITEM *new_current_item)
+|
+|   Description   :  Redisplay the menu so that the given row becomes the
+|                    top row and the given item becomes the new current
+|                    item.
+|
+|   Return Values :  -
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(void)
+_nc_New_TopRow_and_CurrentItem(
+				MENU * menu,
+				int new_toprow,
+				ITEM * new_current_item)
+{
+  ITEM *cur_item;
+  bool mterm_called = FALSE;
+  bool iterm_called = FALSE;
+
+  assert(menu);
+  if (menu->status & _POSTED)
+    {
+      if (new_current_item != menu->curitem)
+	{
+	  Call_Hook(menu, itemterm);
+	  iterm_called = TRUE;
+	}
+      if (new_toprow != menu->toprow)
+	{
+	  Call_Hook(menu, menuterm);
+	  mterm_called = TRUE;
+	}
+
+      cur_item = menu->curitem;
+      assert(cur_item);
+      menu->toprow = new_toprow;
+      menu->curitem = new_current_item;
+
+      if (mterm_called)
+	{
+	  Call_Hook(menu, menuinit);
+	}
+      if (iterm_called)
+	{
+	  /* this means, move from the old current_item to the new one... */
+	  Move_To_Current_Item(menu, cur_item);
+	  Call_Hook(menu, iteminit);
+	}
+      if (mterm_called || iterm_called)
+	{
+	  _nc_Show_Menu(menu);
+	}
+      else
+	pos_menu_cursor(menu);
+    }
+  else
+    {				/* if we are not posted, this is quite simple */
+      menu->toprow = new_toprow;
+      menu->curitem = new_current_item;
+    }
+}
+
+/* m_global.c ends here */
diff --git a/apps/lib/curses/pdcurses/menu/m_hook.c b/apps/lib/curses/pdcurses/menu/m_hook.c
new file mode 100644
index 0000000..df78d0a
--- /dev/null
+++ b/apps/lib/curses/pdcurses/menu/m_hook.c
@@ -0,0 +1,151 @@
+/****************************************************************************
+ * Copyright (c) 1998-2004,2010 Free Software Foundation, Inc.              *
+ *                                                                          *
+ * 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, distribute with modifications, sublicense, and/or sell       *
+ * copies of the Software, and to permit persons to whom the Software is    *
+ * furnished to do so, subject to the following conditions:                 *
+ *                                                                          *
+ * The above copyright notice and this permission notice shall be included  *
+ * in all copies or substantial portions of the Software.                   *
+ *                                                                          *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
+ * IN NO EVENT SHALL THE ABOVE 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.                               *
+ *                                                                          *
+ * Except as contained in this notice, the name(s) of the above copyright   *
+ * holders shall not be used in advertising or otherwise to promote the     *
+ * sale, use or other dealings in this Software without prior written       *
+ * authorization.                                                           *
+ ****************************************************************************/
+
+/****************************************************************************
+ *   Author:  Juergen Pfeifer, 1995,1997                                    *
+ ****************************************************************************/
+
+/***************************************************************************
+* Module m_hook                                                            *
+* Assign application specific routines for automatic invocation by menus   *
+***************************************************************************/
+
+#include "menu.priv.h"
+
+MODULE_ID("$Id: m_hook.c,v 1.15 2010/01/23 21:16:54 tom Exp $")
+
+/* "Template" macro to generate function to set application specific hook */
+#define GEN_HOOK_SET_FUNCTION( typ, name ) \
+NCURSES_IMPEXP int NCURSES_API set_ ## typ ## _ ## name (MENU *menu, Menu_Hook func )\
+{\
+   T((T_CALLED("set_" #typ "_" #name "(%p,%p)"), menu, func));\
+   (Normalize_Menu(menu) -> typ ## name = func );\
+   RETURN(E_OK);\
+}
+
+/* "Template" macro to generate function to get application specific hook */
+#define GEN_HOOK_GET_FUNCTION( typ, name ) \
+NCURSES_IMPEXP Menu_Hook NCURSES_API typ ## _ ## name ( const MENU *menu )\
+{\
+   T((T_CALLED(#typ "_" #name "(%p)"), (const void *) menu));\
+   returnMenuHook(Normalize_Menu(menu) -> typ ## name);\
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnmenu
+|   Function      :  int set_menu_init(MENU *menu, void (*f)(MENU *))
+|
+|   Description   :  Set user-exit which is called when menu is posted
+|                    or just after the top row changes.
+|
+|   Return Values :  E_OK               - success
++--------------------------------------------------------------------------*/
+GEN_HOOK_SET_FUNCTION(menu, init)
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnmenu
+|   Function      :  void (*)(MENU *) menu_init(const MENU *menu)
+|
+|   Description   :  Return address of user-exit function which is called
+|                    when a menu is posted or just after the top row
+|                    changes.
+|
+|   Return Values :  Menu init function address or NULL
++--------------------------------------------------------------------------*/
+GEN_HOOK_GET_FUNCTION(menu, init)
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnmenu
+|   Function      :  int set_menu_term (MENU *menu, void (*f)(MENU *))
+|
+|   Description   :  Set user-exit which is called when menu is unposted
+|                    or just before the top row changes.
+|
+|   Return Values :  E_OK               - success
++--------------------------------------------------------------------------*/
+GEN_HOOK_SET_FUNCTION(menu, term)
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnmenu
+|   Function      :  void (*)(MENU *) menu_term(const MENU *menu)
+|
+|   Description   :  Return address of user-exit function which is called
+|                    when a menu is unposted or just before the top row
+|                    changes.
+|
+|   Return Values :  Menu finalization function address or NULL
++--------------------------------------------------------------------------*/
+GEN_HOOK_GET_FUNCTION(menu, term)
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnmenu
+|   Function      :  int set_item_init (MENU *menu, void (*f)(MENU *))
+|
+|   Description   :  Set user-exit which is called when menu is posted
+|                    or just after the current item changes.
+|
+|   Return Values :  E_OK               - success
++--------------------------------------------------------------------------*/
+GEN_HOOK_SET_FUNCTION(item, init)
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnmenu
+|   Function      :  void (*)(MENU *) item_init (const MENU *menu)
+|
+|   Description   :  Return address of user-exit function which is called
+|                    when a menu is posted or just after the current item
+|                    changes.
+|
+|   Return Values :  Item init function address or NULL
++--------------------------------------------------------------------------*/
+GEN_HOOK_GET_FUNCTION(item, init)
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnmenu
+|   Function      :  int set_item_term (MENU *menu, void (*f)(MENU *))
+|
+|   Description   :  Set user-exit which is called when menu is unposted
+|                    or just before the current item changes.
+|
+|   Return Values :  E_OK               - success
++--------------------------------------------------------------------------*/
+GEN_HOOK_SET_FUNCTION(item, term)
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnmenu
+|   Function      :  void (*)(MENU *) item_init (const MENU *menu)
+|
+|   Description   :  Return address of user-exit function which is called
+|                    when a menu is unposted or just before the current item
+|                    changes.
+|
+|   Return Values :  Item finalization function address or NULL
++--------------------------------------------------------------------------*/
+GEN_HOOK_GET_FUNCTION(item, term)
+
+/* m_hook.c ends here */
diff --git a/apps/lib/curses/pdcurses/menu/m_item_cur.c b/apps/lib/curses/pdcurses/menu/m_item_cur.c
new file mode 100644
index 0000000..189e61b
--- /dev/null
+++ b/apps/lib/curses/pdcurses/menu/m_item_cur.c
@@ -0,0 +1,113 @@
+/****************************************************************************
+ * Copyright (c) 1998-2004,2010 Free Software Foundation, Inc.              *
+ *                                                                          *
+ * 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, distribute with modifications, sublicense, and/or sell       *
+ * copies of the Software, and to permit persons to whom the Software is    *
+ * furnished to do so, subject to the following conditions:                 *
+ *                                                                          *
+ * The above copyright notice and this permission notice shall be included  *
+ * in all copies or substantial portions of the Software.                   *
+ *                                                                          *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
+ * IN NO EVENT SHALL THE ABOVE 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.                               *
+ *                                                                          *
+ * Except as contained in this notice, the name(s) of the above copyright   *
+ * holders shall not be used in advertising or otherwise to promote the     *
+ * sale, use or other dealings in this Software without prior written       *
+ * authorization.                                                           *
+ ****************************************************************************/
+
+/****************************************************************************
+ *   Author:  Juergen Pfeifer, 1995,1997                                    *
+ ****************************************************************************/
+
+/***************************************************************************
+* Module m_item_cur                                                        *
+* Set and get current menus item                                           *
+***************************************************************************/
+
+#include "menu.priv.h"
+
+MODULE_ID("$Id: m_item_cur.c,v 1.18 2010/01/23 21:20:10 tom Exp $")
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnmenu
+|   Function      :  int set_current_item(MENU *menu, const ITEM *item)
+|
+|   Description   :  Make the item the current item
+|
+|   Return Values :  E_OK                - success
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(int)
+set_current_item(MENU * menu, ITEM * item)
+{
+  T((T_CALLED("set_current_item(%p,%p)"), (void *)menu, (void *)item));
+
+  if (menu && item && (item->imenu == menu))
+    {
+      if (menu->status & _IN_DRIVER)
+	RETURN(E_BAD_STATE);
+
+      assert(menu->curitem);
+      if (item != menu->curitem)
+	{
+	  if (menu->status & _LINK_NEEDED)
+	    {
+	      /*
+	       * Items are available, but they are not linked together.
+	       * So we have to link here.
+	       */
+	      _nc_Link_Items(menu);
+	    }
+	  assert(menu->pattern);
+	  Reset_Pattern(menu);
+	  /* adjust the window to make item visible and update the menu */
+	  Adjust_Current_Item(menu, menu->toprow, item);
+	}
+    }
+  else
+    RETURN(E_BAD_ARGUMENT);
+
+  RETURN(E_OK);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnmenu
+|   Function      :  ITEM *current_item(const MENU *menu)
+|
+|   Description   :  Return the menus current item
+|
+|   Return Values :  Item pointer or NULL if failure
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(ITEM *)
+current_item(const MENU * menu)
+{
+  T((T_CALLED("current_item(%p)"), (const void *)menu));
+  returnItem((menu && menu->items) ? menu->curitem : (ITEM *) 0);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnmenu
+|   Function      :  int item_index(const ITEM *)
+|
+|   Description   :  Return the logical index of this item.
+|
+|   Return Values :  The index or ERR if this is an invalid item pointer
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(int)
+item_index(const ITEM * item)
+{
+  T((T_CALLED("item_index(%p)"), (const void *)item));
+  returnCode((item && item->imenu) ? item->index : ERR);
+}
+
+/* m_item_cur.c ends here */
diff --git a/apps/lib/curses/pdcurses/menu/m_item_nam.c b/apps/lib/curses/pdcurses/menu/m_item_nam.c
new file mode 100644
index 0000000..eb6f58a
--- /dev/null
+++ b/apps/lib/curses/pdcurses/menu/m_item_nam.c
@@ -0,0 +1,72 @@
+/****************************************************************************
+ * Copyright (c) 1998-2004,2010 Free Software Foundation, Inc.              *
+ *                                                                          *
+ * 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, distribute with modifications, sublicense, and/or sell       *
+ * copies of the Software, and to permit persons to whom the Software is    *
+ * furnished to do so, subject to the following conditions:                 *
+ *                                                                          *
+ * The above copyright notice and this permission notice shall be included  *
+ * in all copies or substantial portions of the Software.                   *
+ *                                                                          *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
+ * IN NO EVENT SHALL THE ABOVE 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.                               *
+ *                                                                          *
+ * Except as contained in this notice, the name(s) of the above copyright   *
+ * holders shall not be used in advertising or otherwise to promote the     *
+ * sale, use or other dealings in this Software without prior written       *
+ * authorization.                                                           *
+ ****************************************************************************/
+
+/****************************************************************************
+ *   Author:  Juergen Pfeifer, 1995,1997                                    *
+ ****************************************************************************/
+
+/***************************************************************************
+* Module m_item_nam                                                        *
+* Get menus item name and description                                      *
+***************************************************************************/
+
+#include "menu.priv.h"
+
+MODULE_ID("$Id: m_item_nam.c,v 1.15 2010/01/23 21:20:10 tom Exp $")
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnmenu
+|   Function      :  char *item_name(const ITEM *item)
+|
+|   Description   :  Return name of menu item
+|
+|   Return Values :  See above; returns NULL if item is invalid
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(const char *)
+item_name(const ITEM * item)
+{
+  T((T_CALLED("item_name(%p)"), (const void *)item));
+  returnCPtr((item) ? item->name.str : (char *)0);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnmenu
+|   Function      :  char *item_description(const ITEM *item)
+|
+|   Description   :  Returns description of item
+|
+|   Return Values :  See above; Returns NULL if item is invalid
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(const char *)
+item_description(const ITEM * item)
+{
+  T((T_CALLED("item_description(%p)"), (const void *)item));
+  returnCPtr((item) ? item->description.str : (char *)0);
+}
+
+/* m_item_nam.c ends here */
diff --git a/apps/lib/curses/pdcurses/menu/m_item_new.c b/apps/lib/curses/pdcurses/menu/m_item_new.c
new file mode 100644
index 0000000..a10ec4b
--- /dev/null
+++ b/apps/lib/curses/pdcurses/menu/m_item_new.c
@@ -0,0 +1,275 @@
+/****************************************************************************
+ * Copyright (c) 1998-2009,2010 Free Software Foundation, Inc.              *
+ *                                                                          *
+ * 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, distribute with modifications, sublicense, and/or sell       *
+ * copies of the Software, and to permit persons to whom the Software is    *
+ * furnished to do so, subject to the following conditions:                 *
+ *                                                                          *
+ * The above copyright notice and this permission notice shall be included  *
+ * in all copies or substantial portions of the Software.                   *
+ *                                                                          *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
+ * IN NO EVENT SHALL THE ABOVE 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.                               *
+ *                                                                          *
+ * Except as contained in this notice, the name(s) of the above copyright   *
+ * holders shall not be used in advertising or otherwise to promote the     *
+ * sale, use or other dealings in this Software without prior written       *
+ * authorization.                                                           *
+ ****************************************************************************/
+
+/****************************************************************************
+ *   Author:  Juergen Pfeifer, 1995,1997                                    *
+ ****************************************************************************/
+
+/***************************************************************************
+* Module m_item_new                                                        *
+* Create and destroy menu items                                            *
+* Set and get marker string for menu                                       *
+***************************************************************************/
+
+#include "menu.priv.h"
+
+#if USE_WIDEC_SUPPORT
+#if HAVE_WCTYPE_H
+#include <wctype.h>
+#endif
+#endif
+
+MODULE_ID("$Id: m_item_new.c,v 1.30 2010/01/23 21:20:11 tom Exp $")
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnmenu
+|   Function      :  bool Is_Printable_String(const char *s)
+|
+|   Description   :  Checks whether or not the string contains only printable
+|                    characters.
+|
+|   Return Values :  TRUE     - if string is printable
+|                    FALSE    - if string contains non-printable characters
++--------------------------------------------------------------------------*/
+static bool
+Is_Printable_String(const char *s)
+{
+  int result = TRUE;
+
+#if USE_WIDEC_SUPPORT
+  int count = mbstowcs(0, s, 0);
+  wchar_t *temp = 0;
+
+  assert(s);
+
+  if (count > 0
+      && (temp = typeCalloc(wchar_t, (2 + (unsigned)count))) != 0)
+    {
+      int n;
+
+      mbstowcs(temp, s, (unsigned)count);
+      for (n = 0; n < count; ++n)
+	if (!iswprint((wint_t) temp[n]))
+	  {
+	    result = FALSE;
+	    break;
+	  }
+      free(temp);
+    }
+#else
+  assert(s);
+  while (*s)
+    {
+      if (!isprint(UChar(*s)))
+	{
+	  result = FALSE;
+	  break;
+	}
+      s++;
+    }
+#endif
+  return result;
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnmenu
+|   Function      :  ITEM *new_item(char *name, char *description)
+|
+|   Description   :  Create a new item with name and description. Return
+|                    a pointer to this new item.
+|                    N.B.: an item must(!) have a name.
+|
+|   Return Values :  The item pointer or NULL if creation failed.
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(ITEM *)
+new_item(const char *name, const char *description)
+{
+  ITEM *item;
+
+  T((T_CALLED("new_item(\"%s\", \"%s\")"),
+     name ? name : "",
+     description ? description : ""));
+
+  if (!name || (*name == '\0') || !Is_Printable_String(name))
+    {
+      item = (ITEM *) 0;
+      SET_ERROR(E_BAD_ARGUMENT);
+    }
+  else
+    {
+      item = typeCalloc(ITEM, 1);
+      if (item)
+	{
+	  *item = _nc_Default_Item;	/* hope we have struct assignment */
+
+	  item->name.length = strlen(name);
+	  item->name.str = name;
+
+	  if (description && (*description != '\0') &&
+	      Is_Printable_String(description))
+	    {
+	      item->description.length = strlen(description);
+	      item->description.str = description;
+	    }
+	  else
+	    {
+	      item->description.length = 0;
+	      item->description.str = (char *)0;
+	    }
+	}
+      else
+	SET_ERROR(E_SYSTEM_ERROR);
+    }
+  returnItem(item);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnmenu
+|   Function      :  int free_item(ITEM *item)
+|
+|   Description   :  Free the allocated storage for this item.
+|                    N.B.: a connected item can't be freed.
+|
+|   Return Values :  E_OK              - success
+|                    E_BAD_ARGUMENT    - invalid value has been passed
+|                    E_CONNECTED       - item is still connected to a menu
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(int)
+free_item(ITEM * item)
+{
+  T((T_CALLED("free_item(%p)"), (void *)item));
+
+  if (!item)
+    RETURN(E_BAD_ARGUMENT);
+
+  if (item->imenu)
+    RETURN(E_CONNECTED);
+
+  free(item);
+
+  RETURN(E_OK);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnmenu
+|   Function      :  int set_menu_mark( MENU *menu, const char *mark )
+|
+|   Description   :  Set the mark string used to indicate the current
+|                    item (single-valued menu) or the selected items
+|                    (multi-valued menu).
+|                    The mark argument may be NULL, in which case no
+|                    marker is used.
+|                    This might be a little bit tricky, because this may
+|                    affect the geometry of the menu, which we don't allow
+|                    if it is already posted.
+|
+|   Return Values :  E_OK               - success
+|                    E_BAD_ARGUMENT     - an invalid value has been passed
+|                    E_SYSTEM_ERROR     - no memory to store mark
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(int)
+set_menu_mark(MENU * menu, const char *mark)
+{
+  unsigned l;
+
+  T((T_CALLED("set_menu_mark(%p,%s)"), (void *)menu, _nc_visbuf(mark)));
+
+  if (mark && (*mark != '\0') && Is_Printable_String(mark))
+    l = strlen(mark);
+  else
+    l = 0;
+
+  if (menu)
+    {
+      char *old_mark = menu->mark;
+      unsigned short old_status = menu->status;
+
+      if (menu->status & _POSTED)
+	{
+	  /* If the menu is already posted, the geometry is fixed. Then
+	     we can only accept a mark with exactly the same length */
+	  if (menu->marklen != (int)l)
+	    RETURN(E_BAD_ARGUMENT);
+	}
+      menu->marklen = l;
+      if (l)
+	{
+	  menu->mark = strdup(mark);
+	  if (menu->mark)
+	    {
+	      strcpy(menu->mark, mark);
+	      if (menu != &_nc_Default_Menu)
+		menu->status |= _MARK_ALLOCATED;
+	    }
+	  else
+	    {
+	      menu->mark = old_mark;
+	      menu->marklen = (old_mark != 0) ? strlen(old_mark) : 0;
+	      RETURN(E_SYSTEM_ERROR);
+	    }
+	}
+      else
+	menu->mark = (char *)0;
+
+      if ((old_status & _MARK_ALLOCATED) && old_mark)
+	free(old_mark);
+
+      if (menu->status & _POSTED)
+	{
+	  _nc_Draw_Menu(menu);
+	  _nc_Show_Menu(menu);
+	}
+      else
+	{
+	  /* Recalculate the geometry */
+	  _nc_Calculate_Item_Length_and_Width(menu);
+	}
+    }
+  else
+    {
+      returnCode(set_menu_mark(&_nc_Default_Menu, mark));
+    }
+  RETURN(E_OK);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnmenu
+|   Function      :  char *menu_mark(const MENU *menu)
+|
+|   Description   :  Return a pointer to the marker string
+|
+|   Return Values :  The marker string pointer or NULL if no marker defined
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(const char *)
+menu_mark(const MENU * menu)
+{
+  T((T_CALLED("menu_mark(%p)"), (const void *)menu));
+  returnPtr(Normalize_Menu(menu)->mark);
+}
+
+/* m_item_new.c */
diff --git a/apps/lib/curses/pdcurses/menu/m_item_opt.c b/apps/lib/curses/pdcurses/menu/m_item_opt.c
new file mode 100644
index 0000000..de5eb8d
--- /dev/null
+++ b/apps/lib/curses/pdcurses/menu/m_item_opt.c
@@ -0,0 +1,159 @@
+/****************************************************************************
+ * Copyright (c) 1998-2004,2010 Free Software Foundation, Inc.              *
+ *                                                                          *
+ * 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, distribute with modifications, sublicense, and/or sell       *
+ * copies of the Software, and to permit persons to whom the Software is    *
+ * furnished to do so, subject to the following conditions:                 *
+ *                                                                          *
+ * The above copyright notice and this permission notice shall be included  *
+ * in all copies or substantial portions of the Software.                   *
+ *                                                                          *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
+ * IN NO EVENT SHALL THE ABOVE 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.                               *
+ *                                                                          *
+ * Except as contained in this notice, the name(s) of the above copyright   *
+ * holders shall not be used in advertising or otherwise to promote the     *
+ * sale, use or other dealings in this Software without prior written       *
+ * authorization.                                                           *
+ ****************************************************************************/
+
+/****************************************************************************
+ *   Author:  Juergen Pfeifer, 1995,1997                                    *
+ ****************************************************************************/
+
+/***************************************************************************
+* Module m_item_opt                                                        *
+* Menus item option routines                                               *
+***************************************************************************/
+
+#include "menu.priv.h"
+
+MODULE_ID("$Id: m_item_opt.c,v 1.18 2010/01/23 21:20:10 tom Exp $")
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnmenu
+|   Function      :  int set_item_opts(ITEM *item, Item_Options opts)
+|
+|   Description   :  Set the options of the item. If there are relevant
+|                    changes, the item is connected and the menu is posted,
+|                    the menu will be redisplayed.
+|
+|   Return Values :  E_OK            - success
+|                    E_BAD_ARGUMENT  - invalid item options
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(int)
+set_item_opts(ITEM * item, Item_Options opts)
+{
+  T((T_CALLED("set_menu_opts(%p,%d)"), (void *)item, opts));
+
+  opts &= ALL_ITEM_OPTS;
+
+  if (opts & ~ALL_ITEM_OPTS)
+    RETURN(E_BAD_ARGUMENT);
+
+  if (item)
+    {
+      if (item->opt != opts)
+	{
+	  MENU *menu = item->imenu;
+
+	  item->opt = opts;
+
+	  if ((!(opts & O_SELECTABLE)) && item->value)
+	    item->value = FALSE;
+
+	  if (menu && (menu->status & _POSTED))
+	    {
+	      Move_And_Post_Item(menu, item);
+	      _nc_Show_Menu(menu);
+	    }
+	}
+    }
+  else
+    _nc_Default_Item.opt = opts;
+
+  RETURN(E_OK);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnmenu
+|   Function      :  int item_opts_off(ITEM *item, Item_Options opts)
+|
+|   Description   :  Switch of the options for this item.
+|
+|   Return Values :  E_OK            - success
+|                    E_BAD_ARGUMENT  - invalid options
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(int)
+item_opts_off(ITEM * item, Item_Options opts)
+{
+  ITEM *citem = item;		/* use a copy because set_item_opts must detect
+
+				   NULL item itself to adjust its behavior */
+
+  T((T_CALLED("item_opts_off(%p,%d)"), (void *)item, opts));
+
+  if (opts & ~ALL_ITEM_OPTS)
+    RETURN(E_BAD_ARGUMENT);
+  else
+    {
+      Normalize_Item(citem);
+      opts = citem->opt & ~(opts & ALL_ITEM_OPTS);
+      returnCode(set_item_opts(item, opts));
+    }
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnmenu
+|   Function      :  int item_opts_on(ITEM *item, Item_Options opts)
+|
+|   Description   :  Switch on the options for this item.
+|
+|   Return Values :  E_OK            - success
+|                    E_BAD_ARGUMENT  - invalid options
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(int)
+item_opts_on(ITEM * item, Item_Options opts)
+{
+  ITEM *citem = item;		/* use a copy because set_item_opts must detect
+
+				   NULL item itself to adjust its behavior */
+
+  T((T_CALLED("item_opts_on(%p,%d)"), (void *)item, opts));
+
+  opts &= ALL_ITEM_OPTS;
+  if (opts & ~ALL_ITEM_OPTS)
+    RETURN(E_BAD_ARGUMENT);
+  else
+    {
+      Normalize_Item(citem);
+      opts = citem->opt | opts;
+      returnCode(set_item_opts(item, opts));
+    }
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnmenu
+|   Function      :  Item_Options item_opts(const ITEM *item)
+|
+|   Description   :  Switch of the options for this item.
+|
+|   Return Values :  Items options
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(Item_Options)
+item_opts(const ITEM * item)
+{
+  T((T_CALLED("item_opts(%p)"), (const void *)item));
+  returnItemOpts(ALL_ITEM_OPTS & Normalize_Item(item)->opt);
+}
+
+/* m_item_opt.c ends here */
diff --git a/apps/lib/curses/pdcurses/menu/m_item_top.c b/apps/lib/curses/pdcurses/menu/m_item_top.c
new file mode 100644
index 0000000..89f8316
--- /dev/null
+++ b/apps/lib/curses/pdcurses/menu/m_item_top.c
@@ -0,0 +1,107 @@
+/****************************************************************************
+ * Copyright (c) 1998-2004,2010 Free Software Foundation, Inc.              *
+ *                                                                          *
+ * 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, distribute with modifications, sublicense, and/or sell       *
+ * copies of the Software, and to permit persons to whom the Software is    *
+ * furnished to do so, subject to the following conditions:                 *
+ *                                                                          *
+ * The above copyright notice and this permission notice shall be included  *
+ * in all copies or substantial portions of the Software.                   *
+ *                                                                          *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
+ * IN NO EVENT SHALL THE ABOVE 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.                               *
+ *                                                                          *
+ * Except as contained in this notice, the name(s) of the above copyright   *
+ * holders shall not be used in advertising or otherwise to promote the     *
+ * sale, use or other dealings in this Software without prior written       *
+ * authorization.                                                           *
+ ****************************************************************************/
+
+/****************************************************************************
+ *   Author:  Juergen Pfeifer, 1995,1997                                    *
+ ****************************************************************************/
+
+/***************************************************************************
+* Module m_item_top                                                        *
+* Set and get top menus item                                               *
+***************************************************************************/
+
+#include "menu.priv.h"
+
+MODULE_ID("$Id: m_item_top.c,v 1.11 2010/01/23 21:20:10 tom Exp $")
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnmenu
+|   Function      :  int set_top_row(MENU *menu, int row)
+|
+|   Description   :  Makes the specified row the top row in the menu
+|
+|   Return Values :  E_OK             - success
+|                    E_BAD_ARGUMENT   - not a menu pointer or invalid row
+|                    E_NOT_CONNECTED  - there are no items for the menu
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(int)
+set_top_row(MENU * menu, int row)
+{
+  ITEM *item;
+
+  T((T_CALLED("set_top_row(%p,%d)"), (void *)menu, row));
+
+  if (menu)
+    {
+      if (menu->status & _IN_DRIVER)
+	RETURN(E_BAD_STATE);
+      if (menu->items == (ITEM **) 0)
+	RETURN(E_NOT_CONNECTED);
+
+      if ((row < 0) || (row > (menu->rows - menu->arows)))
+	RETURN(E_BAD_ARGUMENT);
+    }
+  else
+    RETURN(E_BAD_ARGUMENT);
+
+  if (row != menu->toprow)
+    {
+      if (menu->status & _LINK_NEEDED)
+	_nc_Link_Items(menu);
+
+      item = menu->items[(menu->opt & O_ROWMAJOR) ? (row * menu->cols) : row];
+      assert(menu->pattern);
+      Reset_Pattern(menu);
+      _nc_New_TopRow_and_CurrentItem(menu, row, item);
+    }
+
+  RETURN(E_OK);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnmenu
+|   Function      :  int top_row(const MENU *)
+|
+|   Description   :  Return the top row of the menu
+|
+|   Return Values :  The row number or ERR if there is no row
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(int)
+top_row(const MENU * menu)
+{
+  T((T_CALLED("top_row(%p)"), (const void *)menu));
+  if (menu && menu->items && *(menu->items))
+    {
+      assert((menu->toprow >= 0) && (menu->toprow < menu->rows));
+      returnCode(menu->toprow);
+    }
+  else
+    returnCode(ERR);
+}
+
+/* m_item_top.c ends here */
diff --git a/apps/lib/curses/pdcurses/menu/m_item_use.c b/apps/lib/curses/pdcurses/menu/m_item_use.c
new file mode 100644
index 0000000..4a25a85
--- /dev/null
+++ b/apps/lib/curses/pdcurses/menu/m_item_use.c
@@ -0,0 +1,76 @@
+/****************************************************************************
+ * Copyright (c) 1998-2004,2010 Free Software Foundation, Inc.              *
+ *                                                                          *
+ * 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, distribute with modifications, sublicense, and/or sell       *
+ * copies of the Software, and to permit persons to whom the Software is    *
+ * furnished to do so, subject to the following conditions:                 *
+ *                                                                          *
+ * The above copyright notice and this permission notice shall be included  *
+ * in all copies or substantial portions of the Software.                   *
+ *                                                                          *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
+ * IN NO EVENT SHALL THE ABOVE 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.                               *
+ *                                                                          *
+ * Except as contained in this notice, the name(s) of the above copyright   *
+ * holders shall not be used in advertising or otherwise to promote the     *
+ * sale, use or other dealings in this Software without prior written       *
+ * authorization.                                                           *
+ ****************************************************************************/
+
+/****************************************************************************
+ *   Author:  Juergen Pfeifer, 1995,1997                                    *
+ ****************************************************************************/
+
+/***************************************************************************
+* Module m_item_use                                                        *
+* Associate application data with menu items                               *
+***************************************************************************/
+
+#include "menu.priv.h"
+
+MODULE_ID("$Id: m_item_use.c,v 1.17 2010/01/23 21:20:10 tom Exp $")
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnmenu
+|   Function      :  int set_item_userptr(ITEM *item, void *userptr)
+|
+|   Description   :  Set the pointer that is reserved in any item to store
+|                    application relevant informations.
+|
+|   Return Values :  E_OK               - success
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(int)
+set_item_userptr(ITEM * item, void *userptr)
+{
+  T((T_CALLED("set_item_userptr(%p,%p)"), (void *)item, (void *)userptr));
+  Normalize_Item(item)->userptr = userptr;
+  RETURN(E_OK);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnmenu
+|   Function      :  void *item_userptr(const ITEM *item)
+|
+|   Description   :  Return the pointer that is reserved in any item to store
+|                    application relevant informations.
+|
+|   Return Values :  Value of the pointer. If no such pointer has been set,
+|                    NULL is returned.
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(void *)
+item_userptr(const ITEM * item)
+{
+  T((T_CALLED("item_userptr(%p)"), (const void *)item));
+  returnVoidPtr(Normalize_Item(item)->userptr);
+}
+
+/* m_item_use.c */
diff --git a/apps/lib/curses/pdcurses/menu/m_item_val.c b/apps/lib/curses/pdcurses/menu/m_item_val.c
new file mode 100644
index 0000000..c628338
--- /dev/null
+++ b/apps/lib/curses/pdcurses/menu/m_item_val.c
@@ -0,0 +1,104 @@
+/****************************************************************************
+ * Copyright (c) 1998-2004,2010 Free Software Foundation, Inc.              *
+ *                                                                          *
+ * 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, distribute with modifications, sublicense, and/or sell       *
+ * copies of the Software, and to permit persons to whom the Software is    *
+ * furnished to do so, subject to the following conditions:                 *
+ *                                                                          *
+ * The above copyright notice and this permission notice shall be included  *
+ * in all copies or substantial portions of the Software.                   *
+ *                                                                          *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
+ * IN NO EVENT SHALL THE ABOVE 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.                               *
+ *                                                                          *
+ * Except as contained in this notice, the name(s) of the above copyright   *
+ * holders shall not be used in advertising or otherwise to promote the     *
+ * sale, use or other dealings in this Software without prior written       *
+ * authorization.                                                           *
+ ****************************************************************************/
+
+/****************************************************************************
+ *   Author:  Juergen Pfeifer, 1995,1997                                    *
+ ****************************************************************************/
+
+/***************************************************************************
+* Module m_item_val                                                        *
+* Set and get menus item values                                            *
+***************************************************************************/
+
+#include "menu.priv.h"
+
+MODULE_ID("$Id: m_item_val.c,v 1.15 2010/01/23 21:20:10 tom Exp $")
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnmenu
+|   Function      :  int set_item_value(ITEM *item, int value)
+|
+|   Description   :  Programmatically set the item's selection value. This is
+|                    only allowed if the item is selectable at all and if
+|                    it is not connected to a single-valued menu.
+|                    If the item is connected to a posted menu, the menu
+|                    will be redisplayed.
+|
+|   Return Values :  E_OK              - success
+|                    E_REQUEST_DENIED  - not selectable or single valued menu
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(int)
+set_item_value(ITEM * item, bool value)
+{
+  MENU *menu;
+
+  T((T_CALLED("set_item_value(%p,%d)"), (void *)item, value));
+  if (item)
+    {
+      menu = item->imenu;
+
+      if ((!(item->opt & O_SELECTABLE)) ||
+	  (menu && (menu->opt & O_ONEVALUE)))
+	RETURN(E_REQUEST_DENIED);
+
+      if (item->value ^ value)
+	{
+	  item->value = value ? TRUE : FALSE;
+	  if (menu)
+	    {
+	      if (menu->status & _POSTED)
+		{
+		  Move_And_Post_Item(menu, item);
+		  _nc_Show_Menu(menu);
+		}
+	    }
+	}
+    }
+  else
+    _nc_Default_Item.value = value;
+
+  RETURN(E_OK);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnmenu
+|   Function      :  bool item_value(const ITEM *item)
+|
+|   Description   :  Return the selection value of the item
+|
+|   Return Values :  TRUE   - if item is selected
+|                    FALSE  - if item is not selected
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(bool)
+item_value(const ITEM * item)
+{
+  T((T_CALLED("item_value(%p)"), (const void *)item));
+  returnBool((Normalize_Item(item)->value) ? TRUE : FALSE);
+}
+
+/* m_item_val.c ends here */
diff --git a/apps/lib/curses/pdcurses/menu/m_item_vis.c b/apps/lib/curses/pdcurses/menu/m_item_vis.c
new file mode 100644
index 0000000..312f0a0
--- /dev/null
+++ b/apps/lib/curses/pdcurses/menu/m_item_vis.c
@@ -0,0 +1,68 @@
+/****************************************************************************
+ * Copyright (c) 1998-2004,2010 Free Software Foundation, Inc.              *
+ *                                                                          *
+ * 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, distribute with modifications, sublicense, and/or sell       *
+ * copies of the Software, and to permit persons to whom the Software is    *
+ * furnished to do so, subject to the following conditions:                 *
+ *                                                                          *
+ * The above copyright notice and this permission notice shall be included  *
+ * in all copies or substantial portions of the Software.                   *
+ *                                                                          *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
+ * IN NO EVENT SHALL THE ABOVE 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.                               *
+ *                                                                          *
+ * Except as contained in this notice, the name(s) of the above copyright   *
+ * holders shall not be used in advertising or otherwise to promote the     *
+ * sale, use or other dealings in this Software without prior written       *
+ * authorization.                                                           *
+ ****************************************************************************/
+
+/****************************************************************************
+ *   Author:  Juergen Pfeifer, 1995,1997                                    *
+ ****************************************************************************/
+
+/***************************************************************************
+* Module m_item_vis                                                        *
+* Tell if menu item is visible                                             *
+***************************************************************************/
+
+#include "menu.priv.h"
+
+MODULE_ID("$Id: m_item_vis.c,v 1.16 2010/01/23 21:20:10 tom Exp $")
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnmenu
+|   Function      :  bool item_visible(const ITEM *item)
+|
+|   Description   :  A item is visible if it currently appears in the
+|                    subwindow of a posted menu.
+|
+|   Return Values :  TRUE  if visible
+|                    FALSE if invisible
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(bool)
+item_visible(const ITEM * item)
+{
+  MENU *menu;
+
+  T((T_CALLED("item_visible(%p)"), (const void *)item));
+  if (item &&
+      (menu = item->imenu) &&
+      (menu->status & _POSTED) &&
+      ((menu->toprow + menu->arows) > (item->y)) &&
+      (item->y >= menu->toprow))
+    returnBool(TRUE);
+  else
+    returnBool(FALSE);
+}
+
+/* m_item_vis.c ends here */
diff --git a/apps/lib/curses/pdcurses/menu/m_items.c b/apps/lib/curses/pdcurses/menu/m_items.c
new file mode 100644
index 0000000..e1755f1
--- /dev/null
+++ b/apps/lib/curses/pdcurses/menu/m_items.c
@@ -0,0 +1,110 @@
+/****************************************************************************
+ * Copyright (c) 1998-2005,2010 Free Software Foundation, Inc.              *
+ *                                                                          *
+ * 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, distribute with modifications, sublicense, and/or sell       *
+ * copies of the Software, and to permit persons to whom the Software is    *
+ * furnished to do so, subject to the following conditions:                 *
+ *                                                                          *
+ * The above copyright notice and this permission notice shall be included  *
+ * in all copies or substantial portions of the Software.                   *
+ *                                                                          *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
+ * IN NO EVENT SHALL THE ABOVE 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.                               *
+ *                                                                          *
+ * Except as contained in this notice, the name(s) of the above copyright   *
+ * holders shall not be used in advertising or otherwise to promote the     *
+ * sale, use or other dealings in this Software without prior written       *
+ * authorization.                                                           *
+ ****************************************************************************/
+
+/****************************************************************************
+ *   Author:  Juergen Pfeifer, 1995,1997                                    *
+ ****************************************************************************/
+
+/***************************************************************************
+* Module m_items                                                           *
+* Connect and disconnect items to and from menus                           *
+***************************************************************************/
+
+#include "menu.priv.h"
+
+MODULE_ID("$Id: m_items.c,v 1.17 2010/01/23 21:20:10 tom Exp $")
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnmenu
+|   Function      :  int set_menu_items(MENU *menu, ITEM **items)
+|
+|   Description   :  Sets the item pointer array connected to menu.
+|
+|   Return Values :  E_OK           - success
+|                    E_POSTED       - menu is already posted
+|                    E_CONNECTED    - one or more items are already connected
+|                                     to another menu.
+|                    E_BAD_ARGUMENT - An incorrect menu or item array was
+|                                     passed to the function
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(int)
+set_menu_items(MENU * menu, ITEM ** items)
+{
+  T((T_CALLED("set_menu_items(%p,%p)"), (void *)menu, (void *)items));
+
+  if (!menu || (items && !(*items)))
+    RETURN(E_BAD_ARGUMENT);
+
+  if (menu->status & _POSTED)
+    RETURN(E_POSTED);
+
+  if (menu->items)
+    _nc_Disconnect_Items(menu);
+
+  if (items)
+    {
+      if (!_nc_Connect_Items(menu, items))
+	RETURN(E_CONNECTED);
+    }
+
+  menu->items = items;
+  RETURN(E_OK);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnmenu
+|   Function      :  ITEM **menu_items(const MENU *menu)
+|
+|   Description   :  Returns a pointer to the item pointer array of the menu
+|
+|   Return Values :  NULL on error
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(ITEM **)
+menu_items(const MENU * menu)
+{
+  T((T_CALLED("menu_items(%p)"), (const void *)menu));
+  returnItemPtr(menu ? menu->items : (ITEM **) 0);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnmenu
+|   Function      :  int item_count(const MENU *menu)
+|
+|   Description   :  Get the number of items connected to the menu. If the
+|                    menu pointer is NULL we return -1.
+|
+|   Return Values :  Number of items or -1 to indicate error.
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(int)
+item_count(const MENU * menu)
+{
+  T((T_CALLED("item_count(%p)"), (const void *)menu));
+  returnCode(menu ? menu->nitems : -1);
+}
+
+/* m_items.c ends here */
diff --git a/apps/lib/curses/pdcurses/menu/m_new.c b/apps/lib/curses/pdcurses/menu/m_new.c
new file mode 100644
index 0000000..2f9fe55
--- /dev/null
+++ b/apps/lib/curses/pdcurses/menu/m_new.c
@@ -0,0 +1,142 @@
+/****************************************************************************
+ * Copyright (c) 1998-2009,2010 Free Software Foundation, Inc.              *
+ *                                                                          *
+ * 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, distribute with modifications, sublicense, and/or sell       *
+ * copies of the Software, and to permit persons to whom the Software is    *
+ * furnished to do so, subject to the following conditions:                 *
+ *                                                                          *
+ * The above copyright notice and this permission notice shall be included  *
+ * in all copies or substantial portions of the Software.                   *
+ *                                                                          *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
+ * IN NO EVENT SHALL THE ABOVE 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.                               *
+ *                                                                          *
+ * Except as contained in this notice, the name(s) of the above copyright   *
+ * holders shall not be used in advertising or otherwise to promote the     *
+ * sale, use or other dealings in this Software without prior written       *
+ * authorization.                                                           *
+ ****************************************************************************/
+
+/****************************************************************************
+ *   Author:  Juergen Pfeifer, 1995,1997                                    *
+ ****************************************************************************/
+
+/***************************************************************************
+* Module m_new                                                             *
+* Creation and destruction of new menus                                    *
+***************************************************************************/
+
+#include "menu.priv.h"
+
+MODULE_ID("$Id: m_new.c,v 1.21 2010/01/23 21:20:11 tom Exp $")
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnmenu
+|   Function      :  MENU* _nc_new_menu(SCREEN*, ITEM **items)
+|
+|   Description   :  Creates a new menu connected to the item pointer
+|                    array items and returns a pointer to the new menu.
+|                    The new menu is initialized with the values from the
+|                    default menu.
+|
+|   Return Values :  NULL on error
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(MENU *)
+NCURSES_SP_NAME(new_menu) (NCURSES_SP_DCLx ITEM ** items)
+{
+  int err = E_SYSTEM_ERROR;
+  MENU *menu = typeCalloc(MENU, 1);
+
+  T((T_CALLED("new_menu(%p,%p)"), (void *)SP_PARM, (void *)items));
+  if (menu)
+    {
+      *menu = _nc_Default_Menu;
+      menu->status = 0;
+      menu->rows = menu->frows;
+      menu->cols = menu->fcols;
+#if NCURSES_SP_FUNCS
+      /* This ensures userwin and usersub are always non-null,
+         so we can derive always the SCREEN that this menu is
+         running on. */
+      menu->userwin = SP_PARM->_stdscr;
+      menu->usersub = SP_PARM->_stdscr;
+#endif
+      if (items && *items)
+	{
+	  if (!_nc_Connect_Items(menu, items))
+	    {
+	      err = E_NOT_CONNECTED;
+	      free(menu);
+	      menu = (MENU *) 0;
+	    }
+	  else
+	    err = E_OK;
+	}
+    }
+
+  if (!menu)
+    SET_ERROR(err);
+
+  returnMenu(menu);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnmenu
+|   Function      :  MENU *new_menu(ITEM **items)
+|
+|   Description   :  Creates a new menu connected to the item pointer
+|                    array items and returns a pointer to the new menu.
+|                    The new menu is initialized with the values from the
+|                    default menu.
+|
+|   Return Values :  NULL on error
++--------------------------------------------------------------------------*/
+#if NCURSES_SP_FUNCS
+NCURSES_EXPORT(MENU *)
+new_menu(ITEM ** items)
+{
+  return NCURSES_SP_NAME(new_menu) (CURRENT_SCREEN, items);
+}
+#endif
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnmenu
+|   Function      :  int free_menu(MENU *menu)
+|
+|   Description   :  Disconnects menu from its associated item pointer
+|                    array and frees the storage allocated for the menu.
+|
+|   Return Values :  E_OK               - success
+|                    E_BAD_ARGUMENT     - Invalid menu pointer passed
+|                    E_POSTED           - Menu is already posted
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(int)
+free_menu(MENU * menu)
+{
+  T((T_CALLED("free_menu(%p)"), (void *)menu));
+  if (!menu)
+    RETURN(E_BAD_ARGUMENT);
+
+  if (menu->status & _POSTED)
+    RETURN(E_POSTED);
+
+  if (menu->items)
+    _nc_Disconnect_Items(menu);
+
+  if ((menu->status & _MARK_ALLOCATED) && menu->mark)
+    free(menu->mark);
+
+  free(menu);
+  RETURN(E_OK);
+}
+
+/* m_new.c ends here */
diff --git a/apps/lib/curses/pdcurses/menu/m_opts.c b/apps/lib/curses/pdcurses/menu/m_opts.c
new file mode 100644
index 0000000..bc6924b
--- /dev/null
+++ b/apps/lib/curses/pdcurses/menu/m_opts.c
@@ -0,0 +1,183 @@
+/****************************************************************************
+ * Copyright (c) 1998-2004,2010 Free Software Foundation, Inc.              *
+ *                                                                          *
+ * 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, distribute with modifications, sublicense, and/or sell       *
+ * copies of the Software, and to permit persons to whom the Software is    *
+ * furnished to do so, subject to the following conditions:                 *
+ *                                                                          *
+ * The above copyright notice and this permission notice shall be included  *
+ * in all copies or substantial portions of the Software.                   *
+ *                                                                          *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
+ * IN NO EVENT SHALL THE ABOVE 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.                               *
+ *                                                                          *
+ * Except as contained in this notice, the name(s) of the above copyright   *
+ * holders shall not be used in advertising or otherwise to promote the     *
+ * sale, use or other dealings in this Software without prior written       *
+ * authorization.                                                           *
+ ****************************************************************************/
+
+/****************************************************************************
+ *   Author:  Juergen Pfeifer, 1995,1997                                    *
+ ****************************************************************************/
+
+/***************************************************************************
+* Module m_opts                                                            *
+* Menus option routines                                                    *
+***************************************************************************/
+
+#include "menu.priv.h"
+
+MODULE_ID("$Id: m_opts.c,v 1.20 2010/01/23 21:20:10 tom Exp $")
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnmenu
+|   Function      :  int set_menu_opts(MENU *menu, Menu_Options opts)
+|
+|   Description   :  Set the options for this menu. If the new settings
+|                    end up in a change of the geometry of the menu, it
+|                    will be recalculated. This operation is forbidden if
+|                    the menu is already posted.
+|
+|   Return Values :  E_OK           - success
+|                    E_BAD_ARGUMENT - invalid menu options
+|                    E_POSTED       - menu is already posted
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(int)
+set_menu_opts(MENU * menu, Menu_Options opts)
+{
+  T((T_CALLED("set_menu_opts(%p,%d)"), (void *)menu, opts));
+
+  opts &= ALL_MENU_OPTS;
+
+  if (opts & ~ALL_MENU_OPTS)
+    RETURN(E_BAD_ARGUMENT);
+
+  if (menu)
+    {
+      if (menu->status & _POSTED)
+	RETURN(E_POSTED);
+
+      if ((opts & O_ROWMAJOR) != (menu->opt & O_ROWMAJOR))
+	{
+	  /* we need this only if the layout really changed ... */
+	  if (menu->items && menu->items[0])
+	    {
+	      menu->toprow = 0;
+	      menu->curitem = menu->items[0];
+	      assert(menu->curitem);
+	      set_menu_format(menu, menu->frows, menu->fcols);
+	    }
+	}
+
+      menu->opt = opts;
+
+      if (opts & O_ONEVALUE)
+	{
+	  ITEM **item;
+
+	  if (((item = menu->items) != (ITEM **) 0))
+	    for (; *item; item++)
+	      (*item)->value = FALSE;
+	}
+
+      if (opts & O_SHOWDESC)	/* this also changes the geometry */
+	_nc_Calculate_Item_Length_and_Width(menu);
+    }
+  else
+    _nc_Default_Menu.opt = opts;
+
+  RETURN(E_OK);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnmenu
+|   Function      :  int menu_opts_off(MENU *menu, Menu_Options opts)
+|
+|   Description   :  Switch off the options for this menu. If the new settings
+|                    end up in a change of the geometry of the menu, it
+|                    will be recalculated. This operation is forbidden if
+|                    the menu is already posted.
+|
+|   Return Values :  E_OK           - success
+|                    E_BAD_ARGUMENT - invalid options
+|                    E_POSTED       - menu is already posted
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(int)
+menu_opts_off(MENU * menu, Menu_Options opts)
+{
+  MENU *cmenu = menu;		/* use a copy because set_menu_opts must detect
+
+				   NULL menu itself to adjust its behavior */
+
+  T((T_CALLED("menu_opts_off(%p,%d)"), (void *)menu, opts));
+
+  opts &= ALL_MENU_OPTS;
+  if (opts & ~ALL_MENU_OPTS)
+    RETURN(E_BAD_ARGUMENT);
+  else
+    {
+      Normalize_Menu(cmenu);
+      opts = cmenu->opt & ~opts;
+      returnCode(set_menu_opts(menu, opts));
+    }
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnmenu
+|   Function      :  int menu_opts_on(MENU *menu, Menu_Options opts)
+|
+|   Description   :  Switch on the options for this menu. If the new settings
+|                    end up in a change of the geometry of the menu, it
+|                    will be recalculated. This operation is forbidden if
+|                    the menu is already posted.
+|
+|   Return Values :  E_OK           - success
+|                    E_BAD_ARGUMENT - invalid menu options
+|                    E_POSTED       - menu is already posted
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(int)
+menu_opts_on(MENU * menu, Menu_Options opts)
+{
+  MENU *cmenu = menu;		/* use a copy because set_menu_opts must detect
+
+				   NULL menu itself to adjust its behavior */
+
+  T((T_CALLED("menu_opts_on(%p,%d)"), (void *)menu, opts));
+
+  opts &= ALL_MENU_OPTS;
+  if (opts & ~ALL_MENU_OPTS)
+    RETURN(E_BAD_ARGUMENT);
+  else
+    {
+      Normalize_Menu(cmenu);
+      opts = cmenu->opt | opts;
+      returnCode(set_menu_opts(menu, opts));
+    }
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnmenu
+|   Function      :  Menu_Options menu_opts(const MENU *menu)
+|
+|   Description   :  Return the options for this menu.
+|
+|   Return Values :  Menu options
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(Menu_Options)
+menu_opts(const MENU * menu)
+{
+  T((T_CALLED("menu_opts(%p)"), (const void *)menu));
+  returnMenuOpts(ALL_MENU_OPTS & Normalize_Menu(menu)->opt);
+}
+
+/* m_opts.c ends here */
diff --git a/apps/lib/curses/pdcurses/menu/m_pad.c b/apps/lib/curses/pdcurses/menu/m_pad.c
new file mode 100644
index 0000000..379ce7c
--- /dev/null
+++ b/apps/lib/curses/pdcurses/menu/m_pad.c
@@ -0,0 +1,95 @@
+/****************************************************************************
+ * Copyright (c) 1998-2004,2010 Free Software Foundation, Inc.              *
+ *                                                                          *
+ * 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, distribute with modifications, sublicense, and/or sell       *
+ * copies of the Software, and to permit persons to whom the Software is    *
+ * furnished to do so, subject to the following conditions:                 *
+ *                                                                          *
+ * The above copyright notice and this permission notice shall be included  *
+ * in all copies or substantial portions of the Software.                   *
+ *                                                                          *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
+ * IN NO EVENT SHALL THE ABOVE 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.                               *
+ *                                                                          *
+ * Except as contained in this notice, the name(s) of the above copyright   *
+ * holders shall not be used in advertising or otherwise to promote the     *
+ * sale, use or other dealings in this Software without prior written       *
+ * authorization.                                                           *
+ ****************************************************************************/
+
+/****************************************************************************
+ *   Author:  Juergen Pfeifer, 1995,1997                                    *
+ ****************************************************************************/
+
+/***************************************************************************
+* Module m_pad                                                             *
+* Control menus padding character                                          *
+***************************************************************************/
+
+#include "menu.priv.h"
+
+MODULE_ID("$Id: m_pad.c,v 1.12 2010/01/23 21:20:10 tom Exp $")
+
+/* Macro to redraw menu if it is posted and changed */
+#define Refresh_Menu(menu) \
+   if ( (menu) && ((menu)->status & _POSTED) )\
+   {\
+      _nc_Draw_Menu( menu );\
+      _nc_Show_Menu( menu ); \
+   }
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnmenu
+|   Function      :  int set_menu_pad(MENU* menu, int pad)
+|
+|   Description   :  Set the character to be used to separate the item name
+|                    from its description. This must be a printable
+|                    character.
+|
+|   Return Values :  E_OK              - success
+|                    E_BAD_ARGUMENT    - an invalid value has been passed
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(int)
+set_menu_pad(MENU * menu, int pad)
+{
+  bool do_refresh = (menu != (MENU *) 0);
+
+  T((T_CALLED("set_menu_pad(%p,%d)"), (void *)menu, pad));
+
+  if (!isprint(UChar(pad)))
+    RETURN(E_BAD_ARGUMENT);
+
+  Normalize_Menu(menu);
+  menu->pad = pad;
+
+  if (do_refresh)
+    Refresh_Menu(menu);
+
+  RETURN(E_OK);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnmenu
+|   Function      :  int menu_pad(const MENU *menu)
+|
+|   Description   :  Return the value of the padding character
+|
+|   Return Values :  The pad character
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(int)
+menu_pad(const MENU * menu)
+{
+  T((T_CALLED("menu_pad(%p)"), (const void *)menu));
+  returnCode(Normalize_Menu(menu)->pad);
+}
+
+/* m_pad.c ends here */
diff --git a/apps/lib/curses/pdcurses/menu/m_pattern.c b/apps/lib/curses/pdcurses/menu/m_pattern.c
new file mode 100644
index 0000000..ebede0a
--- /dev/null
+++ b/apps/lib/curses/pdcurses/menu/m_pattern.c
@@ -0,0 +1,124 @@
+/****************************************************************************
+ * Copyright (c) 1998-2006,2010 Free Software Foundation, Inc.              *
+ *                                                                          *
+ * 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, distribute with modifications, sublicense, and/or sell       *
+ * copies of the Software, and to permit persons to whom the Software is    *
+ * furnished to do so, subject to the following conditions:                 *
+ *                                                                          *
+ * The above copyright notice and this permission notice shall be included  *
+ * in all copies or substantial portions of the Software.                   *
+ *                                                                          *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
+ * IN NO EVENT SHALL THE ABOVE 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.                               *
+ *                                                                          *
+ * Except as contained in this notice, the name(s) of the above copyright   *
+ * holders shall not be used in advertising or otherwise to promote the     *
+ * sale, use or other dealings in this Software without prior written       *
+ * authorization.                                                           *
+ ****************************************************************************/
+
+/****************************************************************************
+ *   Author:  Juergen Pfeifer, 1995,1997                                    *
+ ****************************************************************************/
+
+/***************************************************************************
+* Module m_pattern                                                         *
+* Pattern matching handling                                                *
+***************************************************************************/
+
+#include "menu.priv.h"
+
+MODULE_ID("$Id: m_pattern.c,v 1.16 2010/01/23 21:20:10 tom Exp $")
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnmenu
+|   Function      :  char *menu_pattern(const MENU *menu)
+|
+|   Description   :  Return the value of the pattern buffer.
+|
+|   Return Values :  NULL          - if there is no pattern buffer allocated
+|                    EmptyString   - if there is a pattern buffer but no
+|                                    pattern is stored
+|                    PatternString - as expected
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(char *)
+menu_pattern(const MENU * menu)
+{
+  static char empty[] = "";
+
+  T((T_CALLED("menu_pattern(%p)"), (const void *)menu));
+  returnPtr(menu ? (menu->pattern ? menu->pattern : empty) : 0);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnmenu
+|   Function      :  int set_menu_pattern(MENU *menu, const char *p)
+|
+|   Description   :  Set the match pattern for a menu and position to the
+|                    first item that matches.
+|
+|   Return Values :  E_OK              - success
+|                    E_BAD_ARGUMENT    - invalid menu or pattern pointer
+|                    E_BAD_STATE       - menu in user hook routine
+|                    E_NOT_CONNECTED   - no items connected to menu
+|                    E_NO_MATCH        - no item matches pattern
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(int)
+set_menu_pattern(MENU * menu, const char *p)
+{
+  ITEM *matchitem;
+  int matchpos;
+
+  T((T_CALLED("set_menu_pattern(%p,%s)"), (void *)menu, _nc_visbuf(p)));
+
+  if (!menu || !p)
+    RETURN(E_BAD_ARGUMENT);
+
+  if (!(menu->items))
+    RETURN(E_NOT_CONNECTED);
+
+  if (menu->status & _IN_DRIVER)
+    RETURN(E_BAD_STATE);
+
+  Reset_Pattern(menu);
+
+  if (!(*p))
+    {
+      pos_menu_cursor(menu);
+      RETURN(E_OK);
+    }
+
+  if (menu->status & _LINK_NEEDED)
+    _nc_Link_Items(menu);
+
+  matchpos = menu->toprow;
+  matchitem = menu->curitem;
+  assert(matchitem);
+
+  while (*p)
+    {
+      if (!isprint(UChar(*p)) ||
+	  (_nc_Match_Next_Character_In_Item_Name(menu, *p, &matchitem) != E_OK))
+	{
+	  Reset_Pattern(menu);
+	  pos_menu_cursor(menu);
+	  RETURN(E_NO_MATCH);
+	}
+      p++;
+    }
+
+  /* This is reached if there was a match. So we position to the new item */
+  Adjust_Current_Item(menu, matchpos, matchitem);
+  RETURN(E_OK);
+}
+
+/* m_pattern.c ends here */
diff --git a/apps/lib/curses/pdcurses/menu/m_post.c b/apps/lib/curses/pdcurses/menu/m_post.c
new file mode 100644
index 0000000..007476b
--- /dev/null
+++ b/apps/lib/curses/pdcurses/menu/m_post.c
@@ -0,0 +1,377 @@
+/****************************************************************************
+ * Copyright (c) 1998-2009,2010 Free Software Foundation, Inc.              *
+ *                                                                          *
+ * 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, distribute with modifications, sublicense, and/or sell       *
+ * copies of the Software, and to permit persons to whom the Software is    *
+ * furnished to do so, subject to the following conditions:                 *
+ *                                                                          *
+ * The above copyright notice and this permission notice shall be included  *
+ * in all copies or substantial portions of the Software.                   *
+ *                                                                          *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
+ * IN NO EVENT SHALL THE ABOVE 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.                               *
+ *                                                                          *
+ * Except as contained in this notice, the name(s) of the above copyright   *
+ * holders shall not be used in advertising or otherwise to promote the     *
+ * sale, use or other dealings in this Software without prior written       *
+ * authorization.                                                           *
+ ****************************************************************************/
+
+/****************************************************************************
+ *   Author:  Juergen Pfeifer, 1995,1997                                    *
+ ****************************************************************************/
+
+/***************************************************************************
+* Module m_post                                                            *
+* Write or erase menus from associated subwindows                          *
+***************************************************************************/
+
+#include "menu.priv.h"
+
+MODULE_ID("$Id: m_post.c,v 1.29 2010/05/01 19:18:27 tom Exp $")
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnmenu
+|   Function      :  void _nc_Post_Item(MENU *menu, ITEM *item)
+|
+|   Description   :  Draw the item in the menus window at the current
+|                    window position
+|
+|   Return Values :  -
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(void)
+_nc_Post_Item(const MENU * menu, const ITEM * item)
+{
+  int i;
+  chtype ch;
+  int item_x, item_y;
+  int count = 0;
+  bool isfore = FALSE, isback = FALSE, isgrey = FALSE;
+  int name_len;
+  int desc_len;
+
+  assert(menu->win);
+
+  getyx(menu->win, item_y, item_x);
+
+  /* We need a marker iff
+     - it is a onevalued menu and it is the current item
+     - or it has a selection value
+   */
+  wattron(menu->win, menu->back);
+  if (item->value || (item == menu->curitem))
+    {
+      if (menu->marklen)
+	{
+	  /* In a multi selection menu we use the fore attribute
+	     for a selected marker that is not the current one.
+	     This improves visualization of the menu, because now
+	     always the 'normal' marker denotes the current
+	     item. */
+	  if (!(menu->opt & O_ONEVALUE) && item->value && item != menu->curitem)
+	    {
+	      wattron(menu->win, menu->fore);
+	      isfore = TRUE;
+	    }
+	  waddstr(menu->win, menu->mark);
+	  if (isfore)
+	    {
+	      wattron(menu->win, menu->fore);
+	      isfore = FALSE;
+	    }
+	}
+    }
+  else				/* otherwise we have to wipe out the marker area */
+    for (ch = ' ', i = menu->marklen; i > 0; i--)
+      waddch(menu->win, ch);
+  wattroff(menu->win, menu->back);
+  count += menu->marklen;
+
+  /* First we have to calculate the attribute depending on selectability
+     and selection status
+   */
+  if (!(item->opt & O_SELECTABLE))
+    {
+      wattron(menu->win, menu->grey);
+      isgrey = TRUE;
+    }
+  else
+    {
+      if (item->value || item == menu->curitem)
+	{
+	  wattron(menu->win, menu->fore);
+	  isfore = TRUE;
+	}
+      else
+	{
+	  wattron(menu->win, menu->back);
+	  isback = TRUE;
+	}
+    }
+
+  waddnstr(menu->win, item->name.str, item->name.length);
+  name_len = _nc_Calculate_Text_Width(&(item->name));
+  for (ch = ' ', i = menu->namelen - name_len; i > 0; i--)
+    {
+      waddch(menu->win, ch);
+    }
+  count += menu->namelen;
+
+  /* Show description if required and available */
+  if ((menu->opt & O_SHOWDESC) && menu->desclen > 0)
+    {
+      int m = menu->spc_desc / 2;
+      int cy = -1, cx = -1;
+
+      for (ch = ' ', i = 0; i < menu->spc_desc; i++)
+	{
+	  if (i == m)
+	    {
+	      waddch(menu->win, menu->pad);
+	      getyx(menu->win, cy, cx);
+	    }
+	  else
+	    waddch(menu->win, ch);
+	}
+      if (item->description.length)
+	waddnstr(menu->win, item->description.str, item->description.length);
+      desc_len = _nc_Calculate_Text_Width(&(item->description));
+      for (ch = ' ', i = menu->desclen - desc_len; i > 0; i--)
+	{
+	  waddch(menu->win, ch);
+	}
+      count += menu->desclen + menu->spc_desc;
+
+      if (menu->spc_rows > 1)
+	{
+	  int j, k, ncy, ncx;
+
+	  assert(cx >= 0 && cy >= 0);
+	  getyx(menu->win, ncy, ncx);
+	  if (isgrey)
+	    wattroff(menu->win, menu->grey);
+	  else if (isfore)
+	    wattroff(menu->win, menu->fore);
+	  wattron(menu->win, menu->back);
+	  for (j = 1; j < menu->spc_rows; j++)
+	    {
+	      if ((item_y + j) < getmaxy(menu->win))
+		{
+		  wmove(menu->win, item_y + j, item_x);
+		  for (k = 0; k < count; k++)
+		    waddch(menu->win, ' ');
+		}
+	      if ((cy + j) < getmaxy(menu->win))
+		(void)mvwaddch(menu->win, cy + j, cx - 1, menu->pad);
+	    }
+	  wmove(menu->win, ncy, ncx);
+	  if (!isback)
+	    wattroff(menu->win, menu->back);
+	}
+    }
+
+  /* Remove attributes */
+  if (isfore)
+    wattroff(menu->win, menu->fore);
+  if (isback)
+    wattroff(menu->win, menu->back);
+  if (isgrey)
+    wattroff(menu->win, menu->grey);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnmenu
+|   Function      :  void _nc_Draw_Menu(const MENU *)
+|
+|   Description   :  Display the menu in its windows
+|
+|   Return Values :  -
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(void)
+_nc_Draw_Menu(const MENU * menu)
+{
+  ITEM *item = menu->items[0];
+  ITEM *lasthor, *lastvert;
+  ITEM *hitem;
+  int y = 0;
+  chtype s_bkgd;
+
+  assert(item && menu->win);
+
+  s_bkgd = getbkgd(menu->win);
+  wbkgdset(menu->win, menu->back);
+  werase(menu->win);
+  wbkgdset(menu->win, s_bkgd);
+
+  lastvert = (menu->opt & O_NONCYCLIC) ? (ITEM *) 0 : item;
+
+  do
+    {
+      wmove(menu->win, y, 0);
+
+      hitem = item;
+      lasthor = (menu->opt & O_NONCYCLIC) ? (ITEM *) 0 : hitem;
+
+      do
+	{
+	  _nc_Post_Item(menu, hitem);
+
+	  wattron(menu->win, menu->back);
+	  if (((hitem = hitem->right) != lasthor) && hitem)
+	    {
+	      int i, j, cy, cx;
+	      chtype ch = ' ';
+
+	      getyx(menu->win, cy, cx);
+	      for (j = 0; j < menu->spc_rows; j++)
+		{
+		  wmove(menu->win, cy + j, cx);
+		  for (i = 0; i < menu->spc_cols; i++)
+		    {
+		      waddch(menu->win, ch);
+		    }
+		}
+	      wmove(menu->win, cy, cx + menu->spc_cols);
+	    }
+	}
+      while (hitem && (hitem != lasthor));
+      wattroff(menu->win, menu->back);
+
+      item = item->down;
+      y += menu->spc_rows;
+
+    }
+  while (item && (item != lastvert));
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnmenu
+|   Function      :  int post_menu(MENU* menu)
+|
+|   Description   :  Post a menu to the screen. This makes it visible.
+|
+|   Return Values :  E_OK                - success
+|                    E_BAD_ARGUMENT      - not a valid menu pointer
+|                    E_SYSTEM_ERROR      - error in lower layers
+|                    E_NOT_CONNECTED     - No items connected to menu
+|                    E_BAD_STATE         - Menu in userexit routine
+|                    E_POSTED            - Menu already posted
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(int)
+post_menu(MENU * menu)
+{
+  T((T_CALLED("post_menu(%p)"), (void *)menu));
+
+  if (!menu)
+    RETURN(E_BAD_ARGUMENT);
+
+  if (menu->status & _IN_DRIVER)
+    RETURN(E_BAD_STATE);
+
+  if (menu->status & _POSTED)
+    RETURN(E_POSTED);
+
+  if (menu->items && *(menu->items))
+    {
+      int y;
+      int h = 1 + menu->spc_rows * (menu->rows - 1);
+
+      WINDOW *win = Get_Menu_Window(menu);
+      int maxy = getmaxy(win);
+
+      if ((menu->win = newpad(h+2, menu->width+2)))
+	{
+	  y = (maxy >= h) ? h : maxy;
+	  if (y >= menu->height)
+	    y = menu->height;
+	  if (!(menu->sub = subpad(menu->win, y, menu->width, 0, 0)))
+	    RETURN(E_SYSTEM_ERROR);
+	}
+      else
+	RETURN(E_SYSTEM_ERROR);
+
+      if (menu->status & _LINK_NEEDED)
+	_nc_Link_Items(menu);
+    }
+  else
+    RETURN(E_NOT_CONNECTED);
+
+  menu->status |= _POSTED;
+
+  if (!(menu->opt & O_ONEVALUE))
+    {
+      ITEM **items;
+
+      for (items = menu->items; *items; items++)
+	{
+	  (*items)->value = FALSE;
+	}
+    }
+
+  _nc_Draw_Menu(menu);
+
+  Call_Hook(menu, menuinit);
+  Call_Hook(menu, iteminit);
+
+  _nc_Show_Menu(menu);
+
+  RETURN(E_OK);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnmenu
+|   Function      :  int unpost_menu(MENU*)
+|
+|   Description   :  Detach menu from screen
+|
+|   Return Values :  E_OK              - success
+|                    E_BAD_ARGUMENT    - not a valid menu pointer
+|                    E_BAD_STATE       - menu in userexit routine
+|                    E_NOT_POSTED      - menu is not posted
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(int)
+unpost_menu(MENU * menu)
+{
+  WINDOW *win;
+
+  T((T_CALLED("unpost_menu(%p)"), (void *)menu));
+
+  if (!menu)
+    RETURN(E_BAD_ARGUMENT);
+
+  if (menu->status & _IN_DRIVER)
+    RETURN(E_BAD_STATE);
+
+  if (!(menu->status & _POSTED))
+    RETURN(E_NOT_POSTED);
+
+  Call_Hook(menu, itemterm);
+  Call_Hook(menu, menuterm);
+
+  win = Get_Menu_Window(menu);
+  werase(win);
+  wsyncup(win);
+
+  assert(menu->sub);
+  delwin(menu->sub);
+  menu->sub = (WINDOW *)0;
+
+  assert(menu->win);
+  delwin(menu->win);
+  menu->win = (WINDOW *)0;
+
+  menu->status &= ~_POSTED;
+
+  RETURN(E_OK);
+}
+
+/* m_post.c ends here */
diff --git a/apps/lib/curses/pdcurses/menu/m_req_name.c b/apps/lib/curses/pdcurses/menu/m_req_name.c
new file mode 100644
index 0000000..50c0c68
--- /dev/null
+++ b/apps/lib/curses/pdcurses/menu/m_req_name.c
@@ -0,0 +1,125 @@
+/****************************************************************************
+ * Copyright (c) 1998-2008,2009 Free Software Foundation, Inc.              *
+ *                                                                          *
+ * 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, distribute with modifications, sublicense, and/or sell       *
+ * copies of the Software, and to permit persons to whom the Software is    *
+ * furnished to do so, subject to the following conditions:                 *
+ *                                                                          *
+ * The above copyright notice and this permission notice shall be included  *
+ * in all copies or substantial portions of the Software.                   *
+ *                                                                          *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
+ * IN NO EVENT SHALL THE ABOVE 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.                               *
+ *                                                                          *
+ * Except as contained in this notice, the name(s) of the above copyright   *
+ * holders shall not be used in advertising or otherwise to promote the     *
+ * sale, use or other dealings in this Software without prior written       *
+ * authorization.                                                           *
+ ****************************************************************************/
+
+/****************************************************************************
+ *   Author:  Juergen Pfeifer, 1995,1997                                    *
+ ****************************************************************************/
+
+/***************************************************************************
+* Module m_request_name                                                    *
+* Routines to handle external names of menu requests                       *
+***************************************************************************/
+
+#include "menu.priv.h"
+
+MODULE_ID("$Id: m_req_name.c,v 1.21 2009/10/10 16:17:23 tom Exp $")
+
+static const char *request_names[MAX_MENU_COMMAND - MIN_MENU_COMMAND + 1] =
+{
+  "LEFT_ITEM",
+  "RIGHT_ITEM",
+  "UP_ITEM",
+  "DOWN_ITEM",
+  "SCR_ULINE",
+  "SCR_DLINE",
+  "SCR_DPAGE",
+  "SCR_UPAGE",
+  "FIRST_ITEM",
+  "LAST_ITEM",
+  "NEXT_ITEM",
+  "PREV_ITEM",
+  "TOGGLE_ITEM",
+  "CLEAR_PATTERN",
+  "BACK_PATTERN",
+  "NEXT_MATCH",
+  "PREV_MATCH"
+};
+
+#define A_SIZE (sizeof(request_names)/sizeof(request_names[0]))
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnmenu
+|   Function      :  const char * menu_request_name (int request);
+|
+|   Description   :  Get the external name of a menu request.
+|
+|   Return Values :  Pointer to name      - on success
+|                    NULL                 - on invalid request code
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(const char *)
+menu_request_name(int request)
+{
+  T((T_CALLED("menu_request_name(%d)"), request));
+  if ((request < MIN_MENU_COMMAND) || (request > MAX_MENU_COMMAND))
+    {
+      SET_ERROR(E_BAD_ARGUMENT);
+      returnCPtr((const char *)0);
+    }
+  else
+    returnCPtr(request_names[request - MIN_MENU_COMMAND]);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnmenu
+|   Function      :  int menu_request_by_name (const char *str);
+|
+|   Description   :  Search for a request with this name.
+|
+|   Return Values :  Request Id       - on success
+|                    E_NO_MATCH       - request not found
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(int)
+menu_request_by_name(const char *str)
+{
+  /* because the table is so small, it doesn't really hurt
+     to run sequentially through it.
+   */
+  unsigned int i = 0;
+  char buf[16];
+
+  T((T_CALLED("menu_request_by_name(%s)"), _nc_visbuf(str)));
+
+  if (str)
+    {
+      strncpy(buf, str, sizeof(buf));
+      while ((i < sizeof(buf)) && (buf[i] != '\0'))
+	{
+	  buf[i] = (char)toupper(UChar(buf[i]));
+	  i++;
+	}
+
+      for (i = 0; i < A_SIZE; i++)
+	{
+	  if (strncmp(request_names[i], buf, sizeof(buf)) == 0)
+	    returnCode(MIN_MENU_COMMAND + (int)i);
+	}
+    }
+  RETURN(E_NO_MATCH);
+}
+
+/* m_req_name.c ends here */
diff --git a/apps/lib/curses/pdcurses/menu/m_scale.c b/apps/lib/curses/pdcurses/menu/m_scale.c
new file mode 100644
index 0000000..26a560e
--- /dev/null
+++ b/apps/lib/curses/pdcurses/menu/m_scale.c
@@ -0,0 +1,76 @@
+/****************************************************************************
+ * Copyright (c) 1998-2004,2010 Free Software Foundation, Inc.              *
+ *                                                                          *
+ * 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, distribute with modifications, sublicense, and/or sell       *
+ * copies of the Software, and to permit persons to whom the Software is    *
+ * furnished to do so, subject to the following conditions:                 *
+ *                                                                          *
+ * The above copyright notice and this permission notice shall be included  *
+ * in all copies or substantial portions of the Software.                   *
+ *                                                                          *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
+ * IN NO EVENT SHALL THE ABOVE 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.                               *
+ *                                                                          *
+ * Except as contained in this notice, the name(s) of the above copyright   *
+ * holders shall not be used in advertising or otherwise to promote the     *
+ * sale, use or other dealings in this Software without prior written       *
+ * authorization.                                                           *
+ ****************************************************************************/
+
+/****************************************************************************
+ *   Author:  Juergen Pfeifer, 1995,1997                                    *
+ ****************************************************************************/
+
+/***************************************************************************
+* Module m_scale                                                           *
+* Menu scaling routine                                                     *
+***************************************************************************/
+
+#include "menu.priv.h"
+
+MODULE_ID("$Id: m_scale.c,v 1.10 2010/01/23 21:20:10 tom Exp $")
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnmenu
+|   Function      :  int scale_menu(const MENU *menu)
+|
+|   Description   :  Returns the minimum window size necessary for the
+|                    subwindow of menu.
+|
+|   Return Values :  E_OK                  - success
+|                    E_BAD_ARGUMENT        - invalid menu pointer
+|                    E_NOT_CONNECTED       - no items are connected to menu
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(int)
+scale_menu(const MENU * menu, int *rows, int *cols)
+{
+  T((T_CALLED("scale_menu(%p,%p,%p)"),
+     (const void *)menu,
+     (void *)rows,
+     (void *)cols));
+
+  if (!menu)
+    RETURN(E_BAD_ARGUMENT);
+
+  if (menu->items && *(menu->items))
+    {
+      if (rows)
+	*rows = menu->height;
+      if (cols)
+	*cols = menu->width;
+      RETURN(E_OK);
+    }
+  else
+    RETURN(E_NOT_CONNECTED);
+}
+
+/* m_scale.c ends here */
diff --git a/apps/lib/curses/pdcurses/menu/m_spacing.c b/apps/lib/curses/pdcurses/menu/m_spacing.c
new file mode 100644
index 0000000..1cfa2e1
--- /dev/null
+++ b/apps/lib/curses/pdcurses/menu/m_spacing.c
@@ -0,0 +1,113 @@
+/****************************************************************************
+ * Copyright (c) 1998-2004,2010 Free Software Foundation, Inc.              *
+ *                                                                          *
+ * 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, distribute with modifications, sublicense, and/or sell       *
+ * copies of the Software, and to permit persons to whom the Software is    *
+ * furnished to do so, subject to the following conditions:                 *
+ *                                                                          *
+ * The above copyright notice and this permission notice shall be included  *
+ * in all copies or substantial portions of the Software.                   *
+ *                                                                          *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
+ * IN NO EVENT SHALL THE ABOVE 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.                               *
+ *                                                                          *
+ * Except as contained in this notice, the name(s) of the above copyright   *
+ * holders shall not be used in advertising or otherwise to promote the     *
+ * sale, use or other dealings in this Software without prior written       *
+ * authorization.                                                           *
+ ****************************************************************************/
+
+/****************************************************************************
+ *   Author:  Juergen Pfeifer, 1995,1997                                    *
+ ****************************************************************************/
+
+/***************************************************************************
+* Module m_spacing                                                         *
+* Routines to handle spacing between entries                               *
+***************************************************************************/
+
+#include "menu.priv.h"
+
+MODULE_ID("$Id: m_spacing.c,v 1.18 2010/01/23 21:20:10 tom Exp $")
+
+#define MAX_SPC_DESC ((TABSIZE) ? (TABSIZE) : 8)
+#define MAX_SPC_COLS ((TABSIZE) ? (TABSIZE) : 8)
+#define MAX_SPC_ROWS (3)
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnmenu
+|   Function      :  int set_menu_spacing(MENU *menu,int desc, int r, int c);
+|
+|   Description   :  Set the spacing between entries
+|
+|   Return Values :  E_OK                 - on success
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(int)
+set_menu_spacing(MENU * menu, int s_desc, int s_row, int s_col)
+{
+  MENU *m;			/* split for ATAC workaround */
+
+  T((T_CALLED("set_menu_spacing(%p,%d,%d,%d)"),
+     (void *)menu, s_desc, s_row, s_col));
+
+  m = Normalize_Menu(menu);
+
+  assert(m);
+  if (m->status & _POSTED)
+    RETURN(E_POSTED);
+
+  if (((s_desc < 0) || (s_desc > MAX_SPC_DESC)) ||
+      ((s_row < 0) || (s_row > MAX_SPC_ROWS)) ||
+      ((s_col < 0) || (s_col > MAX_SPC_COLS)))
+    RETURN(E_BAD_ARGUMENT);
+
+  m->spc_desc = s_desc ? s_desc : 1;
+  m->spc_rows = s_row ? s_row : 1;
+  m->spc_cols = s_col ? s_col : 1;
+  _nc_Calculate_Item_Length_and_Width(m);
+
+  RETURN(E_OK);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnmenu
+|   Function      :  int menu_spacing (const MENU *,int *,int *,int *);
+|
+|   Description   :  Retrieve info about spacing between the entries
+|
+|   Return Values :  E_OK             - on success
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(int)
+menu_spacing(const MENU * menu, int *s_desc, int *s_row, int *s_col)
+{
+  const MENU *m;		/* split for ATAC workaround */
+
+  T((T_CALLED("menu_spacing(%p,%p,%p,%p)"),
+     (const void *)menu,
+     (void *)s_desc,
+     (void *)s_row,
+     (void *)s_col));
+
+  m = Normalize_Menu(menu);
+
+  assert(m);
+  if (s_desc)
+    *s_desc = m->spc_desc;
+  if (s_row)
+    *s_row = m->spc_rows;
+  if (s_col)
+    *s_col = m->spc_cols;
+
+  RETURN(E_OK);
+}
+
+/* m_spacing.c ends here */
diff --git a/apps/lib/curses/pdcurses/menu/m_sub.c b/apps/lib/curses/pdcurses/menu/m_sub.c
new file mode 100644
index 0000000..4bb373f
--- /dev/null
+++ b/apps/lib/curses/pdcurses/menu/m_sub.c
@@ -0,0 +1,100 @@
+/****************************************************************************
+ * Copyright (c) 1998-2004,2010 Free Software Foundation, Inc.              *
+ *                                                                          *
+ * 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, distribute with modifications, sublicense, and/or sell       *
+ * copies of the Software, and to permit persons to whom the Software is    *
+ * furnished to do so, subject to the following conditions:                 *
+ *                                                                          *
+ * The above copyright notice and this permission notice shall be included  *
+ * in all copies or substantial portions of the Software.                   *
+ *                                                                          *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
+ * IN NO EVENT SHALL THE ABOVE 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.                               *
+ *                                                                          *
+ * Except as contained in this notice, the name(s) of the above copyright   *
+ * holders shall not be used in advertising or otherwise to promote the     *
+ * sale, use or other dealings in this Software without prior written       *
+ * authorization.                                                           *
+ ****************************************************************************/
+
+/****************************************************************************
+ *   Author:  Juergen Pfeifer, 1995,1997                                    *
+ ****************************************************************************/
+
+/***************************************************************************
+* Module m_sub                                                             *
+* Menus subwindow association routines                                     *
+***************************************************************************/
+
+#include "menu.priv.h"
+
+MODULE_ID("$Id: m_sub.c,v 1.12 2010/01/23 21:20:11 tom Exp $")
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnmenu
+|   Function      :  int set_menu_sub(MENU *menu, WINDOW *win)
+|
+|   Description   :  Sets the subwindow of the menu.
+|
+|   Return Values :  E_OK           - success
+|                    E_POSTED       - menu is already posted
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(int)
+set_menu_sub(MENU * menu, WINDOW *win)
+{
+  T((T_CALLED("set_menu_sub(%p,%p)"), (void *)menu, (void *)win));
+
+  if (menu)
+    {
+      if (menu->status & _POSTED)
+	RETURN(E_POSTED);
+      else
+#if NCURSES_SP_FUNCS
+	{
+	  /* We ensure that usersub is never null. So even if a null
+	     WINDOW parameter is passed, we store the SCREENS stdscr.
+	     The only MENU that can have a null usersub is the static
+	     _nc_default_Menu.
+	   */
+	  SCREEN *sp = _nc_screen_of(menu->usersub);
+
+	  menu->usersub = win ? win : stdscr;
+	  _nc_Calculate_Item_Length_and_Width(menu);
+	}
+#else
+	menu->usersub = win;
+#endif
+    }
+  else
+    _nc_Default_Menu.usersub = win;
+
+  RETURN(E_OK);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnmenu
+|   Function      :  WINDOW* menu_sub(const MENU *menu)
+|
+|   Description   :  Returns a pointer to the subwindow of the menu
+|
+|   Return Values :  NULL on error, otherwise a pointer to the window
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(WINDOW *)
+menu_sub(const MENU * menu)
+{
+  const MENU *m = Normalize_Menu(menu);
+
+  T((T_CALLED("menu_sub(%p)"), (const void *)menu));
+  returnWin(Get_Menu_Window(m));
+}
+
+/* m_sub.c ends here */
diff --git a/apps/lib/curses/pdcurses/menu/m_trace.c b/apps/lib/curses/pdcurses/menu/m_trace.c
new file mode 100644
index 0000000..094ff86
--- /dev/null
+++ b/apps/lib/curses/pdcurses/menu/m_trace.c
@@ -0,0 +1,77 @@
+/****************************************************************************
+ * Copyright (c) 2004-2005,2010 Free Software Foundation, Inc.              *
+ *                                                                          *
+ * 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, distribute with modifications, sublicense, and/or sell       *
+ * copies of the Software, and to permit persons to whom the Software is    *
+ * furnished to do so, subject to the following conditions:                 *
+ *                                                                          *
+ * The above copyright notice and this permission notice shall be included  *
+ * in all copies or substantial portions of the Software.                   *
+ *                                                                          *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
+ * IN NO EVENT SHALL THE ABOVE 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.                               *
+ *                                                                          *
+ * Except as contained in this notice, the name(s) of the above copyright   *
+ * holders shall not be used in advertising or otherwise to promote the     *
+ * sale, use or other dealings in this Software without prior written       *
+ * authorization.                                                           *
+ ****************************************************************************/
+
+/****************************************************************************
+ *   Author:  Thomas E. Dickey                                              *
+ ****************************************************************************/
+
+#include "menu.priv.h"
+
+MODULE_ID("$Id: m_trace.c,v 1.4 2010/01/23 21:20:10 tom Exp $")
+
+NCURSES_EXPORT(ITEM *)
+_nc_retrace_item(ITEM * code)
+{
+  T((T_RETURN("%p"), (void *)code));
+  return code;
+}
+
+NCURSES_EXPORT(ITEM **)
+_nc_retrace_item_ptr(ITEM ** code)
+{
+  T((T_RETURN("%p"), (void *)code));
+  return code;
+}
+
+NCURSES_EXPORT(Item_Options)
+_nc_retrace_item_opts(Item_Options code)
+{
+  T((T_RETURN("%d"), code));
+  return code;
+}
+
+NCURSES_EXPORT(MENU *)
+_nc_retrace_menu(MENU * code)
+{
+  T((T_RETURN("%p"), (void *)code));
+  return code;
+}
+
+NCURSES_EXPORT(Menu_Hook)
+_nc_retrace_menu_hook(Menu_Hook code)
+{
+  T((T_RETURN("%p"), code));
+  return code;
+}
+
+NCURSES_EXPORT(Menu_Options)
+_nc_retrace_menu_opts(Menu_Options code)
+{
+  T((T_RETURN("%d"), code));
+  return code;
+}
diff --git a/apps/lib/curses/pdcurses/menu/m_userptr.c b/apps/lib/curses/pdcurses/menu/m_userptr.c
new file mode 100644
index 0000000..67d6ecd
--- /dev/null
+++ b/apps/lib/curses/pdcurses/menu/m_userptr.c
@@ -0,0 +1,76 @@
+/****************************************************************************
+ * Copyright (c) 1998-2004,2010 Free Software Foundation, Inc.              *
+ *                                                                          *
+ * 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, distribute with modifications, sublicense, and/or sell       *
+ * copies of the Software, and to permit persons to whom the Software is    *
+ * furnished to do so, subject to the following conditions:                 *
+ *                                                                          *
+ * The above copyright notice and this permission notice shall be included  *
+ * in all copies or substantial portions of the Software.                   *
+ *                                                                          *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
+ * IN NO EVENT SHALL THE ABOVE 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.                               *
+ *                                                                          *
+ * Except as contained in this notice, the name(s) of the above copyright   *
+ * holders shall not be used in advertising or otherwise to promote the     *
+ * sale, use or other dealings in this Software without prior written       *
+ * authorization.                                                           *
+ ****************************************************************************/
+
+/****************************************************************************
+ *   Author:  Juergen Pfeifer, 1995,1997                                    *
+ ****************************************************************************/
+
+/***************************************************************************
+* Module m_userptr                                                         *
+* Associate application data with menus                                    *
+***************************************************************************/
+
+#include "menu.priv.h"
+
+MODULE_ID("$Id: m_userptr.c,v 1.17 2010/01/23 21:20:10 tom Exp $")
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnmenu
+|   Function      :  int set_menu_userptr(MENU *menu, void *userptr)
+|
+|   Description   :  Set the pointer that is reserved in any menu to store
+|                    application relevant informations.
+|
+|   Return Values :  E_OK         - success
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(int)
+set_menu_userptr(MENU * menu, void *userptr)
+{
+  T((T_CALLED("set_menu_userptr(%p,%p)"), (void *)menu, (void *)userptr));
+  Normalize_Menu(menu)->userptr = userptr;
+  RETURN(E_OK);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnmenu
+|   Function      :  void *menu_userptr(const MENU *menu)
+|
+|   Description   :  Return the pointer that is reserved in any menu to
+|                    store application relevant informations.
+|
+|   Return Values :  Value of the pointer. If no such pointer has been set,
+|                    NULL is returned
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(void *)
+menu_userptr(const MENU * menu)
+{
+  T((T_CALLED("menu_userptr(%p)"), (const void *)menu));
+  returnVoidPtr(Normalize_Menu(menu)->userptr);
+}
+
+/* m_userptr.c ends here */
diff --git a/apps/lib/curses/pdcurses/menu/m_win.c b/apps/lib/curses/pdcurses/menu/m_win.c
new file mode 100644
index 0000000..d025c1b
--- /dev/null
+++ b/apps/lib/curses/pdcurses/menu/m_win.c
@@ -0,0 +1,100 @@
+/****************************************************************************
+ * Copyright (c) 1998-2004,2010 Free Software Foundation, Inc.              *
+ *                                                                          *
+ * 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, distribute with modifications, sublicense, and/or sell       *
+ * copies of the Software, and to permit persons to whom the Software is    *
+ * furnished to do so, subject to the following conditions:                 *
+ *                                                                          *
+ * The above copyright notice and this permission notice shall be included  *
+ * in all copies or substantial portions of the Software.                   *
+ *                                                                          *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
+ * IN NO EVENT SHALL THE ABOVE 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.                               *
+ *                                                                          *
+ * Except as contained in this notice, the name(s) of the above copyright   *
+ * holders shall not be used in advertising or otherwise to promote the     *
+ * sale, use or other dealings in this Software without prior written       *
+ * authorization.                                                           *
+ ****************************************************************************/
+
+/****************************************************************************
+ *   Author:  Juergen Pfeifer, 1995,1997                                    *
+ ****************************************************************************/
+
+/***************************************************************************
+* Module m_win                                                             *
+* Menus window association routines                                        *
+***************************************************************************/
+
+#include "menu.priv.h"
+
+MODULE_ID("$Id: m_win.c,v 1.17 2010/01/23 21:20:11 tom Exp $")
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnmenu
+|   Function      :  int set_menu_win(MENU *menu, WINDOW *win)
+|
+|   Description   :  Sets the window of the menu.
+|
+|   Return Values :  E_OK               - success
+|                    E_POSTED           - menu is already posted
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(int)
+set_menu_win(MENU * menu, WINDOW *win)
+{
+  T((T_CALLED("set_menu_win(%p,%p)"), (void *)menu, (void *)win));
+
+  if (menu)
+    {
+      if (menu->status & _POSTED)
+	RETURN(E_POSTED);
+      else
+#if NCURSES_SP_FUNCS
+	{
+	  /* We ensure that userwin is never null. So even if a null
+	     WINDOW parameter is passed, we store the SCREENS stdscr.
+	     The only MENU that can have a null userwin is the static
+	     _nc_default_Menu.
+	   */
+	  SCREEN *sp = _nc_screen_of(menu->userwin);
+
+	  menu->userwin = win ? win : stdscr;
+	  _nc_Calculate_Item_Length_and_Width(menu);
+	}
+#else
+	menu->userwin = win;
+#endif
+    }
+  else
+    _nc_Default_Menu.userwin = win;
+
+  RETURN(E_OK);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnmenu
+|   Function      :  WINDOW* menu_win(const MENU*)
+|
+|   Description   :  Returns pointer to the window of the menu
+|
+|   Return Values :  NULL on error, otherwise pointer to window
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(WINDOW *)
+menu_win(const MENU * menu)
+{
+  const MENU *m = Normalize_Menu(menu);
+
+  T((T_CALLED("menu_win(%p)"), (const void *)menu));
+  returnWin(Get_Menu_UserWin(m));
+}
+
+/* m_win.c ends here */
diff --git a/apps/lib/curses/pdcurses/menu/menu.h b/apps/lib/curses/pdcurses/menu/menu.h
new file mode 100644
index 0000000..1fdd9e7
--- /dev/null
+++ b/apps/lib/curses/pdcurses/menu/menu.h
@@ -0,0 +1,261 @@
+/****************************************************************************
+ * Copyright (c) 1998-2007,2009 Free Software Foundation, Inc.              *
+ *                                                                          *
+ * 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, distribute with modifications, sublicense, and/or sell       *
+ * copies of the Software, and to permit persons to whom the Software is    *
+ * furnished to do so, subject to the following conditions:                 *
+ *                                                                          *
+ * The above copyright notice and this permission notice shall be included  *
+ * in all copies or substantial portions of the Software.                   *
+ *                                                                          *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
+ * IN NO EVENT SHALL THE ABOVE 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.                               *
+ *                                                                          *
+ * Except as contained in this notice, the name(s) of the above copyright   *
+ * holders shall not be used in advertising or otherwise to promote the     *
+ * sale, use or other dealings in this Software without prior written       *
+ * authorization.                                                           *
+ ****************************************************************************/
+
+/****************************************************************************
+ *   Author:  Juergen Pfeifer, 1995,1997                                    *
+ ****************************************************************************/
+
+/* $Id: menu.h,v 1.20 2009/04/05 00:28:07 tom Exp $ */
+
+#ifndef ETI_MENU
+#define ETI_MENU
+
+#ifdef AMIGA
+#define TEXT TEXT_ncurses
+#endif
+
+#include <curses.h>
+#include <eti.h>
+#include <ncurses_cfg.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef int Menu_Options;
+typedef int Item_Options;
+
+/* Menu options: */
+#define O_ONEVALUE      (0x01)
+#define O_SHOWDESC      (0x02)
+#define O_ROWMAJOR      (0x04)
+#define O_IGNORECASE    (0x08)
+#define O_SHOWMATCH     (0x10)
+#define O_NONCYCLIC     (0x20)
+
+/* Item options: */
+#define O_SELECTABLE    (0x01)
+
+typedef struct
+{
+  const char* str;
+  unsigned short length;
+} TEXT;
+
+typedef struct tagITEM
+{
+  TEXT           name;        /* name of menu item                         */
+  TEXT           description; /* description of item, optional in display  */
+  struct tagMENU *imenu;      /* Pointer to parent menu                    */
+  void           *userptr;    /* Pointer to user defined per item data     */
+  Item_Options   opt;         /* Item options                              */
+  short          index;       /* Item number if connected to a menu        */
+  short          y;           /* y and x location of item in menu          */
+  short          x;
+  bool           value;       /* Selection value                           */
+
+  struct tagITEM *left;       /* neighbor items                            */
+  struct tagITEM *right;
+  struct tagITEM *up;
+  struct tagITEM *down;
+
+} ITEM;
+
+typedef void (*Menu_Hook)(struct tagMENU *);
+
+typedef struct tagMENU
+{
+  short          height;                /* Nr. of chars high               */
+  short          width;                 /* Nr. of chars wide               */
+  short          rows;                  /* Nr. of items high               */
+  short          cols;                  /* Nr. of items wide               */
+  short          frows;                 /* Nr. of formatted items high     */
+  short          fcols;                 /* Nr. of formatted items wide     */
+  short          arows;                 /* Nr. of items high (actual)      */
+  short          namelen;               /* Max. name length                */
+  short          desclen;               /* Max. description length         */
+  short          marklen;               /* Length of mark, if any          */
+  short          itemlen;               /* Length of one item              */
+  short          spc_desc;              /* Spacing for descriptor          */
+  short          spc_cols;              /* Spacing for columns             */
+  short          spc_rows;              /* Spacing for rows                */
+  char          *pattern;               /* Buffer to store match chars     */
+  short          pindex;                /* Index into pattern buffer       */
+  WINDOW        *win;                   /* Window containing menu          */
+  WINDOW        *sub;                   /* Subwindow for menu display      */
+  WINDOW        *userwin;               /* User's window                   */
+  WINDOW        *usersub;               /* User's subwindow                */
+  ITEM          **items;                /* array of items                  */
+  short          nitems;                /* Nr. of items in menu            */
+  ITEM          *curitem;               /* Current item                    */
+  short          toprow;                /* Top row of menu                 */
+  chtype         fore;                  /* Selection attribute             */
+  chtype         back;                  /* Nonselection attribute          */
+  chtype         grey;                  /* Inactive attribute              */
+  unsigned char  pad;                   /* Pad character                   */
+
+  Menu_Hook      menuinit;              /* User hooks                      */
+  Menu_Hook      menuterm;
+  Menu_Hook      iteminit;
+  Menu_Hook      itemterm;
+
+  void          *userptr;               /* Pointer to menus user data      */
+  char          *mark;                  /* Pointer to marker string        */
+
+  Menu_Options   opt;                   /* Menu options                    */
+  unsigned short status;                /* Internal state of menu          */
+
+} MENU;
+
+
+/* Define keys */
+
+#define REQ_LEFT_ITEM           (KEY_MAX + 1)
+#define REQ_RIGHT_ITEM          (KEY_MAX + 2)
+#define REQ_UP_ITEM             (KEY_MAX + 3)
+#define REQ_DOWN_ITEM           (KEY_MAX + 4)
+#define REQ_SCR_ULINE           (KEY_MAX + 5)
+#define REQ_SCR_DLINE           (KEY_MAX + 6)
+#define REQ_SCR_DPAGE           (KEY_MAX + 7)
+#define REQ_SCR_UPAGE           (KEY_MAX + 8)
+#define REQ_FIRST_ITEM          (KEY_MAX + 9)
+#define REQ_LAST_ITEM           (KEY_MAX + 10)
+#define REQ_NEXT_ITEM           (KEY_MAX + 11)
+#define REQ_PREV_ITEM           (KEY_MAX + 12)
+#define REQ_TOGGLE_ITEM         (KEY_MAX + 13)
+#define REQ_CLEAR_PATTERN       (KEY_MAX + 14)
+#define REQ_BACK_PATTERN        (KEY_MAX + 15)
+#define REQ_NEXT_MATCH          (KEY_MAX + 16)
+#define REQ_PREV_MATCH          (KEY_MAX + 17)
+
+#define MIN_MENU_COMMAND        (KEY_MAX + 1)
+#define MAX_MENU_COMMAND        (KEY_MAX + 17)
+
+/*
+ * Some AT&T code expects MAX_COMMAND to be out-of-band not
+ * just for menu commands but for forms ones as well.
+ */
+#if defined(MAX_COMMAND)
+#  if (MAX_MENU_COMMAND > MAX_COMMAND)
+#    error Something is wrong -- MAX_MENU_COMMAND is greater than MAX_COMMAND
+#  elif (MAX_COMMAND != (KEY_MAX + 128))
+#    error Something is wrong -- MAX_COMMAND is already inconsistently defined.
+#  endif
+#else
+#  define MAX_COMMAND (KEY_MAX + 128)
+#endif
+
+
+/* --------- prototypes for libmenu functions ----------------------------- */
+
+extern NCURSES_EXPORT(ITEM **)	menu_items (const MENU *);
+extern NCURSES_EXPORT(ITEM *)	current_item (const MENU *);
+extern NCURSES_EXPORT(ITEM *)	new_item (const char *,const char *);
+
+extern NCURSES_EXPORT(MENU *)	new_menu (ITEM **);
+
+extern NCURSES_EXPORT(Item_Options)	item_opts (const ITEM *);
+extern NCURSES_EXPORT(Menu_Options)	menu_opts (const MENU *);
+
+extern NCURSES_EXPORT(Menu_Hook)	item_init (const MENU *);
+extern NCURSES_EXPORT(Menu_Hook)	item_term (const MENU *);
+extern NCURSES_EXPORT(Menu_Hook)	menu_init (const MENU *);
+extern NCURSES_EXPORT(Menu_Hook)	menu_term (const MENU *);
+
+extern NCURSES_EXPORT(WINDOW *)	menu_sub (const MENU *);
+extern NCURSES_EXPORT(WINDOW *)	menu_win (const MENU *);
+
+extern NCURSES_EXPORT(const char *)	item_description (const ITEM *);
+extern NCURSES_EXPORT(const char *)	item_name (const ITEM *);
+extern NCURSES_EXPORT(const char *)	menu_mark (const MENU *);
+extern NCURSES_EXPORT(const char *)	menu_request_name (int);
+
+extern NCURSES_EXPORT(char *)	menu_pattern (const MENU *);
+
+extern NCURSES_EXPORT(void *)	menu_userptr (const MENU *);
+extern NCURSES_EXPORT(void *)	item_userptr (const ITEM *);
+
+extern NCURSES_EXPORT(chtype)	menu_back (const MENU *);
+extern NCURSES_EXPORT(chtype)	menu_fore (const MENU *);
+extern NCURSES_EXPORT(chtype)	menu_grey (const MENU *);
+
+extern NCURSES_EXPORT(int)	free_item (ITEM *);
+extern NCURSES_EXPORT(int)	free_menu (MENU *);
+extern NCURSES_EXPORT(int)	item_count (const MENU *);
+extern NCURSES_EXPORT(int)	item_index (const ITEM *);
+extern NCURSES_EXPORT(int)	item_opts_off (ITEM *,Item_Options);
+extern NCURSES_EXPORT(int)	item_opts_on (ITEM *,Item_Options);
+extern NCURSES_EXPORT(int)	menu_driver (MENU *,int);
+extern NCURSES_EXPORT(int)	menu_opts_off (MENU *,Menu_Options);
+extern NCURSES_EXPORT(int)	menu_opts_on (MENU *,Menu_Options);
+extern NCURSES_EXPORT(int)	menu_pad (const MENU *);
+extern NCURSES_EXPORT(int)	pos_menu_cursor (const MENU *);
+extern NCURSES_EXPORT(int)	post_menu (MENU *);
+extern NCURSES_EXPORT(int)	scale_menu (const MENU *,int *,int *);
+extern NCURSES_EXPORT(int)	set_current_item (MENU *menu,ITEM *item);
+extern NCURSES_EXPORT(int)	set_item_init (MENU *, Menu_Hook);
+extern NCURSES_EXPORT(int)	set_item_opts (ITEM *,Item_Options);
+extern NCURSES_EXPORT(int)	set_item_term (MENU *, Menu_Hook);
+extern NCURSES_EXPORT(int)	set_item_userptr (ITEM *, void *);
+extern NCURSES_EXPORT(int)	set_item_value (ITEM *,bool);
+extern NCURSES_EXPORT(int)	set_menu_back (MENU *,chtype);
+extern NCURSES_EXPORT(int)	set_menu_fore (MENU *,chtype);
+extern NCURSES_EXPORT(int)	set_menu_format (MENU *,int,int);
+extern NCURSES_EXPORT(int)	set_menu_grey (MENU *,chtype);
+extern NCURSES_EXPORT(int)	set_menu_init (MENU *, Menu_Hook);
+extern NCURSES_EXPORT(int)	set_menu_items (MENU *,ITEM **);
+extern NCURSES_EXPORT(int)	set_menu_mark (MENU *, const char *);
+extern NCURSES_EXPORT(int)	set_menu_opts (MENU *,Menu_Options);
+extern NCURSES_EXPORT(int)	set_menu_pad (MENU *,int);
+extern NCURSES_EXPORT(int)	set_menu_pattern (MENU *,const char *);
+extern NCURSES_EXPORT(int)	set_menu_sub (MENU *,WINDOW *);
+extern NCURSES_EXPORT(int)	set_menu_term (MENU *, Menu_Hook);
+extern NCURSES_EXPORT(int)	set_menu_userptr (MENU *,void *);
+extern NCURSES_EXPORT(int)	set_menu_win (MENU *,WINDOW *);
+extern NCURSES_EXPORT(int)	set_top_row (MENU *,int);
+extern NCURSES_EXPORT(int)	top_row (const MENU *);
+extern NCURSES_EXPORT(int)	unpost_menu (MENU *);
+extern NCURSES_EXPORT(int)	menu_request_by_name (const char *);
+extern NCURSES_EXPORT(int)	set_menu_spacing (MENU *,int,int,int);
+extern NCURSES_EXPORT(int)	menu_spacing (const MENU *,int *,int *,int *);
+
+
+extern NCURSES_EXPORT(bool)	item_value (const ITEM *);
+extern NCURSES_EXPORT(bool)	item_visible (const ITEM *);
+
+extern NCURSES_EXPORT(void)	menu_format (const MENU *,int *,int *);
+
+#if NCURSES_SP_FUNCS
+extern NCURSES_EXPORT(MENU *)	NCURSES_SP_NAME(new_menu) (SCREEN*, ITEM **);
+#endif
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif /* ETI_MENU */
diff --git a/apps/lib/curses/pdcurses/menu/menu.priv.h b/apps/lib/curses/pdcurses/menu/menu.priv.h
new file mode 100644
index 0000000..f6edc1a
--- /dev/null
+++ b/apps/lib/curses/pdcurses/menu/menu.priv.h
@@ -0,0 +1,157 @@
+/****************************************************************************
+ * Copyright (c) 1998-2005,2009 Free Software Foundation, Inc.              *
+ *                                                                          *
+ * 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, distribute with modifications, sublicense, and/or sell       *
+ * copies of the Software, and to permit persons to whom the Software is    *
+ * furnished to do so, subject to the following conditions:                 *
+ *                                                                          *
+ * The above copyright notice and this permission notice shall be included  *
+ * in all copies or substantial portions of the Software.                   *
+ *                                                                          *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
+ * IN NO EVENT SHALL THE ABOVE 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.                               *
+ *                                                                          *
+ * Except as contained in this notice, the name(s) of the above copyright   *
+ * holders shall not be used in advertising or otherwise to promote the     *
+ * sale, use or other dealings in this Software without prior written       *
+ * authorization.                                                           *
+ ****************************************************************************/
+
+/****************************************************************************
+ *   Author:  Juergen Pfeifer, 1995,1997                                    *
+ ****************************************************************************/
+
+/* $Id: menu.priv.h,v 1.23 2009/02/28 21:02:57 juergen Exp $ */
+
+/***************************************************************************
+* Module menu.priv.h                                                       *
+* Top level private header file for all libnmenu modules                   *
+***************************************************************************/
+
+#ifndef MENU_PRIV_H_incl
+#define MENU_PRIV_H_incl 1
+
+#include "../pdcurses/curspriv.h"
+#include <errno.h>
+#include "mf_common.h"
+#include "menu.h"
+
+/* Backspace code */
+#define BS (8)
+
+extern NCURSES_EXPORT_VAR(ITEM) _nc_Default_Item;
+extern NCURSES_EXPORT_VAR(MENU) _nc_Default_Menu;
+
+/* Normalize item to default if none was given */
+#define Normalize_Item( item ) ((item)=(item)?(item):&_nc_Default_Item)
+
+/* Normalize menu to default if none was given */
+#define Normalize_Menu( menu ) ((menu)=(menu)?(menu):&_nc_Default_Menu)
+
+#define Get_Menu_Screen( menu ) (menu->userwin ? \
+				 _nc_screen_of(menu->userwin) : CURRENT_SCREEN)
+
+/* Get the user defined (framing) window of the menu */
+#define Get_Menu_UserWin(menu) ((menu)->userwin ? \
+    (menu)->userwin : stdscr)
+
+/* Normalize menu window */
+#define Get_Menu_Window(  menu ) \
+   ((menu)->usersub  ? (menu)->usersub  : Get_Menu_UserWin(menu))
+
+/* menu specific status flags */
+#define _LINK_NEEDED    (0x04)
+#define _MARK_ALLOCATED (0x08)
+
+#define ALL_MENU_OPTS (                 \
+		       O_ONEVALUE     | \
+		       O_SHOWDESC     | \
+		       O_ROWMAJOR     | \
+		       O_IGNORECASE   | \
+		       O_SHOWMATCH    | \
+		       O_NONCYCLIC    )
+
+#define ALL_ITEM_OPTS (O_SELECTABLE)
+
+/* Move to the window position of an item and draw it */
+#define Move_And_Post_Item(menu,item) \
+  {wmove((menu)->win,(menu)->spc_rows*(item)->y,((menu)->itemlen+(menu)->spc_cols)*(item)->x);\
+   _nc_Post_Item((menu),(item));}
+
+#define Move_To_Current_Item(menu,item) \
+  if ( (item) != (menu)->curitem)\
+    {\
+      Move_And_Post_Item(menu,item);\
+      Move_And_Post_Item(menu,(menu)->curitem);\
+    }
+
+/* This macro ensures, that the item becomes visible, if possible with the
+   specified row as the top row of the window. If this is not possible,
+   the top row will be adjusted and the value is stored in the row argument.
+*/
+#define Adjust_Current_Item(menu,row,item) \
+  { if ((item)->y < row) \
+      row = (item)->y;\
+    if ( (item)->y >= (row + (menu)->arows) )\
+      row = ( (item)->y < ((menu)->rows - row) ) ? \
+            (item)->y : (menu)->rows - (menu)->arows;\
+    _nc_New_TopRow_and_CurrentItem(menu,row,item); }
+
+/* Reset the match pattern buffer */
+#define Reset_Pattern(menu) \
+  { (menu)->pindex = 0; \
+    (menu)->pattern[0] = '\0'; }
+
+#define UChar(c)	((unsigned char)(c))
+
+/* Internal functions. */
+extern NCURSES_EXPORT(void) _nc_Draw_Menu (const MENU *);
+extern NCURSES_EXPORT(void) _nc_Show_Menu (const MENU *);
+extern NCURSES_EXPORT(void) _nc_Calculate_Item_Length_and_Width (MENU *);
+extern NCURSES_EXPORT(int)  _nc_Calculate_Text_Width(const TEXT *);
+extern NCURSES_EXPORT(void) _nc_Post_Item (const MENU *, const ITEM *);
+extern NCURSES_EXPORT(bool) _nc_Connect_Items (MENU *, ITEM **);
+extern NCURSES_EXPORT(void) _nc_Disconnect_Items (MENU *);
+extern NCURSES_EXPORT(void) _nc_New_TopRow_and_CurrentItem (MENU *,int, ITEM *);
+extern NCURSES_EXPORT(void) _nc_Link_Items (MENU *);
+extern NCURSES_EXPORT(int)  _nc_Match_Next_Character_In_Item_Name (MENU*,int,ITEM**);
+extern NCURSES_EXPORT(int)  _nc_menu_cursor_pos (const MENU* menu, const ITEM* item,
+				int* pY, int* pX);
+
+#ifdef TRACE
+
+#define returnItem(code)	TRACE_RETURN(code,item)
+#define returnItemPtr(code)	TRACE_RETURN(code,item_ptr)
+#define returnItemOpts(code)	TRACE_RETURN(code,item_opts)
+#define returnMenu(code)	TRACE_RETURN(code,menu)
+#define returnMenuHook(code)	TRACE_RETURN(code,menu_hook)
+#define returnMenuOpts(code)	TRACE_RETURN(code,menu_opts)
+
+extern NCURSES_EXPORT(ITEM *)	    _nc_retrace_item (ITEM *);
+extern NCURSES_EXPORT(ITEM **)	    _nc_retrace_item_ptr (ITEM **);
+extern NCURSES_EXPORT(Item_Options) _nc_retrace_item_opts (Item_Options);
+extern NCURSES_EXPORT(MENU *)	    _nc_retrace_menu (MENU *);
+extern NCURSES_EXPORT(Menu_Hook)    _nc_retrace_menu_hook (Menu_Hook);
+extern NCURSES_EXPORT(Menu_Options) _nc_retrace_menu_opts (Menu_Options);
+
+#else /* !TRACE */
+
+#define returnItem(code)	return code
+#define returnItemPtr(code)	return code
+#define returnItemOpts(code)	return code
+#define returnMenu(code)	return code
+#define returnMenuHook(code)	return code
+#define returnMenuOpts(code)	return code
+
+#endif /* TRACE/!TRACE */
+
+#endif /* MENU_PRIV_H_incl */
diff --git a/apps/lib/curses/pdcurses/menu/mf_common.h b/apps/lib/curses/pdcurses/menu/mf_common.h
new file mode 100644
index 0000000..681672d
--- /dev/null
+++ b/apps/lib/curses/pdcurses/menu/mf_common.h
@@ -0,0 +1,95 @@
+/****************************************************************************
+ * Copyright (c) 1998-2003,2004 Free Software Foundation, Inc.              *
+ *                                                                          *
+ * 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, distribute with modifications, sublicense, and/or sell       *
+ * copies of the Software, and to permit persons to whom the Software is    *
+ * furnished to do so, subject to the following conditions:                 *
+ *                                                                          *
+ * The above copyright notice and this permission notice shall be included  *
+ * in all copies or substantial portions of the Software.                   *
+ *                                                                          *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
+ * IN NO EVENT SHALL THE ABOVE 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.                               *
+ *                                                                          *
+ * Except as contained in this notice, the name(s) of the above copyright   *
+ * holders shall not be used in advertising or otherwise to promote the     *
+ * sale, use or other dealings in this Software without prior written       *
+ * authorization.                                                           *
+ ****************************************************************************/
+
+/****************************************************************************
+ *   Author:  Juergen Pfeifer, 1995,1997                                    *
+ ****************************************************************************/
+
+/* $Id: mf_common.h,v 0.22 2005/11/26 15:26:52 tom Exp $ */
+
+/* Common internal header for menu and form library */
+
+#ifndef MF_COMMON_H_incl
+#define MF_COMMON_H_incl 1
+
+#include <ncurses_cfg.h>
+#include <curses.h>
+
+#include <stdlib.h>
+#include <sys/types.h>
+#include <assert.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+
+#if DECL_ERRNO
+extern int errno;
+#endif
+
+/* in case of debug version we ignore the suppression of assertions */
+#ifdef TRACE
+#  ifdef NDEBUG
+#    undef NDEBUG
+#  endif
+#endif
+
+#include <nc_alloc.h>
+
+#if USE_RCS_IDS
+#define MODULE_ID(id) static const char Ident[] = id;
+#else
+#define MODULE_ID(id) /*nothing*/
+#endif
+
+
+/* Maximum regular 8-bit character code */
+#define MAX_REGULAR_CHARACTER (0xff)
+
+#define SET_ERROR(code) (errno=(code))
+#define GET_ERROR()     (errno)
+
+#ifdef TRACE
+#define RETURN(code)    returnCode( SET_ERROR(code) )
+#else
+#define RETURN(code)    return( SET_ERROR(code) )
+#endif
+
+/* The few common values in the status fields for menus and forms */
+#define _POSTED         (0x01U)  /* menu or form is posted                  */
+#define _IN_DRIVER      (0x02U)  /* menu or form is processing hook routine */
+
+/* Call object hook */
+#define Call_Hook( object, handler ) \
+   if ( (object) != 0 && ((object)->handler) != (void *) 0 )\
+   {\
+	(object)->status |= _IN_DRIVER;\
+	(object)->handler(object);\
+	(object)->status &= ~_IN_DRIVER;\
+   }
+
+#endif /* MF_COMMON_H_incl */
-- 
1.7.10.4


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH 16/20] app: pdcurses: add libform
  2013-03-06  9:29 ` [PATCH 01/20] Makefile: x_flags prepare for apps support Jean-Christophe PLAGNIOL-VILLARD
                     ` (13 preceding siblings ...)
  2013-03-06  9:29   ` [PATCH 15/20] app: pdcurses: add libmenu Jean-Christophe PLAGNIOL-VILLARD
@ 2013-03-06  9:29   ` Jean-Christophe PLAGNIOL-VILLARD
  2013-03-06  9:29   ` [PATCH 17/20] app: curses: add menu example Jean-Christophe PLAGNIOL-VILLARD
                     ` (3 subsequent siblings)
  18 siblings, 0 replies; 31+ messages in thread
From: Jean-Christophe PLAGNIOL-VILLARD @ 2013-03-06  9:29 UTC (permalink / raw)
  To: barebox

Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
---
 apps/lib/curses/Kconfig                      |    4 +
 apps/lib/curses/pdcurses/Makefile            |  114 +-
 apps/lib/curses/pdcurses/Makefile.include    |    1 +
 apps/lib/curses/pdcurses/form/Makefile       |   42 +
 apps/lib/curses/pdcurses/form/READ.ME        |   42 +
 apps/lib/curses/pdcurses/form/f_trace.c      |   70 +
 apps/lib/curses/pdcurses/form/fld_arg.c      |   98 +
 apps/lib/curses/pdcurses/form/fld_attr.c     |  119 +
 apps/lib/curses/pdcurses/form/fld_current.c  |  137 +
 apps/lib/curses/pdcurses/form/fld_def.c      |  399 +++
 apps/lib/curses/pdcurses/form/fld_dup.c      |  101 +
 apps/lib/curses/pdcurses/form/fld_ftchoice.c |   70 +
 apps/lib/curses/pdcurses/form/fld_ftlink.c   |   87 +
 apps/lib/curses/pdcurses/form/fld_info.c     |  113 +
 apps/lib/curses/pdcurses/form/fld_just.c     |   86 +
 apps/lib/curses/pdcurses/form/fld_link.c     |   96 +
 apps/lib/curses/pdcurses/form/fld_max.c      |   77 +
 apps/lib/curses/pdcurses/form/fld_move.c     |   64 +
 apps/lib/curses/pdcurses/form/fld_newftyp.c  |  143 +
 apps/lib/curses/pdcurses/form/fld_opts.c     |  138 +
 apps/lib/curses/pdcurses/form/fld_pad.c      |   85 +
 apps/lib/curses/pdcurses/form/fld_page.c     |   82 +
 apps/lib/curses/pdcurses/form/fld_stat.c     |   79 +
 apps/lib/curses/pdcurses/form/fld_type.c     |   97 +
 apps/lib/curses/pdcurses/form/fld_user.c     |   72 +
 apps/lib/curses/pdcurses/form/form.h         |  423 +++
 apps/lib/curses/pdcurses/form/form.priv.h    |  299 ++
 apps/lib/curses/pdcurses/form/frm_cursor.c   |   70 +
 apps/lib/curses/pdcurses/form/frm_data.c     |  193 ++
 apps/lib/curses/pdcurses/form/frm_def.c      |  448 +++
 apps/lib/curses/pdcurses/form/frm_driver.c   | 4646 ++++++++++++++++++++++++++
 apps/lib/curses/pdcurses/form/frm_hook.c     |  142 +
 apps/lib/curses/pdcurses/form/frm_opts.c     |  127 +
 apps/lib/curses/pdcurses/form/frm_page.c     |  106 +
 apps/lib/curses/pdcurses/form/frm_post.c     |  124 +
 apps/lib/curses/pdcurses/form/frm_req_name.c |  170 +
 apps/lib/curses/pdcurses/form/frm_scale.c    |   69 +
 apps/lib/curses/pdcurses/form/frm_sub.c      |   86 +
 apps/lib/curses/pdcurses/form/frm_user.c     |   72 +
 apps/lib/curses/pdcurses/form/frm_win.c      |   92 +
 apps/lib/curses/pdcurses/form/fty_alnum.c    |  202 ++
 apps/lib/curses/pdcurses/form/fty_alpha.c    |  202 ++
 apps/lib/curses/pdcurses/form/fty_enum.c     |  442 +++
 apps/lib/curses/pdcurses/form/fty_generic.c  |  297 ++
 apps/lib/curses/pdcurses/form/fty_int.c      |  293 ++
 apps/lib/curses/pdcurses/form/fty_ipv4.c     |  120 +
 apps/lib/curses/pdcurses/form/fty_num.c      |  339 ++
 apps/lib/curses/pdcurses/form/fty_regex.c    |  350 ++
 48 files changed, 11639 insertions(+), 89 deletions(-)
 rewrite apps/lib/curses/pdcurses/Makefile (78%)
 create mode 100644 apps/lib/curses/pdcurses/form/Makefile
 create mode 100644 apps/lib/curses/pdcurses/form/READ.ME
 create mode 100644 apps/lib/curses/pdcurses/form/f_trace.c
 create mode 100644 apps/lib/curses/pdcurses/form/fld_arg.c
 create mode 100644 apps/lib/curses/pdcurses/form/fld_attr.c
 create mode 100644 apps/lib/curses/pdcurses/form/fld_current.c
 create mode 100644 apps/lib/curses/pdcurses/form/fld_def.c
 create mode 100644 apps/lib/curses/pdcurses/form/fld_dup.c
 create mode 100644 apps/lib/curses/pdcurses/form/fld_ftchoice.c
 create mode 100644 apps/lib/curses/pdcurses/form/fld_ftlink.c
 create mode 100644 apps/lib/curses/pdcurses/form/fld_info.c
 create mode 100644 apps/lib/curses/pdcurses/form/fld_just.c
 create mode 100644 apps/lib/curses/pdcurses/form/fld_link.c
 create mode 100644 apps/lib/curses/pdcurses/form/fld_max.c
 create mode 100644 apps/lib/curses/pdcurses/form/fld_move.c
 create mode 100644 apps/lib/curses/pdcurses/form/fld_newftyp.c
 create mode 100644 apps/lib/curses/pdcurses/form/fld_opts.c
 create mode 100644 apps/lib/curses/pdcurses/form/fld_pad.c
 create mode 100644 apps/lib/curses/pdcurses/form/fld_page.c
 create mode 100644 apps/lib/curses/pdcurses/form/fld_stat.c
 create mode 100644 apps/lib/curses/pdcurses/form/fld_type.c
 create mode 100644 apps/lib/curses/pdcurses/form/fld_user.c
 create mode 100644 apps/lib/curses/pdcurses/form/form.h
 create mode 100644 apps/lib/curses/pdcurses/form/form.priv.h
 create mode 100644 apps/lib/curses/pdcurses/form/frm_cursor.c
 create mode 100644 apps/lib/curses/pdcurses/form/frm_data.c
 create mode 100644 apps/lib/curses/pdcurses/form/frm_def.c
 create mode 100644 apps/lib/curses/pdcurses/form/frm_driver.c
 create mode 100644 apps/lib/curses/pdcurses/form/frm_hook.c
 create mode 100644 apps/lib/curses/pdcurses/form/frm_opts.c
 create mode 100644 apps/lib/curses/pdcurses/form/frm_page.c
 create mode 100644 apps/lib/curses/pdcurses/form/frm_post.c
 create mode 100644 apps/lib/curses/pdcurses/form/frm_req_name.c
 create mode 100644 apps/lib/curses/pdcurses/form/frm_scale.c
 create mode 100644 apps/lib/curses/pdcurses/form/frm_sub.c
 create mode 100644 apps/lib/curses/pdcurses/form/frm_user.c
 create mode 100644 apps/lib/curses/pdcurses/form/frm_win.c
 create mode 100644 apps/lib/curses/pdcurses/form/fty_alnum.c
 create mode 100644 apps/lib/curses/pdcurses/form/fty_alpha.c
 create mode 100644 apps/lib/curses/pdcurses/form/fty_enum.c
 create mode 100644 apps/lib/curses/pdcurses/form/fty_generic.c
 create mode 100644 apps/lib/curses/pdcurses/form/fty_int.c
 create mode 100644 apps/lib/curses/pdcurses/form/fty_ipv4.c
 create mode 100644 apps/lib/curses/pdcurses/form/fty_num.c
 create mode 100644 apps/lib/curses/pdcurses/form/fty_regex.c

diff --git a/apps/lib/curses/Kconfig b/apps/lib/curses/Kconfig
index 5950385..8c0fa1b 100644
--- a/apps/lib/curses/Kconfig
+++ b/apps/lib/curses/Kconfig
@@ -22,4 +22,8 @@ config APP_LIB_MENU
 	bool "menu"
 	depends on APP_LIB_PDCURSES
 
+config APP_LIB_FORM
+	bool "form"
+	depends on APP_LIB_MENU
+
 endif
diff --git a/apps/lib/curses/pdcurses/Makefile b/apps/lib/curses/pdcurses/Makefile
dissimilarity index 78%
index 3707947..37c7b8e 100644
--- a/apps/lib/curses/pdcurses/Makefile
+++ b/apps/lib/curses/pdcurses/Makefile
@@ -1,89 +1,25 @@
-#ifeq (y,y)
-#INCLUDES += -D_LP64=0 -Icurses/PDCurses-3.4 -Icurses/pdcurses-backend -Icurses/menu -Icurses/form
-#endif
-
-
-obj-y += pdcurses/
-obj-y += backend/
-
-includes-y += pdcurses-backend/nc_alloc.h
-includes-y += pdcurses-backend/ncurses_cfg.h
-includes-y += PDCurses-3.4/curses.h
-includes-y += PDCurses-3.4/term.h
-includes-y += PDCurses-3.4/panel.h
-includes-y += menu/eti.h
-includes-y += menu/menu.h
-includes-y += menu/mf_common.h
-includes-y += form/form.h
-
-libpanel-y += PDCurses-3.4/pdcurses/panel.o
-
-libmenu-y += menu/m_req_name.o
-libmenu-y += menu/m_item_nam.o
-libmenu-y += menu/m_pad.o
-libmenu-y += menu/m_cursor.o
-libmenu-y += menu/m_item_new.o
-libmenu-y += menu/m_attribs.o
-libmenu-y += menu/m_item_opt.o
-libmenu-y += menu/m_format.o
-libmenu-y += menu/m_post.o
-libmenu-y += menu/m_userptr.o
-libmenu-y += menu/m_item_cur.o
-libmenu-y += menu/m_driver.o
-libmenu-y += menu/m_sub.o
-libmenu-y += menu/m_win.o
-libmenu-y += menu/m_global.o
-libmenu-y += menu/m_item_vis.o
-libmenu-y += menu/m_new.o
-libmenu-y += menu/m_scale.o
-libmenu-y += menu/m_spacing.o
-libmenu-y += menu/m_opts.o
-libmenu-y += menu/m_pattern.o
-libmenu-y += menu/m_item_val.o
-libmenu-y += menu/m_hook.o
-libmenu-y += menu/m_item_use.o
-libmenu-y += menu/m_items.o
-libmenu-y += menu/m_item_top.o
-libform-y += form/frm_page.o
-libform-y += form/frm_opts.o
-libform-y += form/frm_def.o
-libform-y += form/frm_req_name.o
-libform-y += form/fty_alpha.o
-libform-y += form/frm_driver.o
-libform-y += form/fld_user.o
-libform-y += form/frm_win.o
-libform-y += form/fld_newftyp.o
-#libform-y += form/fty_regex.o
-libform-y += form/fld_stat.o
-libform-y += form/fld_pad.o
-libform-y += form/fld_current.o
-libform-y += form/frm_post.o
-#libform-y += form/f_trace.o
-libform-y += form/fty_generic.o
-libform-y += form/fld_page.o
-libform-y += form/frm_hook.o
-libform-y += form/frm_scale.o
-libform-y += form/fty_int.o
-libform-y += form/fty_alnum.o
-libform-y += form/frm_cursor.o
-#libform-y += form/fty_ipv4.o
-libform-y += form/fld_link.o
-libform-y += form/fld_arg.o
-libform-y += form/fld_move.o
-libform-y += form/fld_def.o
-libform-y += form/fld_type.o
-libform-y += form/fld_max.o
-libform-y += form/fld_ftlink.o
-libform-y += form/fld_ftchoice.o
-libform-y += form/fld_info.o
-libform-y += form/frm_user.o
-#libform-y += form/fty_num.o
-libform-y += form/frm_sub.o
-libform-y += form/fty_enum.o
-libform-y += form/frm_data.o
-libform-y += form/fld_opts.o
-libform-y += form/fld_attr.o
-libform-y += form/fld_dup.o
-libform-y += form/fld_just.o
-
-app-y += $(curses-y)
+#ifeq (y,y)
+#INCLUDES += -D_LP64=0 -Icurses/PDCurses-3.4 -Icurses/pdcurses-backend -Icurses/menu -Icurses/form
+#endif
+
+
+obj-y += pdcurses/
+obj-y += backend/
+obj-$(CONFIG_APP_LIB_MENU) += menu/
+obj-$(CONFIG_APP_LIB_FORM) += form/
+
+includes-y += pdcurses-backend/nc_alloc.h
+includes-y += pdcurses-backend/ncurses_cfg.h
+includes-y += PDCurses-3.4/curses.h
+includes-y += PDCurses-3.4/term.h
+includes-y += PDCurses-3.4/panel.h
+includes-y += menu/eti.h
+includes-y += menu/menu.h
+includes-y += menu/mf_common.h
+includes-y += form/form.h
+
+libpanel-y += PDCurses-3.4/pdcurses/panel.o
+
+
+
+app-y += $(curses-y)
diff --git a/apps/lib/curses/pdcurses/Makefile.include b/apps/lib/curses/pdcurses/Makefile.include
index 7a0061e..710e782 100644
--- a/apps/lib/curses/pdcurses/Makefile.include
+++ b/apps/lib/curses/pdcurses/Makefile.include
@@ -1,2 +1,3 @@
 APP_CPPFLAGS-y += -I$(srctree)/apps/lib/curses/pdcurses/include/ -D_LP64=0
 APP_CPPFLAGS-$(CONFIG_APP_LIB_MENU) += -I$(srctree)/apps/lib/curses/pdcurses/menu
+APP_CPPFLAGS-$(CONFIG_APP_LIB_FORM) += -I$(srctree)/apps/lib/curses/pdcurses/form
diff --git a/apps/lib/curses/pdcurses/form/Makefile b/apps/lib/curses/pdcurses/form/Makefile
new file mode 100644
index 0000000..42f641c
--- /dev/null
+++ b/apps/lib/curses/pdcurses/form/Makefile
@@ -0,0 +1,42 @@
+app-y += frm_page.o
+app-y += frm_opts.o
+app-y += frm_def.o
+app-y += frm_req_name.o
+app-y += fty_alpha.o
+app-y += frm_driver.o
+app-y += fld_user.o
+app-y += frm_win.o
+app-y += fld_newftyp.o
+#app-y += fty_regex.o
+app-y += fld_stat.o
+app-y += fld_pad.o
+app-y += fld_current.o
+app-y += frm_post.o
+#app-y += f_trace.o
+app-y += fty_generic.o
+app-y += fld_page.o
+app-y += frm_hook.o
+app-y += frm_scale.o
+app-y += fty_int.o
+app-y += fty_alnum.o
+app-y += frm_cursor.o
+#app-y += fty_ipv4.o
+app-y += fld_link.o
+app-y += fld_arg.o
+app-y += fld_move.o
+app-y += fld_def.o
+app-y += fld_type.o
+app-y += fld_max.o
+app-y += fld_ftlink.o
+app-y += fld_ftchoice.o
+app-y += fld_info.o
+app-y += frm_user.o
+#app-y += fty_num.o
+app-y += frm_sub.o
+app-y += fty_enum.o
+app-y += frm_data.o
+app-y += fld_opts.o
+app-y += fld_attr.o
+app-y += fld_dup.o
+app-y += fld_just.o
+
diff --git a/apps/lib/curses/pdcurses/form/READ.ME b/apps/lib/curses/pdcurses/form/READ.ME
new file mode 100644
index 0000000..da86bf6
--- /dev/null
+++ b/apps/lib/curses/pdcurses/form/READ.ME
@@ -0,0 +1,42 @@
+-------------------------------------------------------------------------------
+-- Copyright (c) 1998-2003,2006 Free Software Foundation, Inc.               --
+--                                                                           --
+-- 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, distribute with modifications, sublicense, and/or sell copies --
+-- of the Software, and to permit persons to whom the Software is furnished  --
+-- to do so, subject to the following conditions:                            --
+--                                                                           --
+-- The above copyright notice and this permission notice shall be included   --
+-- in all copies or substantial portions of the Software.                    --
+--                                                                           --
+-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS   --
+-- OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF                --
+-- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN --
+-- NO EVENT SHALL THE ABOVE 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.                                    --
+--                                                                           --
+-- Except as contained in this notice, the name(s) of the above copyright    --
+-- holders shall not be used in advertising or otherwise to promote the      --
+-- sale, use or other dealings in this Software without prior written        --
+-- authorization.                                                            --
+-------------------------------------------------------------------------------
+-- $Id: READ.ME,v 0.7 2006/04/22 23:13:05 tom Exp $
+-------------------------------------------------------------------------------
+
+This is a clone of the form library that is available with typical
+System V curses implementations (ETI).
+
+It is modelled after the documentation that comes for this library with
+a 386 based SVR4 implementation (ESIX).  
+
+The development environment was and is an ELF based Linux system.
+
+For things that still need doing, see the TO-DO file in the top-level 
+directory.
+
+Juergen Pfeifer
diff --git a/apps/lib/curses/pdcurses/form/f_trace.c b/apps/lib/curses/pdcurses/form/f_trace.c
new file mode 100644
index 0000000..6044e03
--- /dev/null
+++ b/apps/lib/curses/pdcurses/form/f_trace.c
@@ -0,0 +1,70 @@
+/****************************************************************************
+ * Copyright (c) 2004,2010 Free Software Foundation, Inc.                   *
+ *                                                                          *
+ * 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, distribute with modifications, sublicense, and/or sell       *
+ * copies of the Software, and to permit persons to whom the Software is    *
+ * furnished to do so, subject to the following conditions:                 *
+ *                                                                          *
+ * The above copyright notice and this permission notice shall be included  *
+ * in all copies or substantial portions of the Software.                   *
+ *                                                                          *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
+ * IN NO EVENT SHALL THE ABOVE 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.                               *
+ *                                                                          *
+ * Except as contained in this notice, the name(s) of the above copyright   *
+ * holders shall not be used in advertising or otherwise to promote the     *
+ * sale, use or other dealings in this Software without prior written       *
+ * authorization.                                                           *
+ ****************************************************************************/
+
+/****************************************************************************
+ *   Author:  Thomas E. Dickey                                              *
+ ****************************************************************************/
+
+#include "form.priv.h"
+
+MODULE_ID("$Id: f_trace.c,v 1.2 2010/01/23 21:14:36 tom Exp $")
+
+NCURSES_EXPORT(FIELD **)
+_nc_retrace_field_ptr(FIELD **code)
+{
+  T((T_RETURN("%p"), (void *)code));
+  return code;
+}
+
+NCURSES_EXPORT(FIELD *)
+_nc_retrace_field(FIELD *code)
+{
+  T((T_RETURN("%p"), (void *)code));
+  return code;
+}
+
+NCURSES_EXPORT(FIELDTYPE *)
+_nc_retrace_field_type(FIELDTYPE *code)
+{
+  T((T_RETURN("%p"), (void *)code));
+  return code;
+}
+
+NCURSES_EXPORT(FORM *)
+_nc_retrace_form(FORM *code)
+{
+  T((T_RETURN("%p"), (void *)code));
+  return code;
+}
+
+NCURSES_EXPORT(Form_Hook)
+_nc_retrace_form_hook(Form_Hook code)
+{
+  T((T_RETURN("%p"), code));
+  return code;
+}
diff --git a/apps/lib/curses/pdcurses/form/fld_arg.c b/apps/lib/curses/pdcurses/form/fld_arg.c
new file mode 100644
index 0000000..a07bdb1
--- /dev/null
+++ b/apps/lib/curses/pdcurses/form/fld_arg.c
@@ -0,0 +1,98 @@
+/****************************************************************************
+ * Copyright (c) 1998-2004,2010 Free Software Foundation, Inc.              *
+ *                                                                          *
+ * 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, distribute with modifications, sublicense, and/or sell       *
+ * copies of the Software, and to permit persons to whom the Software is    *
+ * furnished to do so, subject to the following conditions:                 *
+ *                                                                          *
+ * The above copyright notice and this permission notice shall be included  *
+ * in all copies or substantial portions of the Software.                   *
+ *                                                                          *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
+ * IN NO EVENT SHALL THE ABOVE 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.                               *
+ *                                                                          *
+ * Except as contained in this notice, the name(s) of the above copyright   *
+ * holders shall not be used in advertising or otherwise to promote the     *
+ * sale, use or other dealings in this Software without prior written       *
+ * authorization.                                                           *
+ ****************************************************************************/
+
+/****************************************************************************
+ *   Author:  Juergen Pfeifer, 1995,1997                                    *
+ ****************************************************************************/
+
+#include "form.priv.h"
+
+MODULE_ID("$Id: fld_arg.c,v 1.12 2010/01/23 21:14:35 tom Exp $")
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  int set_fieldtype_arg(
+|                            FIELDTYPE *typ,
+|                            void * (* const make_arg)(va_list *),
+|                            void * (* const copy_arg)(const void *),
+|                            void   (* const free_arg)(void *) )
+|
+|   Description   :  Connects to the type additional arguments necessary
+|                    for a set_field_type call. The various function pointer
+|                    arguments are:
+|                       make_arg : allocates a structure for the field
+|                                  specific parameters.
+|                       copy_arg : duplicate the structure created by
+|                                  make_arg
+|                       free_arg : Release the memory allocated by make_arg
+|                                  or copy_arg
+|
+|                    At least make_arg must be non-NULL.
+|                    You may pass NULL for copy_arg and free_arg if your
+|                    make_arg function doesn't allocate memory and your
+|                    arg fits into the storage for a (void*).
+|
+|   Return Values :  E_OK           - success
+|                    E_BAD_ARGUMENT - invalid argument
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(int)
+set_fieldtype_arg(FIELDTYPE *typ,
+		  void *(*const make_arg)(va_list *),
+		  void *(*const copy_arg)(const void *),
+		  void (*const free_arg) (void *))
+{
+  T((T_CALLED("set_fieldtype_arg(%p,%p,%p,%p)"),
+     (void *)typ, make_arg, copy_arg, free_arg));
+
+  if (typ != 0 && make_arg != (void *)0)
+    {
+      typ->status |= _HAS_ARGS;
+      typ->makearg = make_arg;
+      typ->copyarg = copy_arg;
+      typ->freearg = free_arg;
+      RETURN(E_OK);
+    }
+  RETURN(E_BAD_ARGUMENT);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  void *field_arg(const FIELD *field)
+|
+|   Description   :  Retrieve pointer to the fields argument structure.
+|
+|   Return Values :  Pointer to structure or NULL if none is defined.
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(void *)
+field_arg(const FIELD *field)
+{
+  T((T_CALLED("field_arg(%p)"), (const void *)field));
+  returnVoidPtr(Normalize_Field(field)->arg);
+}
+
+/* fld_arg.c ends here */
diff --git a/apps/lib/curses/pdcurses/form/fld_attr.c b/apps/lib/curses/pdcurses/form/fld_attr.c
new file mode 100644
index 0000000..0112f00
--- /dev/null
+++ b/apps/lib/curses/pdcurses/form/fld_attr.c
@@ -0,0 +1,119 @@
+/****************************************************************************
+ * Copyright (c) 1998-2004,2010 Free Software Foundation, Inc.              *
+ *                                                                          *
+ * 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, distribute with modifications, sublicense, and/or sell       *
+ * copies of the Software, and to permit persons to whom the Software is    *
+ * furnished to do so, subject to the following conditions:                 *
+ *                                                                          *
+ * The above copyright notice and this permission notice shall be included  *
+ * in all copies or substantial portions of the Software.                   *
+ *                                                                          *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
+ * IN NO EVENT SHALL THE ABOVE 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.                               *
+ *                                                                          *
+ * Except as contained in this notice, the name(s) of the above copyright   *
+ * holders shall not be used in advertising or otherwise to promote the     *
+ * sale, use or other dealings in this Software without prior written       *
+ * authorization.                                                           *
+ ****************************************************************************/
+
+/****************************************************************************
+ *   Author:  Juergen Pfeifer, 1995,1997                                    *
+ ****************************************************************************/
+
+#include "form.priv.h"
+
+MODULE_ID("$Id: fld_attr.c,v 1.11 2010/01/23 21:12:08 tom Exp $")
+
+/*----------------------------------------------------------------------------
+  Field-Attribute manipulation routines
+  --------------------------------------------------------------------------*/
+/* "Template" macro to generate a function to set a fields attribute */
+#define GEN_FIELD_ATTR_SET_FCT( name ) \
+NCURSES_IMPEXP int NCURSES_API set_field_ ## name (FIELD * field, chtype attr)\
+{\
+   int res = E_BAD_ARGUMENT;\
+   T((T_CALLED("set_field_" #name "(%p,%s)"), field, _traceattr(attr)));\
+   if ( attr==A_NORMAL || ((attr & A_ATTRIBUTES)==attr) )\
+     {\
+       Normalize_Field( field );\
+       if (field != 0) \
+	 { \
+	 if ((field -> name) != attr)\
+	   {\
+	     field -> name = attr;\
+	     res = _nc_Synchronize_Attributes( field );\
+	   }\
+	 else\
+	   {\
+	     res = E_OK;\
+	   }\
+	 }\
+     }\
+   RETURN(res);\
+}
+
+/* "Template" macro to generate a function to get a fields attribute */
+#define GEN_FIELD_ATTR_GET_FCT( name ) \
+NCURSES_IMPEXP chtype NCURSES_API field_ ## name (const FIELD * field)\
+{\
+   T((T_CALLED("field_" #name "(%p)"), (const void *) field));\
+   returnAttr( A_ATTRIBUTES & (Normalize_Field( field ) -> name) );\
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  int set_field_fore(FIELD *field, chtype attr)
+|
+|   Description   :  Sets the foreground of the field used to display the
+|                    field contents.
+|
+|   Return Values :  E_OK             - success
+|                    E_BAD_ARGUMENT   - invalid attributes
+|                    E_SYSTEM_ERROR   - system error
++--------------------------------------------------------------------------*/
+GEN_FIELD_ATTR_SET_FCT(fore)
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  chtype field_fore(const FIELD *)
+|
+|   Description   :  Retrieve fields foreground attribute
+|
+|   Return Values :  The foreground attribute
++--------------------------------------------------------------------------*/
+GEN_FIELD_ATTR_GET_FCT(fore)
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  int set_field_back(FIELD *field, chtype attr)
+|
+|   Description   :  Sets the background of the field used to display the
+|                    fields extend.
+|
+|   Return Values :  E_OK             - success
+|                    E_BAD_ARGUMENT   - invalid attributes
+|                    E_SYSTEM_ERROR   - system error
++--------------------------------------------------------------------------*/
+GEN_FIELD_ATTR_SET_FCT(back)
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  chtype field_back(const
+|
+|   Description   :  Retrieve fields background attribute
+|
+|   Return Values :  The background attribute
++--------------------------------------------------------------------------*/
+GEN_FIELD_ATTR_GET_FCT(back)
+
+/* fld_attr.c ends here */
diff --git a/apps/lib/curses/pdcurses/form/fld_current.c b/apps/lib/curses/pdcurses/form/fld_current.c
new file mode 100644
index 0000000..ef9ec00
--- /dev/null
+++ b/apps/lib/curses/pdcurses/form/fld_current.c
@@ -0,0 +1,137 @@
+/****************************************************************************
+ * Copyright (c) 1998-2004,2010 Free Software Foundation, Inc.              *
+ *                                                                          *
+ * 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, distribute with modifications, sublicense, and/or sell       *
+ * copies of the Software, and to permit persons to whom the Software is    *
+ * furnished to do so, subject to the following conditions:                 *
+ *                                                                          *
+ * The above copyright notice and this permission notice shall be included  *
+ * in all copies or substantial portions of the Software.                   *
+ *                                                                          *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
+ * IN NO EVENT SHALL THE ABOVE 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.                               *
+ *                                                                          *
+ * Except as contained in this notice, the name(s) of the above copyright   *
+ * holders shall not be used in advertising or otherwise to promote the     *
+ * sale, use or other dealings in this Software without prior written       *
+ * authorization.                                                           *
+ ****************************************************************************/
+
+/****************************************************************************
+ *   Author:  Juergen Pfeifer, 1995,1997                                    *
+ ****************************************************************************/
+
+#include "form.priv.h"
+
+MODULE_ID("$Id: fld_current.c,v 1.12 2010/01/23 21:14:35 tom Exp $")
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  int set_current_field(FORM  * form,FIELD * field)
+|
+|   Description   :  Set the current field of the form to the specified one.
+|
+|   Return Values :  E_OK              - success
+|                    E_BAD_ARGUMENT    - invalid form or field pointer
+|                    E_REQUEST_DENIED  - field not selectable
+|                    E_BAD_STATE       - called from a hook routine
+|                    E_INVALID_FIELD   - current field can't be left
+|                    E_SYSTEM_ERROR    - system error
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(int)
+set_current_field(FORM *form, FIELD *field)
+{
+  int err = E_OK;
+
+  T((T_CALLED("set_current_field(%p,%p)"), (void *)form, (void *)field));
+  if (form == 0 || field == 0)
+    {
+      RETURN(E_BAD_ARGUMENT);
+    }
+  else if ((form != field->form) || Field_Is_Not_Selectable(field))
+    {
+      RETURN(E_REQUEST_DENIED);
+    }
+  else if ((form->status & _POSTED) == 0)
+    {
+      form->current = field;
+      form->curpage = field->page;
+    }
+  else
+    {
+      if ((form->status & _IN_DRIVER) != 0)
+	{
+	  err = E_BAD_STATE;
+	}
+      else
+	{
+	  if (form->current != field)
+	    {
+	      if (!_nc_Internal_Validation(form))
+		{
+		  err = E_INVALID_FIELD;
+		}
+	      else
+		{
+		  Call_Hook(form, fieldterm);
+		  if (field->page != form->curpage)
+		    {
+		      Call_Hook(form, formterm);
+		      err = _nc_Set_Form_Page(form, (int)field->page, field);
+		      Call_Hook(form, forminit);
+		    }
+		  else
+		    {
+		      err = _nc_Set_Current_Field(form, field);
+		    }
+		  Call_Hook(form, fieldinit);
+		  (void)_nc_Refresh_Current_Field(form);
+		}
+	    }
+	}
+    }
+  RETURN(err);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  FIELD *current_field(const FORM * form)
+|
+|   Description   :  Return the current field.
+|
+|   Return Values :  Pointer to the current field.
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(FIELD *)
+current_field(const FORM *form)
+{
+  T((T_CALLED("current_field(%p)"), (const void *)form));
+  returnField(Normalize_Form(form)->current);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  int field_index(const FIELD * field)
+|
+|   Description   :  Return the index of the field in the field-array of
+|                    the form.
+|
+|   Return Values :  >= 0   : field index
+|                    -1     : fieldpointer invalid or field not connected
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(int)
+field_index(const FIELD *field)
+{
+  T((T_CALLED("field_index(%p)"), (const void *)field));
+  returnCode((field != 0 && field->form != 0) ? (int)field->index : -1);
+}
+
+/* fld_current.c ends here */
diff --git a/apps/lib/curses/pdcurses/form/fld_def.c b/apps/lib/curses/pdcurses/form/fld_def.c
new file mode 100644
index 0000000..6d7bd34
--- /dev/null
+++ b/apps/lib/curses/pdcurses/form/fld_def.c
@@ -0,0 +1,399 @@
+/****************************************************************************
+ * Copyright (c) 1998-2007,2010 Free Software Foundation, Inc.              *
+ *                                                                          *
+ * 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, distribute with modifications, sublicense, and/or sell       *
+ * copies of the Software, and to permit persons to whom the Software is    *
+ * furnished to do so, subject to the following conditions:                 *
+ *                                                                          *
+ * The above copyright notice and this permission notice shall be included  *
+ * in all copies or substantial portions of the Software.                   *
+ *                                                                          *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
+ * IN NO EVENT SHALL THE ABOVE 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.                               *
+ *                                                                          *
+ * Except as contained in this notice, the name(s) of the above copyright   *
+ * holders shall not be used in advertising or otherwise to promote the     *
+ * sale, use or other dealings in this Software without prior written       *
+ * authorization.                                                           *
+ ****************************************************************************/
+
+/****************************************************************************
+ *   Author:  Juergen Pfeifer, 1995,1997                                    *
+ ****************************************************************************/
+
+#include "form.priv.h"
+
+MODULE_ID("$Id: fld_def.c,v 1.38 2010/01/23 21:14:35 tom Exp $")
+
+/* this can't be readonly */
+static FIELD default_field =
+{
+  0,				/* status  */
+  0,				/* rows    */
+  0,				/* cols    */
+  0,				/* frow    */
+  0,				/* fcol    */
+  0,				/* drows   */
+  0,				/* dcols   */
+  0,				/* maxgrow */
+  0,				/* nrow    */
+  0,				/* nbuf    */
+  NO_JUSTIFICATION,		/* just    */
+  0,				/* page    */
+  0,				/* index   */
+  (int)' ',			/* pad     */
+  A_NORMAL,			/* fore    */
+  A_NORMAL,			/* back    */
+  ALL_FIELD_OPTS,		/* opts    */
+  (FIELD *)0,			/* snext   */
+  (FIELD *)0,			/* sprev   */
+  (FIELD *)0,			/* link    */
+  (FORM *)0,			/* form    */
+  (FIELDTYPE *)0,		/* type    */
+  (char *)0,			/* arg     */
+  (FIELD_CELL *)0,		/* buf     */
+  (char *)0			/* usrptr  */
+  NCURSES_FIELD_EXTENSION
+};
+
+NCURSES_EXPORT_VAR(FIELD *)
+_nc_Default_Field = &default_field;
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  TypeArgument *_nc_Make_Argument(
+|                              const FIELDTYPE *typ,
+|                              va_list *ap,
+|                              int *err )
+|
+|   Description   :  Create an argument structure for the specified type.
+|                    Use the type-dependent argument list to construct
+|                    it.
+|
+|   Return Values :  Pointer to argument structure. Maybe NULL.
+|                    In case of an error in *err an error counter is increased.
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(TypeArgument *)
+_nc_Make_Argument(const FIELDTYPE *typ, va_list *ap, int *err)
+{
+  TypeArgument *res = (TypeArgument *)0;
+  TypeArgument *p;
+
+  if (typ != 0 && (typ->status & _HAS_ARGS) != 0)
+    {
+      assert(err != 0 && ap != (va_list *)0);
+      if ((typ->status & _LINKED_TYPE) != 0)
+	{
+	  p = typeMalloc(TypeArgument, 1);
+
+	  if (p != 0)
+	    {
+	      p->left = _nc_Make_Argument(typ->left, ap, err);
+	      p->right = _nc_Make_Argument(typ->right, ap, err);
+	      return p;
+	    }
+	  else
+	    {
+	      *err += 1;
+	    }
+	}
+      else
+	{
+	  assert(typ->makearg != (void *)0);
+	  if (!(res = (TypeArgument *)typ->makearg(ap)))
+	    {
+	      *err += 1;
+	    }
+	}
+    }
+  return res;
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  TypeArgument *_nc_Copy_Argument(const FIELDTYPE *typ,
+|                                                    const TypeArgument *argp,
+|                                                    int *err )
+|
+|   Description   :  Create a copy of an argument structure for the specified
+|                    type.
+|
+|   Return Values :  Pointer to argument structure. Maybe NULL.
+|                    In case of an error in *err an error counter is increased.
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(TypeArgument *)
+_nc_Copy_Argument(const FIELDTYPE *typ, const TypeArgument *argp, int *err)
+{
+  TypeArgument *res = (TypeArgument *)0;
+  TypeArgument *p;
+
+  if (typ != 0 && (typ->status & _HAS_ARGS) != 0)
+    {
+      assert(err != 0 && argp != 0);
+      if ((typ->status & _LINKED_TYPE) != 0)
+	{
+	  p = typeMalloc(TypeArgument, 1);
+
+	  if (p != 0)
+	    {
+	      p->left = _nc_Copy_Argument(typ, argp->left, err);
+	      p->right = _nc_Copy_Argument(typ, argp->right, err);
+	      return p;
+	    }
+	  *err += 1;
+	}
+      else
+	{
+	  if (typ->copyarg != (void *)0)
+	    {
+	      if (!(res = (TypeArgument *)(typ->copyarg((const void *)argp))))
+		{
+		  *err += 1;
+		}
+	    }
+	  else
+	    {
+	      res = (TypeArgument *)argp;
+	    }
+	}
+    }
+  return res;
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  void _nc_Free_Argument(const FIELDTYPE *typ,
+|                                           TypeArgument * argp )
+|
+|   Description   :  Release memory associated with the argument structure
+|                    for the given fieldtype.
+|
+|   Return Values :  -
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(void)
+_nc_Free_Argument(const FIELDTYPE *typ, TypeArgument *argp)
+{
+  if (typ != 0 && (typ->status & _HAS_ARGS) != 0)
+    {
+      if ((typ->status & _LINKED_TYPE) != 0)
+	{
+	  assert(argp != 0);
+	  _nc_Free_Argument(typ->left, argp->left);
+	  _nc_Free_Argument(typ->right, argp->right);
+	  free(argp);
+	}
+      else
+	{
+	  if (typ->freearg != (void *)0)
+	    {
+	      typ->freearg((void *)argp);
+	    }
+	}
+    }
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  bool _nc_Copy_Type( FIELD *dst, FIELD const *src )
+|
+|   Description   :  Copy argument structure of field src to field dst
+|
+|   Return Values :  TRUE       - copy worked
+|                    FALSE      - error occurred
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(bool)
+_nc_Copy_Type(FIELD *dst, FIELD const *src)
+{
+  int err = 0;
+
+  assert(dst != 0 && src != 0);
+
+  dst->type = src->type;
+  dst->arg = (void *)_nc_Copy_Argument(src->type, (TypeArgument *)(src->arg), &err);
+
+  if (err != 0)
+    {
+      _nc_Free_Argument(dst->type, (TypeArgument *)(dst->arg));
+      dst->type = (FIELDTYPE *)0;
+      dst->arg = (void *)0;
+      return FALSE;
+    }
+  else
+    {
+      if (dst->type != 0)
+	{
+	  dst->type->ref++;
+	}
+      return TRUE;
+    }
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  void _nc_Free_Type( FIELD *field )
+|
+|   Description   :  Release Argument structure for this field
+|
+|   Return Values :  -
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(void)
+_nc_Free_Type(FIELD *field)
+{
+  assert(field != 0);
+  if (field->type != 0)
+    {
+      field->type->ref--;
+      _nc_Free_Argument(field->type, (TypeArgument *)(field->arg));
+    }
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  FIELD *new_field( int rows, int cols,
+|                                      int frow, int fcol,
+|                                      int nrow, int nbuf )
+|
+|   Description   :  Create a new field with this many 'rows' and 'cols',
+|                    starting at 'frow/fcol' in the subwindow of the form.
+|                    Allocate 'nrow' off-screen rows and 'nbuf' additional
+|                    buffers. If an error occurs, errno is set to
+|
+|                    E_BAD_ARGUMENT - invalid argument
+|                    E_SYSTEM_ERROR - system error
+|
+|   Return Values :  Pointer to the new field or NULL if failure.
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(FIELD *)
+new_field(int rows, int cols, int frow, int fcol, int nrow, int nbuf)
+{
+  static const FIELD_CELL blank = BLANK;
+  static const FIELD_CELL zeros = ZEROS;
+
+  FIELD *New_Field = (FIELD *)0;
+  int err = E_BAD_ARGUMENT;
+
+  T((T_CALLED("new_field(%d,%d,%d,%d,%d,%d)"), rows, cols, frow, fcol, nrow, nbuf));
+  if (rows > 0 &&
+      cols > 0 &&
+      frow >= 0 &&
+      fcol >= 0 &&
+      nrow >= 0 &&
+      nbuf >= 0 &&
+      ((err = E_SYSTEM_ERROR) != 0) &&	/* trick: this resets the default error */
+      (New_Field = typeMalloc(FIELD, 1)) != 0)
+    {
+      T((T_CREATE("field %p"), (void *)New_Field));
+      *New_Field = default_field;
+      New_Field->rows = rows;
+      New_Field->cols = cols;
+      New_Field->drows = rows + nrow;
+      New_Field->dcols = cols;
+      New_Field->frow = frow;
+      New_Field->fcol = fcol;
+      New_Field->nrow = nrow;
+      New_Field->nbuf = nbuf;
+      New_Field->link = New_Field;
+
+#if USE_WIDEC_SUPPORT
+      New_Field->working = newpad(1, Buffer_Length(New_Field) + 1);
+      New_Field->expanded = typeCalloc(char *, 1 + (unsigned)nbuf);
+#endif
+
+      if (_nc_Copy_Type(New_Field, &default_field))
+	{
+	  size_t len;
+
+	  len = Total_Buffer_Size(New_Field);
+	  if ((New_Field->buf = (FIELD_CELL *)malloc(len)))
+	    {
+	      /* Prefill buffers with blanks and insert terminating zeroes
+	         between buffers */
+	      int i, j;
+	      int cells = Buffer_Length(New_Field);
+
+	      for (i = 0; i <= New_Field->nbuf; i++)
+		{
+		  FIELD_CELL *buffer = &(New_Field->buf[(cells + 1) * i]);
+
+		  for (j = 0; j < cells; ++j)
+		    {
+		      buffer[j] = blank;
+		    }
+		  buffer[j] = zeros;
+		}
+	      returnField(New_Field);
+	    }
+	}
+    }
+
+  if (New_Field)
+    free_field(New_Field);
+
+  SET_ERROR(err);
+  returnField((FIELD *)0);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  int free_field( FIELD *field )
+|
+|   Description   :  Frees the storage allocated for the field.
+|
+|   Return Values :  E_OK           - success
+|                    E_BAD_ARGUMENT - invalid field pointer
+|                    E_CONNECTED    - field is connected
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(int)
+free_field(FIELD *field)
+{
+  T((T_CALLED("free_field(%p)"), (void *)field));
+  if (!field)
+    {
+      RETURN(E_BAD_ARGUMENT);
+    }
+  else if (field->form != 0)
+    {
+      RETURN(E_CONNECTED);
+    }
+  else if (field == field->link)
+    {
+      if (field->buf != 0)
+	free(field->buf);
+    }
+  else
+    {
+      FIELD *f;
+
+      for (f = field; f->link != field; f = f->link)
+	{
+	}
+      f->link = field->link;
+    }
+  _nc_Free_Type(field);
+#if USE_WIDEC_SUPPORT
+  if (field->expanded != 0)
+    {
+      int n;
+
+      for (n = 0; n <= field->nbuf; ++n)
+	{
+	  FreeIfNeeded(field->expanded[n]);
+	}
+      free(field->expanded);
+      (void)delwin(field->working);
+    }
+#endif
+  free(field);
+  RETURN(E_OK);
+}
+
+/* fld_def.c ends here */
diff --git a/apps/lib/curses/pdcurses/form/fld_dup.c b/apps/lib/curses/pdcurses/form/fld_dup.c
new file mode 100644
index 0000000..b8e501b
--- /dev/null
+++ b/apps/lib/curses/pdcurses/form/fld_dup.c
@@ -0,0 +1,101 @@
+/****************************************************************************
+ * Copyright (c) 1998-2007,2010 Free Software Foundation, Inc.              *
+ *                                                                          *
+ * 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, distribute with modifications, sublicense, and/or sell       *
+ * copies of the Software, and to permit persons to whom the Software is    *
+ * furnished to do so, subject to the following conditions:                 *
+ *                                                                          *
+ * The above copyright notice and this permission notice shall be included  *
+ * in all copies or substantial portions of the Software.                   *
+ *                                                                          *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
+ * IN NO EVENT SHALL THE ABOVE 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.                               *
+ *                                                                          *
+ * Except as contained in this notice, the name(s) of the above copyright   *
+ * holders shall not be used in advertising or otherwise to promote the     *
+ * sale, use or other dealings in this Software without prior written       *
+ * authorization.                                                           *
+ ****************************************************************************/
+
+/****************************************************************************
+ *   Author:  Juergen Pfeifer, 1995,1997                                    *
+ ****************************************************************************/
+
+#include "form.priv.h"
+
+MODULE_ID("$Id: fld_dup.c,v 1.13 2010/01/23 21:14:35 tom Exp $")
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  FIELD *dup_field(FIELD *field, int frow, int fcol)
+|
+|   Description   :  Duplicates the field at the specified position. All
+|                    field attributes and the buffers are copied.
+|                    If an error occurs, errno is set to
+|
+|                    E_BAD_ARGUMENT - invalid argument
+|                    E_SYSTEM_ERROR - system error
+|
+|   Return Values :  Pointer to the new field or NULL if failure
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(FIELD *)
+dup_field(FIELD *field, int frow, int fcol)
+{
+  FIELD *New_Field = (FIELD *)0;
+  int err = E_BAD_ARGUMENT;
+
+  T((T_CALLED("dup_field(%p,%d,%d)"), (void *)field, frow, fcol));
+  if (field && (frow >= 0) && (fcol >= 0) &&
+      ((err = E_SYSTEM_ERROR) != 0) &&	/* trick : this resets the default error */
+      (New_Field = typeMalloc(FIELD, 1)))
+    {
+      T((T_CREATE("field %p"), (void *)New_Field));
+      *New_Field = *_nc_Default_Field;
+      New_Field->frow = frow;
+      New_Field->fcol = fcol;
+      New_Field->link = New_Field;
+      New_Field->rows = field->rows;
+      New_Field->cols = field->cols;
+      New_Field->nrow = field->nrow;
+      New_Field->drows = field->drows;
+      New_Field->dcols = field->dcols;
+      New_Field->maxgrow = field->maxgrow;
+      New_Field->nbuf = field->nbuf;
+      New_Field->just = field->just;
+      New_Field->fore = field->fore;
+      New_Field->back = field->back;
+      New_Field->pad = field->pad;
+      New_Field->opts = field->opts;
+      New_Field->usrptr = field->usrptr;
+
+      if (_nc_Copy_Type(New_Field, field))
+	{
+	  size_t i, len;
+
+	  len = Total_Buffer_Size(New_Field);
+	  if ((New_Field->buf = (FIELD_CELL *)malloc(len)))
+	    {
+	      for (i = 0; i < len; ++i)
+		New_Field->buf[i] = field->buf[i];
+	      returnField(New_Field);
+	    }
+	}
+    }
+
+  if (New_Field)
+    free_field(New_Field);
+
+  SET_ERROR(err);
+  returnField((FIELD *)0);
+}
+
+/* fld_dup.c ends here */
diff --git a/apps/lib/curses/pdcurses/form/fld_ftchoice.c b/apps/lib/curses/pdcurses/form/fld_ftchoice.c
new file mode 100644
index 0000000..e628171
--- /dev/null
+++ b/apps/lib/curses/pdcurses/form/fld_ftchoice.c
@@ -0,0 +1,70 @@
+/****************************************************************************
+ * Copyright (c) 1998-2009,2010 Free Software Foundation, Inc.              *
+ *                                                                          *
+ * 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, distribute with modifications, sublicense, and/or sell       *
+ * copies of the Software, and to permit persons to whom the Software is    *
+ * furnished to do so, subject to the following conditions:                 *
+ *                                                                          *
+ * The above copyright notice and this permission notice shall be included  *
+ * in all copies or substantial portions of the Software.                   *
+ *                                                                          *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
+ * IN NO EVENT SHALL THE ABOVE 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.                               *
+ *                                                                          *
+ * Except as contained in this notice, the name(s) of the above copyright   *
+ * holders shall not be used in advertising or otherwise to promote the     *
+ * sale, use or other dealings in this Software without prior written       *
+ * authorization.                                                           *
+ ****************************************************************************/
+
+/****************************************************************************
+ *   Author:  Juergen Pfeifer, 1995,1997                                    *
+ ****************************************************************************/
+
+#include "form.priv.h"
+
+MODULE_ID("$Id: fld_ftchoice.c,v 1.12 2010/01/23 21:14:35 tom Exp $")
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  int set_fieldtype_choice(
+|                          FIELDTYPE *typ,
+|                          bool (* const next_choice)(FIELD *,const void *),
+|                          bool (* const prev_choice)(FIELD *,const void *))
+|
+|   Description   :  Define implementation of enumeration requests.
+|
+|   Return Values :  E_OK           - success
+|                    E_BAD_ARGUMENT - invalid arguments
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(int)
+set_fieldtype_choice(FIELDTYPE *typ,
+		     bool (*const next_choice) (FIELD *, const void *),
+		     bool (*const prev_choice) (FIELD *, const void *))
+{
+  T((T_CALLED("set_fieldtype_choice(%p,%p,%p)"), (void *)typ, next_choice, prev_choice));
+
+  if (!typ || !next_choice || !prev_choice)
+    RETURN(E_BAD_ARGUMENT);
+
+  typ->status |= _HAS_CHOICE;
+#if NCURSES_INTEROP_FUNCS
+  typ->enum_next.onext = next_choice;
+  typ->enum_prev.oprev = prev_choice;
+#else
+  typ->next = next_choice;
+  typ->prev = prev_choice;
+#endif
+  RETURN(E_OK);
+}
+
+/* fld_ftchoice.c ends here */
diff --git a/apps/lib/curses/pdcurses/form/fld_ftlink.c b/apps/lib/curses/pdcurses/form/fld_ftlink.c
new file mode 100644
index 0000000..aa5862f
--- /dev/null
+++ b/apps/lib/curses/pdcurses/form/fld_ftlink.c
@@ -0,0 +1,87 @@
+/****************************************************************************
+ * Copyright (c) 1998-2007,2010 Free Software Foundation, Inc.              *
+ *                                                                          *
+ * 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, distribute with modifications, sublicense, and/or sell       *
+ * copies of the Software, and to permit persons to whom the Software is    *
+ * furnished to do so, subject to the following conditions:                 *
+ *                                                                          *
+ * The above copyright notice and this permission notice shall be included  *
+ * in all copies or substantial portions of the Software.                   *
+ *                                                                          *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
+ * IN NO EVENT SHALL THE ABOVE 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.                               *
+ *                                                                          *
+ * Except as contained in this notice, the name(s) of the above copyright   *
+ * holders shall not be used in advertising or otherwise to promote the     *
+ * sale, use or other dealings in this Software without prior written       *
+ * authorization.                                                           *
+ ****************************************************************************/
+
+/****************************************************************************
+ *   Author:  Juergen Pfeifer, 1995,1997                                    *
+ ****************************************************************************/
+
+#include "form.priv.h"
+
+MODULE_ID("$Id: fld_ftlink.c,v 1.14 2010/01/23 21:14:35 tom Exp $")
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  FIELDTYPE *link_fieldtype(
+|                                FIELDTYPE *type1,
+|                                FIELDTYPE *type2)
+|
+|   Description   :  Create a new fieldtype built from the two given types.
+|                    They are connected by an logical 'OR'.
+|                    If an error occurs, errno is set to
+|                       E_BAD_ARGUMENT  - invalid arguments
+|                       E_SYSTEM_ERROR  - system error (no memory)
+|
+|   Return Values :  Fieldtype pointer or NULL if error occurred.
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(FIELDTYPE *)
+link_fieldtype(FIELDTYPE *type1, FIELDTYPE *type2)
+{
+  FIELDTYPE *nftyp = (FIELDTYPE *)0;
+
+  T((T_CALLED("link_fieldtype(%p,%p)"), (void *)type1, (void *)type2));
+  if (type1 && type2)
+    {
+      nftyp = typeMalloc(FIELDTYPE, 1);
+
+      if (nftyp)
+	{
+	  T((T_CREATE("fieldtype %p"), (void *)nftyp));
+	  *nftyp = *_nc_Default_FieldType;
+	  nftyp->status |= _LINKED_TYPE;
+	  if ((type1->status & _HAS_ARGS) || (type2->status & _HAS_ARGS))
+	    nftyp->status |= _HAS_ARGS;
+	  if ((type1->status & _HAS_CHOICE) || (type2->status & _HAS_CHOICE))
+	    nftyp->status |= _HAS_CHOICE;
+	  nftyp->left = type1;
+	  nftyp->right = type2;
+	  type1->ref++;
+	  type2->ref++;
+	}
+      else
+	{
+	  SET_ERROR(E_SYSTEM_ERROR);
+	}
+    }
+  else
+    {
+      SET_ERROR(E_BAD_ARGUMENT);
+    }
+  returnFieldType(nftyp);
+}
+
+/* fld_ftlink.c ends here */
diff --git a/apps/lib/curses/pdcurses/form/fld_info.c b/apps/lib/curses/pdcurses/form/fld_info.c
new file mode 100644
index 0000000..da95e65
--- /dev/null
+++ b/apps/lib/curses/pdcurses/form/fld_info.c
@@ -0,0 +1,113 @@
+/****************************************************************************
+ * Copyright (c) 1998-2004,2010 Free Software Foundation, Inc.              *
+ *                                                                          *
+ * 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, distribute with modifications, sublicense, and/or sell       *
+ * copies of the Software, and to permit persons to whom the Software is    *
+ * furnished to do so, subject to the following conditions:                 *
+ *                                                                          *
+ * The above copyright notice and this permission notice shall be included  *
+ * in all copies or substantial portions of the Software.                   *
+ *                                                                          *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
+ * IN NO EVENT SHALL THE ABOVE 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.                               *
+ *                                                                          *
+ * Except as contained in this notice, the name(s) of the above copyright   *
+ * holders shall not be used in advertising or otherwise to promote the     *
+ * sale, use or other dealings in this Software without prior written       *
+ * authorization.                                                           *
+ ****************************************************************************/
+
+/****************************************************************************
+ *   Author:  Juergen Pfeifer, 1995,1997                                    *
+ ****************************************************************************/
+
+#include "form.priv.h"
+
+MODULE_ID("$Id: fld_info.c,v 1.11 2010/01/23 21:14:35 tom Exp $")
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  int field_info(const FIELD *field,
+|                                   int *rows, int *cols,
+|                                   int *frow, int *fcol,
+|                                   int *nrow, int *nbuf)
+|
+|   Description   :  Retrieve infos about the fields creation parameters.
+|
+|   Return Values :  E_OK           - success
+|                    E_BAD_ARGUMENT - invalid field pointer
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(int)
+field_info(const FIELD *field,
+	   int *rows, int *cols,
+	   int *frow, int *fcol,
+	   int *nrow, int *nbuf)
+{
+  T((T_CALLED("field_info(%p,%p,%p,%p,%p,%p,%p)"),
+     (const void *)field,
+     (void *)rows, (void *)cols,
+     (void *)frow, (void *)fcol,
+     (void *)nrow, (void *)nbuf));
+
+  if (!field)
+    RETURN(E_BAD_ARGUMENT);
+
+  if (rows)
+    *rows = field->rows;
+  if (cols)
+    *cols = field->cols;
+  if (frow)
+    *frow = field->frow;
+  if (fcol)
+    *fcol = field->fcol;
+  if (nrow)
+    *nrow = field->nrow;
+  if (nbuf)
+    *nbuf = field->nbuf;
+  RETURN(E_OK);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  int dynamic_field_info(const FIELD *field,
+|                                           int *drows, int *dcols,
+|                                           int *maxgrow)
+|
+|   Description   :  Retrieve informations about a dynamic fields current
+|                    dynamic parameters.
+|
+|   Return Values :  E_OK           - success
+|                    E_BAD_ARGUMENT - invalid argument
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(int)
+dynamic_field_info(const FIELD *field, int *drows, int *dcols, int *maxgrow)
+{
+  T((T_CALLED("dynamic_field_info(%p,%p,%p,%p)"),
+     (const void *)field,
+     (void *)drows,
+     (void *)dcols,
+     (void *)maxgrow));
+
+  if (!field)
+    RETURN(E_BAD_ARGUMENT);
+
+  if (drows)
+    *drows = field->drows;
+  if (dcols)
+    *dcols = field->dcols;
+  if (maxgrow)
+    *maxgrow = field->maxgrow;
+
+  RETURN(E_OK);
+}
+
+/* fld_info.c ends here */
diff --git a/apps/lib/curses/pdcurses/form/fld_just.c b/apps/lib/curses/pdcurses/form/fld_just.c
new file mode 100644
index 0000000..a87ea70
--- /dev/null
+++ b/apps/lib/curses/pdcurses/form/fld_just.c
@@ -0,0 +1,86 @@
+/****************************************************************************
+ * Copyright (c) 1998-2004,2010 Free Software Foundation, Inc.              *
+ *                                                                          *
+ * 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, distribute with modifications, sublicense, and/or sell       *
+ * copies of the Software, and to permit persons to whom the Software is    *
+ * furnished to do so, subject to the following conditions:                 *
+ *                                                                          *
+ * The above copyright notice and this permission notice shall be included  *
+ * in all copies or substantial portions of the Software.                   *
+ *                                                                          *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
+ * IN NO EVENT SHALL THE ABOVE 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.                               *
+ *                                                                          *
+ * Except as contained in this notice, the name(s) of the above copyright   *
+ * holders shall not be used in advertising or otherwise to promote the     *
+ * sale, use or other dealings in this Software without prior written       *
+ * authorization.                                                           *
+ ****************************************************************************/
+
+/****************************************************************************
+ *   Author:  Juergen Pfeifer, 1995,1997                                    *
+ ****************************************************************************/
+
+#include "form.priv.h"
+
+MODULE_ID("$Id: fld_just.c,v 1.12 2010/01/23 21:14:35 tom Exp $")
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  int set_field_just(FIELD *field, int just)
+|
+|   Description   :  Set the fields type of justification.
+|
+|   Return Values :  E_OK            - success
+|                    E_BAD_ARGUMENT  - one of the arguments was incorrect
+|                    E_SYSTEM_ERROR  - system error
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(int)
+set_field_just(FIELD *field, int just)
+{
+  int res = E_BAD_ARGUMENT;
+
+  T((T_CALLED("set_field_just(%p,%d)"), (void *)field, just));
+
+  if ((just == NO_JUSTIFICATION) ||
+      (just == JUSTIFY_LEFT) ||
+      (just == JUSTIFY_CENTER) ||
+      (just == JUSTIFY_RIGHT))
+    {
+      Normalize_Field(field);
+      if (field->just != just)
+	{
+	  field->just = just;
+	  res = _nc_Synchronize_Attributes(field);
+	}
+      else
+	res = E_OK;
+    }
+  RETURN(res);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  int field_just( const FIELD *field )
+|
+|   Description   :  Retrieve the fields type of justification
+|
+|   Return Values :  The justification type.
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(int)
+field_just(const FIELD *field)
+{
+  T((T_CALLED("field_just(%p)"), (const void *)field));
+  returnCode(Normalize_Field(field)->just);
+}
+
+/* fld_just.c ends here */
diff --git a/apps/lib/curses/pdcurses/form/fld_link.c b/apps/lib/curses/pdcurses/form/fld_link.c
new file mode 100644
index 0000000..31b9da0
--- /dev/null
+++ b/apps/lib/curses/pdcurses/form/fld_link.c
@@ -0,0 +1,96 @@
+/****************************************************************************
+ * Copyright (c) 1998-2007,2010 Free Software Foundation, Inc.              *
+ *                                                                          *
+ * 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, distribute with modifications, sublicense, and/or sell       *
+ * copies of the Software, and to permit persons to whom the Software is    *
+ * furnished to do so, subject to the following conditions:                 *
+ *                                                                          *
+ * The above copyright notice and this permission notice shall be included  *
+ * in all copies or substantial portions of the Software.                   *
+ *                                                                          *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
+ * IN NO EVENT SHALL THE ABOVE 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.                               *
+ *                                                                          *
+ * Except as contained in this notice, the name(s) of the above copyright   *
+ * holders shall not be used in advertising or otherwise to promote the     *
+ * sale, use or other dealings in this Software without prior written       *
+ * authorization.                                                           *
+ ****************************************************************************/
+
+/****************************************************************************
+ *   Author:  Juergen Pfeifer, 1995,1997                                    *
+ ****************************************************************************/
+
+#include "form.priv.h"
+
+MODULE_ID("$Id: fld_link.c,v 1.12 2010/01/23 21:14:35 tom Exp $")
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  FIELD *link_field(FIELD *field, int frow, int fcol)
+|
+|   Description   :  Duplicates the field at the specified position. The
+|                    new field shares its buffers with the original one,
+|                    the attributes are independent.
+|                    If an error occurs, errno is set to
+|
+|                    E_BAD_ARGUMENT - invalid argument
+|                    E_SYSTEM_ERROR - system error
+|
+|   Return Values :  Pointer to the new field or NULL if failure
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(FIELD *)
+link_field(FIELD *field, int frow, int fcol)
+{
+  FIELD *New_Field = (FIELD *)0;
+  int err = E_BAD_ARGUMENT;
+
+  T((T_CALLED("link_field(%p,%d,%d)"), (void *)field, frow, fcol));
+  if (field && (frow >= 0) && (fcol >= 0) &&
+      ((err = E_SYSTEM_ERROR) != 0) &&	/* trick: this resets the default error */
+      (New_Field = typeMalloc(FIELD, 1)))
+    {
+      T((T_CREATE("field %p"), (void *)New_Field));
+      *New_Field = *_nc_Default_Field;
+      New_Field->frow = frow;
+      New_Field->fcol = fcol;
+
+      New_Field->link = field->link;
+      field->link = New_Field;
+
+      New_Field->buf = field->buf;
+      New_Field->rows = field->rows;
+      New_Field->cols = field->cols;
+      New_Field->nrow = field->nrow;
+      New_Field->nbuf = field->nbuf;
+      New_Field->drows = field->drows;
+      New_Field->dcols = field->dcols;
+      New_Field->maxgrow = field->maxgrow;
+      New_Field->just = field->just;
+      New_Field->fore = field->fore;
+      New_Field->back = field->back;
+      New_Field->pad = field->pad;
+      New_Field->opts = field->opts;
+      New_Field->usrptr = field->usrptr;
+
+      if (_nc_Copy_Type(New_Field, field))
+	returnField(New_Field);
+    }
+
+  if (New_Field)
+    free_field(New_Field);
+
+  SET_ERROR(err);
+  returnField((FIELD *)0);
+}
+
+/* fld_link.c ends here */
diff --git a/apps/lib/curses/pdcurses/form/fld_max.c b/apps/lib/curses/pdcurses/form/fld_max.c
new file mode 100644
index 0000000..91d9819
--- /dev/null
+++ b/apps/lib/curses/pdcurses/form/fld_max.c
@@ -0,0 +1,77 @@
+/****************************************************************************
+ * Copyright (c) 1998-2004,2010 Free Software Foundation, Inc.              *
+ *                                                                          *
+ * 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, distribute with modifications, sublicense, and/or sell       *
+ * copies of the Software, and to permit persons to whom the Software is    *
+ * furnished to do so, subject to the following conditions:                 *
+ *                                                                          *
+ * The above copyright notice and this permission notice shall be included  *
+ * in all copies or substantial portions of the Software.                   *
+ *                                                                          *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
+ * IN NO EVENT SHALL THE ABOVE 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.                               *
+ *                                                                          *
+ * Except as contained in this notice, the name(s) of the above copyright   *
+ * holders shall not be used in advertising or otherwise to promote the     *
+ * sale, use or other dealings in this Software without prior written       *
+ * authorization.                                                           *
+ ****************************************************************************/
+
+/****************************************************************************
+ *   Author:  Juergen Pfeifer, 1995,1997                                    *
+ ****************************************************************************/
+
+#include "form.priv.h"
+
+MODULE_ID("$Id: fld_max.c,v 1.10 2010/01/23 21:14:36 tom Exp $")
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  int set_max_field(FIELD *field, int maxgrow)
+|
+|   Description   :  Set the maximum growth for a dynamic field. If maxgrow=0
+|                    the field may grow to any possible size.
+|
+|   Return Values :  E_OK           - success
+|                    E_BAD_ARGUMENT - invalid argument
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(int)
+set_max_field(FIELD *field, int maxgrow)
+{
+  T((T_CALLED("set_max_field(%p,%d)"), (void *)field, maxgrow));
+
+  if (!field || (maxgrow < 0))
+    RETURN(E_BAD_ARGUMENT);
+  else
+    {
+      bool single_line_field = Single_Line_Field(field);
+
+      if (maxgrow > 0)
+	{
+	  if ((single_line_field && (maxgrow < field->dcols)) ||
+	      (!single_line_field && (maxgrow < field->drows)))
+	    RETURN(E_BAD_ARGUMENT);
+	}
+      field->maxgrow = maxgrow;
+      field->status &= ~_MAY_GROW;
+      if (!(field->opts & O_STATIC))
+	{
+	  if ((maxgrow == 0) ||
+	      (single_line_field && (field->dcols < maxgrow)) ||
+	      (!single_line_field && (field->drows < maxgrow)))
+	    field->status |= _MAY_GROW;
+	}
+    }
+  RETURN(E_OK);
+}
+
+/* fld_max.c ends here */
diff --git a/apps/lib/curses/pdcurses/form/fld_move.c b/apps/lib/curses/pdcurses/form/fld_move.c
new file mode 100644
index 0000000..24652ea
--- /dev/null
+++ b/apps/lib/curses/pdcurses/form/fld_move.c
@@ -0,0 +1,64 @@
+/****************************************************************************
+ * Copyright (c) 1998-2004,2010 Free Software Foundation, Inc.              *
+ *                                                                          *
+ * 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, distribute with modifications, sublicense, and/or sell       *
+ * copies of the Software, and to permit persons to whom the Software is    *
+ * furnished to do so, subject to the following conditions:                 *
+ *                                                                          *
+ * The above copyright notice and this permission notice shall be included  *
+ * in all copies or substantial portions of the Software.                   *
+ *                                                                          *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
+ * IN NO EVENT SHALL THE ABOVE 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.                               *
+ *                                                                          *
+ * Except as contained in this notice, the name(s) of the above copyright   *
+ * holders shall not be used in advertising or otherwise to promote the     *
+ * sale, use or other dealings in this Software without prior written       *
+ * authorization.                                                           *
+ ****************************************************************************/
+
+/****************************************************************************
+ *   Author:  Juergen Pfeifer, 1995,1997                                    *
+ ****************************************************************************/
+
+#include "form.priv.h"
+
+MODULE_ID("$Id: fld_move.c,v 1.10 2010/01/23 21:14:36 tom Exp $")
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  int move_field(FIELD *field,int frow, int fcol)
+|
+|   Description   :  Moves the disconnected field to the new location in
+|                    the forms subwindow.
+|
+|   Return Values :  E_OK            - success
+|                    E_BAD_ARGUMENT  - invalid argument passed
+|                    E_CONNECTED     - field is connected
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(int)
+move_field(FIELD *field, int frow, int fcol)
+{
+  T((T_CALLED("move_field(%p,%d,%d)"), (void *)field, frow, fcol));
+
+  if (!field || (frow < 0) || (fcol < 0))
+    RETURN(E_BAD_ARGUMENT);
+
+  if (field->form)
+    RETURN(E_CONNECTED);
+
+  field->frow = frow;
+  field->fcol = fcol;
+  RETURN(E_OK);
+}
+
+/* fld_move.c ends here */
diff --git a/apps/lib/curses/pdcurses/form/fld_newftyp.c b/apps/lib/curses/pdcurses/form/fld_newftyp.c
new file mode 100644
index 0000000..4351aed
--- /dev/null
+++ b/apps/lib/curses/pdcurses/form/fld_newftyp.c
@@ -0,0 +1,143 @@
+/****************************************************************************
+ * Copyright (c) 1998-2009,2010 Free Software Foundation, Inc.              *
+ *                                                                          *
+ * 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, distribute with modifications, sublicense, and/or sell       *
+ * copies of the Software, and to permit persons to whom the Software is    *
+ * furnished to do so, subject to the following conditions:                 *
+ *                                                                          *
+ * The above copyright notice and this permission notice shall be included  *
+ * in all copies or substantial portions of the Software.                   *
+ *                                                                          *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
+ * IN NO EVENT SHALL THE ABOVE 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.                               *
+ *                                                                          *
+ * Except as contained in this notice, the name(s) of the above copyright   *
+ * holders shall not be used in advertising or otherwise to promote the     *
+ * sale, use or other dealings in this Software without prior written       *
+ * authorization.                                                           *
+ ****************************************************************************/
+
+/****************************************************************************
+ *   Author:  Juergen Pfeifer, 1995,1997                                    *
+ ****************************************************************************/
+
+#include "form.priv.h"
+
+MODULE_ID("$Id: fld_newftyp.c,v 1.19 2010/01/23 21:14:36 tom Exp $")
+
+static FIELDTYPE default_fieldtype =
+{
+  0,				/* status                                      */
+  0L,				/* reference count                             */
+  (FIELDTYPE *)0,		/* pointer to left  operand                    */
+  (FIELDTYPE *)0,		/* pointer to right operand                    */
+  NULL,				/* makearg function                            */
+  NULL,				/* copyarg function                            */
+  NULL,				/* freearg function                            */
+  INIT_FT_FUNC(NULL),		/* field validation function                   */
+  INIT_FT_FUNC(NULL),		/* Character check function                    */
+  INIT_FT_FUNC(NULL),		/* enumerate next function                     */
+  INIT_FT_FUNC(NULL),		/* enumerate previous function                 */
+#if NCURSES_INTEROP_FUNCS
+  NULL				/* generic callback alternative to makearg     */
+#endif
+};
+
+NCURSES_EXPORT_VAR(FIELDTYPE *)
+_nc_Default_FieldType = &default_fieldtype;
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  FIELDTYPE *new_fieldtype(
+|                       bool (* const field_check)(FIELD *,const void *),
+|                       bool (* const char_check) (int, const void *) )
+|
+|   Description   :  Create a new fieldtype. The application programmer must
+|                    write a field_check and a char_check function and give
+|                    them as input to this call.
+|                    If an error occurs, errno is set to
+|                       E_BAD_ARGUMENT  - invalid arguments
+|                       E_SYSTEM_ERROR  - system error (no memory)
+|
+|   Return Values :  Fieldtype pointer or NULL if error occurred
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(FIELDTYPE *)
+new_fieldtype(bool (*const field_check) (FIELD *, const void *),
+	      bool (*const char_check) (int, const void *))
+{
+  FIELDTYPE *nftyp = (FIELDTYPE *)0;
+
+  T((T_CALLED("new_fieldtype(%p,%p)"), field_check, char_check));
+  if ((field_check) || (char_check))
+    {
+      nftyp = typeMalloc(FIELDTYPE, 1);
+
+      if (nftyp)
+	{
+	  T((T_CREATE("fieldtype %p"), (void *)nftyp));
+	  *nftyp = default_fieldtype;
+#if NCURSES_INTEROP_FUNCS
+	  nftyp->fieldcheck.ofcheck = field_check;
+	  nftyp->charcheck.occheck = char_check;
+#else
+	  nftyp->fcheck = field_check;
+	  nftyp->ccheck = char_check;
+#endif
+	}
+      else
+	{
+	  SET_ERROR(E_SYSTEM_ERROR);
+	}
+    }
+  else
+    {
+      SET_ERROR(E_BAD_ARGUMENT);
+    }
+  returnFieldType(nftyp);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  int free_fieldtype(FIELDTYPE *typ)
+|
+|   Description   :  Release the memory associated with this fieldtype.
+|
+|   Return Values :  E_OK            - success
+|                    E_CONNECTED     - there are fields referencing the type
+|                    E_BAD_ARGUMENT  - invalid fieldtype pointer
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(int)
+free_fieldtype(FIELDTYPE *typ)
+{
+  T((T_CALLED("free_fieldtype(%p)"), (void *)typ));
+
+  if (!typ)
+    RETURN(E_BAD_ARGUMENT);
+
+  if (typ->ref != 0)
+    RETURN(E_CONNECTED);
+
+  if (typ->status & _RESIDENT)
+    RETURN(E_CONNECTED);
+
+  if (typ->status & _LINKED_TYPE)
+    {
+      if (typ->left)
+	typ->left->ref--;
+      if (typ->right)
+	typ->right->ref--;
+    }
+  free(typ);
+  RETURN(E_OK);
+}
+
+/* fld_newftyp.c ends here */
diff --git a/apps/lib/curses/pdcurses/form/fld_opts.c b/apps/lib/curses/pdcurses/form/fld_opts.c
new file mode 100644
index 0000000..4e92bd9
--- /dev/null
+++ b/apps/lib/curses/pdcurses/form/fld_opts.c
@@ -0,0 +1,138 @@
+/****************************************************************************
+ * Copyright (c) 1998-2004,2010 Free Software Foundation, Inc.              *
+ *                                                                          *
+ * 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, distribute with modifications, sublicense, and/or sell       *
+ * copies of the Software, and to permit persons to whom the Software is    *
+ * furnished to do so, subject to the following conditions:                 *
+ *                                                                          *
+ * The above copyright notice and this permission notice shall be included  *
+ * in all copies or substantial portions of the Software.                   *
+ *                                                                          *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
+ * IN NO EVENT SHALL THE ABOVE 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.                               *
+ *                                                                          *
+ * Except as contained in this notice, the name(s) of the above copyright   *
+ * holders shall not be used in advertising or otherwise to promote the     *
+ * sale, use or other dealings in this Software without prior written       *
+ * authorization.                                                           *
+ ****************************************************************************/
+
+/****************************************************************************
+ *   Author:  Juergen Pfeifer, 1995,1997                                    *
+ ****************************************************************************/
+
+#include "form.priv.h"
+
+MODULE_ID("$Id: fld_opts.c,v 1.12 2010/01/23 21:14:36 tom Exp $")
+
+/*----------------------------------------------------------------------------
+  Field-Options manipulation routines
+  --------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  int set_field_opts(FIELD *field, Field_Options opts)
+|
+|   Description   :  Turns on the named options for this field and turns
+|                    off all the remaining options.
+|
+|   Return Values :  E_OK            - success
+|                    E_CURRENT       - the field is the current field
+|                    E_BAD_ARGUMENT  - invalid options
+|                    E_SYSTEM_ERROR  - system error
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(int)
+set_field_opts(FIELD *field, Field_Options opts)
+{
+  int res = E_BAD_ARGUMENT;
+
+  T((T_CALLED("set_field_opts(%p,%d)"), (void *)field, opts));
+
+  opts &= ALL_FIELD_OPTS;
+  if (!(opts & ~ALL_FIELD_OPTS))
+    res = _nc_Synchronize_Options(Normalize_Field(field), opts);
+  RETURN(res);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  Field_Options field_opts(const FIELD *field)
+|
+|   Description   :  Retrieve the fields options.
+|
+|   Return Values :  The options.
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(Field_Options)
+field_opts(const FIELD *field)
+{
+  T((T_CALLED("field_opts(%p)"), (const void *)field));
+
+  returnCode(ALL_FIELD_OPTS & Normalize_Field(field)->opts);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  int field_opts_on(FIELD *field, Field_Options opts)
+|
+|   Description   :  Turns on the named options for this field and all the
+|                    remaining options are unchanged.
+|
+|   Return Values :  E_OK            - success
+|                    E_CURRENT       - the field is the current field
+|                    E_BAD_ARGUMENT  - invalid options
+|                    E_SYSTEM_ERROR  - system error
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(int)
+field_opts_on(FIELD *field, Field_Options opts)
+{
+  int res = E_BAD_ARGUMENT;
+
+  T((T_CALLED("field_opts_on(%p,%d)"), (void *)field, opts));
+
+  opts &= ALL_FIELD_OPTS;
+  if (!(opts & ~ALL_FIELD_OPTS))
+    {
+      Normalize_Field(field);
+      res = _nc_Synchronize_Options(field, field->opts | opts);
+    }
+  RETURN(res);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  int field_opts_off(FIELD *field, Field_Options opts)
+|
+|   Description   :  Turns off the named options for this field and all the
+|                    remaining options are unchanged.
+|
+|   Return Values :  E_OK            - success
+|                    E_CURRENT       - the field is the current field
+|                    E_BAD_ARGUMENT  - invalid options
+|                    E_SYSTEM_ERROR  - system error
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(int)
+field_opts_off(FIELD *field, Field_Options opts)
+{
+  int res = E_BAD_ARGUMENT;
+
+  T((T_CALLED("field_opts_off(%p,%d)"), (void *)field, opts));
+
+  opts &= ALL_FIELD_OPTS;
+  if (!(opts & ~ALL_FIELD_OPTS))
+    {
+      Normalize_Field(field);
+      res = _nc_Synchronize_Options(field, field->opts & ~opts);
+    }
+  RETURN(res);
+}
+
+/* fld_opts.c ends here */
diff --git a/apps/lib/curses/pdcurses/form/fld_pad.c b/apps/lib/curses/pdcurses/form/fld_pad.c
new file mode 100644
index 0000000..37df703
--- /dev/null
+++ b/apps/lib/curses/pdcurses/form/fld_pad.c
@@ -0,0 +1,85 @@
+/****************************************************************************
+ * Copyright (c) 1998-2004,2010 Free Software Foundation, Inc.              *
+ *                                                                          *
+ * 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, distribute with modifications, sublicense, and/or sell       *
+ * copies of the Software, and to permit persons to whom the Software is    *
+ * furnished to do so, subject to the following conditions:                 *
+ *                                                                          *
+ * The above copyright notice and this permission notice shall be included  *
+ * in all copies or substantial portions of the Software.                   *
+ *                                                                          *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
+ * IN NO EVENT SHALL THE ABOVE 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.                               *
+ *                                                                          *
+ * Except as contained in this notice, the name(s) of the above copyright   *
+ * holders shall not be used in advertising or otherwise to promote the     *
+ * sale, use or other dealings in this Software without prior written       *
+ * authorization.                                                           *
+ ****************************************************************************/
+
+/****************************************************************************
+ *   Author:  Juergen Pfeifer, 1995,1997                                    *
+ ****************************************************************************/
+
+#include "form.priv.h"
+
+MODULE_ID("$Id: fld_pad.c,v 1.10 2010/01/23 21:14:36 tom Exp $")
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  int set_field_pad(FIELD *field, int ch)
+|
+|   Description   :  Set the pad character used to fill the field. This must
+|                    be a printable character.
+|
+|   Return Values :  E_OK           - success
+|                    E_BAD_ARGUMENT - invalid field pointer or pad character
+|                    E_SYSTEM_ERROR - system error
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(int)
+set_field_pad(FIELD *field, int ch)
+{
+  int res = E_BAD_ARGUMENT;
+
+  T((T_CALLED("set_field_pad(%p,%d)"), (void *)field, ch));
+
+  Normalize_Field(field);
+  if (isprint(UChar(ch)))
+    {
+      if (field->pad != ch)
+	{
+	  field->pad = ch;
+	  res = _nc_Synchronize_Attributes(field);
+	}
+      else
+	res = E_OK;
+    }
+  RETURN(res);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  int field_pad(const FIELD *field)
+|
+|   Description   :  Retrieve the fields pad character.
+|
+|   Return Values :  The pad character.
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(int)
+field_pad(const FIELD *field)
+{
+  T((T_CALLED("field_pad(%p)"), (const void *)field));
+
+  returnCode(Normalize_Field(field)->pad);
+}
+
+/* fld_pad.c ends here */
diff --git a/apps/lib/curses/pdcurses/form/fld_page.c b/apps/lib/curses/pdcurses/form/fld_page.c
new file mode 100644
index 0000000..67f48a1
--- /dev/null
+++ b/apps/lib/curses/pdcurses/form/fld_page.c
@@ -0,0 +1,82 @@
+/****************************************************************************
+ * Copyright (c) 1998-2004,2010 Free Software Foundation, Inc.              *
+ *                                                                          *
+ * 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, distribute with modifications, sublicense, and/or sell       *
+ * copies of the Software, and to permit persons to whom the Software is    *
+ * furnished to do so, subject to the following conditions:                 *
+ *                                                                          *
+ * The above copyright notice and this permission notice shall be included  *
+ * in all copies or substantial portions of the Software.                   *
+ *                                                                          *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
+ * IN NO EVENT SHALL THE ABOVE 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.                               *
+ *                                                                          *
+ * Except as contained in this notice, the name(s) of the above copyright   *
+ * holders shall not be used in advertising or otherwise to promote the     *
+ * sale, use or other dealings in this Software without prior written       *
+ * authorization.                                                           *
+ ****************************************************************************/
+
+/****************************************************************************
+ *   Author:  Juergen Pfeifer, 1995,1997                                    *
+ ****************************************************************************/
+
+#include "form.priv.h"
+
+MODULE_ID("$Id: fld_page.c,v 1.10 2010/01/23 21:14:36 tom Exp $")
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  int set_new_page(FIELD *field, bool new_page_flag)
+|
+|   Description   :  Marks the field as the beginning of a new page of
+|                    the form.
+|
+|   Return Values :  E_OK         - success
+|                    E_CONNECTED  - field is connected
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(int)
+set_new_page(FIELD *field, bool new_page_flag)
+{
+  T((T_CALLED("set_new_page(%p,%d)"), (void *)field, new_page_flag));
+
+  Normalize_Field(field);
+  if (field->form)
+    RETURN(E_CONNECTED);
+
+  if (new_page_flag)
+    field->status |= _NEWPAGE;
+  else
+    field->status &= ~_NEWPAGE;
+
+  RETURN(E_OK);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  bool new_page(const FIELD *field)
+|
+|   Description   :  Retrieve the info whether or not the field starts a
+|                    new page on the form.
+|
+|   Return Values :  TRUE  - field starts a new page
+|                    FALSE - field doesn't start a new page
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(bool)
+new_page(const FIELD *field)
+{
+  T((T_CALLED("new_page(%p)"), (const void *)field));
+
+  returnBool((Normalize_Field(field)->status & _NEWPAGE) ? TRUE : FALSE);
+}
+
+/* fld_page.c ends here */
diff --git a/apps/lib/curses/pdcurses/form/fld_stat.c b/apps/lib/curses/pdcurses/form/fld_stat.c
new file mode 100644
index 0000000..bc5ba50
--- /dev/null
+++ b/apps/lib/curses/pdcurses/form/fld_stat.c
@@ -0,0 +1,79 @@
+/****************************************************************************
+ * Copyright (c) 1998-2004,2010 Free Software Foundation, Inc.              *
+ *                                                                          *
+ * 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, distribute with modifications, sublicense, and/or sell       *
+ * copies of the Software, and to permit persons to whom the Software is    *
+ * furnished to do so, subject to the following conditions:                 *
+ *                                                                          *
+ * The above copyright notice and this permission notice shall be included  *
+ * in all copies or substantial portions of the Software.                   *
+ *                                                                          *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
+ * IN NO EVENT SHALL THE ABOVE 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.                               *
+ *                                                                          *
+ * Except as contained in this notice, the name(s) of the above copyright   *
+ * holders shall not be used in advertising or otherwise to promote the     *
+ * sale, use or other dealings in this Software without prior written       *
+ * authorization.                                                           *
+ ****************************************************************************/
+
+/****************************************************************************
+ *   Author:  Juergen Pfeifer, 1995,1997                                    *
+ ****************************************************************************/
+
+#include "form.priv.h"
+
+MODULE_ID("$Id: fld_stat.c,v 1.12 2010/01/23 21:14:36 tom Exp $")
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  int set_field_status(FIELD *field, bool status)
+|
+|   Description   :  Set or clear the 'changed' indication flag for that
+|                    fields primary buffer.
+|
+|   Return Values :  E_OK            - success
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(int)
+set_field_status(FIELD *field, bool status)
+{
+  T((T_CALLED("set_field_status(%p,%d)"), (void *)field, status));
+
+  Normalize_Field(field);
+
+  if (status)
+    field->status |= _CHANGED;
+  else
+    field->status &= ~_CHANGED;
+
+  RETURN(E_OK);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  bool field_status(const FIELD *field)
+|
+|   Description   :  Retrieve the value of the 'changed' indication flag
+|                    for that fields primary buffer.
+|
+|   Return Values :  TRUE  - buffer has been changed
+|                    FALSE - buffer has not been changed
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(bool)
+field_status(const FIELD *field)
+{
+  T((T_CALLED("field_status(%p)"), (const void *)field));
+
+  returnBool((Normalize_Field(field)->status & _CHANGED) ? TRUE : FALSE);
+}
+
+/* fld_stat.c ends here */
diff --git a/apps/lib/curses/pdcurses/form/fld_type.c b/apps/lib/curses/pdcurses/form/fld_type.c
new file mode 100644
index 0000000..1117a56
--- /dev/null
+++ b/apps/lib/curses/pdcurses/form/fld_type.c
@@ -0,0 +1,97 @@
+/****************************************************************************
+ * Copyright (c) 1998-2004,2010 Free Software Foundation, Inc.              *
+ *                                                                          *
+ * 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, distribute with modifications, sublicense, and/or sell       *
+ * copies of the Software, and to permit persons to whom the Software is    *
+ * furnished to do so, subject to the following conditions:                 *
+ *                                                                          *
+ * The above copyright notice and this permission notice shall be included  *
+ * in all copies or substantial portions of the Software.                   *
+ *                                                                          *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
+ * IN NO EVENT SHALL THE ABOVE 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.                               *
+ *                                                                          *
+ * Except as contained in this notice, the name(s) of the above copyright   *
+ * holders shall not be used in advertising or otherwise to promote the     *
+ * sale, use or other dealings in this Software without prior written       *
+ * authorization.                                                           *
+ ****************************************************************************/
+
+/****************************************************************************
+ *   Author:  Juergen Pfeifer, 1995,1997                                    *
+ ****************************************************************************/
+
+#include "form.priv.h"
+
+MODULE_ID("$Id: fld_type.c,v 1.16 2010/01/23 21:14:36 tom Exp $")
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  int set_field_type(FIELD *field, FIELDTYPE *type,...)
+|
+|   Description   :  Associate the specified fieldtype with the field.
+|                    Certain field types take additional arguments. Look
+|                    at the spec of the field types !
+|
+|   Return Values :  E_OK           - success
+|                    E_SYSTEM_ERROR - system error
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(int)
+set_field_type(FIELD *field, FIELDTYPE *type,...)
+{
+  va_list ap;
+  int res = E_SYSTEM_ERROR;
+  int err = 0;
+
+  T((T_CALLED("set_field_type(%p,%p)"), (void *)field, (void *)type));
+
+  va_start(ap, type);
+
+  Normalize_Field(field);
+  _nc_Free_Type(field);
+
+  field->type = type;
+  field->arg = (void *)_nc_Make_Argument(field->type, &ap, &err);
+
+  if (err)
+    {
+      _nc_Free_Argument(field->type, (TypeArgument *)(field->arg));
+      field->type = (FIELDTYPE *)0;
+      field->arg = (void *)0;
+    }
+  else
+    {
+      res = E_OK;
+      if (field->type)
+	field->type->ref++;
+    }
+
+  va_end(ap);
+  RETURN(res);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  FIELDTYPE *field_type(const FIELD *field)
+|
+|   Description   :  Retrieve the associated fieldtype for this field.
+|
+|   Return Values :  Pointer to fieldtype of NULL if none is defined.
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(FIELDTYPE *)
+field_type(const FIELD *field)
+{
+  T((T_CALLED("field_type(%p)"), (const void *)field));
+  returnFieldType(Normalize_Field(field)->type);
+}
+
+/* fld_type.c ends here */
diff --git a/apps/lib/curses/pdcurses/form/fld_user.c b/apps/lib/curses/pdcurses/form/fld_user.c
new file mode 100644
index 0000000..075580b
--- /dev/null
+++ b/apps/lib/curses/pdcurses/form/fld_user.c
@@ -0,0 +1,72 @@
+/****************************************************************************
+ * Copyright (c) 1998-2004,2010 Free Software Foundation, Inc.              *
+ *                                                                          *
+ * 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, distribute with modifications, sublicense, and/or sell       *
+ * copies of the Software, and to permit persons to whom the Software is    *
+ * furnished to do so, subject to the following conditions:                 *
+ *                                                                          *
+ * The above copyright notice and this permission notice shall be included  *
+ * in all copies or substantial portions of the Software.                   *
+ *                                                                          *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
+ * IN NO EVENT SHALL THE ABOVE 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.                               *
+ *                                                                          *
+ * Except as contained in this notice, the name(s) of the above copyright   *
+ * holders shall not be used in advertising or otherwise to promote the     *
+ * sale, use or other dealings in this Software without prior written       *
+ * authorization.                                                           *
+ ****************************************************************************/
+
+/****************************************************************************
+ *   Author:  Juergen Pfeifer, 1995,1997                                    *
+ ****************************************************************************/
+
+#include "form.priv.h"
+
+MODULE_ID("$Id: fld_user.c,v 1.16 2010/01/23 21:14:36 tom Exp $")
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  int set_field_userptr(FIELD *field, void *usrptr)
+|
+|   Description   :  Set the pointer that is reserved in any field to store
+|                    application relevant informations
+|
+|   Return Values :  E_OK         - on success
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(int)
+set_field_userptr(FIELD *field, void *usrptr)
+{
+  T((T_CALLED("set_field_userptr(%p,%p)"), (void *)field, (void *)usrptr));
+
+  Normalize_Field(field)->usrptr = usrptr;
+  RETURN(E_OK);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  void *field_userptr(const FIELD *field)
+|
+|   Description   :  Return the pointer that is reserved in any field to
+|                    store application relevant informations.
+|
+|   Return Values :  Value of pointer. If no such pointer has been set,
+|                    NULL is returned
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(void *)
+field_userptr(const FIELD *field)
+{
+  T((T_CALLED("field_userptr(%p)"), (const void *)field));
+  returnVoidPtr(Normalize_Field(field)->usrptr);
+}
+
+/* fld_user.c ends here */
diff --git a/apps/lib/curses/pdcurses/form/form.h b/apps/lib/curses/pdcurses/form/form.h
new file mode 100644
index 0000000..d7bb85a
--- /dev/null
+++ b/apps/lib/curses/pdcurses/form/form.h
@@ -0,0 +1,423 @@
+/****************************************************************************
+ * Copyright (c) 1998-2004,2009 Free Software Foundation, Inc.              *
+ *                                                                          *
+ * 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, distribute with modifications, sublicense, and/or sell       *
+ * copies of the Software, and to permit persons to whom the Software is    *
+ * furnished to do so, subject to the following conditions:                 *
+ *                                                                          *
+ * The above copyright notice and this permission notice shall be included  *
+ * in all copies or substantial portions of the Software.                   *
+ *                                                                          *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
+ * IN NO EVENT SHALL THE ABOVE 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.                               *
+ *                                                                          *
+ * Except as contained in this notice, the name(s) of the above copyright   *
+ * holders shall not be used in advertising or otherwise to promote the     *
+ * sale, use or other dealings in this Software without prior written       *
+ * authorization.                                                           *
+ ****************************************************************************/
+
+/****************************************************************************
+ *   Author:  Juergen Pfeifer, 1995,1997                                    *
+ ****************************************************************************/
+
+/* $Id: form.h,v 0.21 2009/11/07 19:31:11 tom Exp $ */
+
+#ifndef FORM_H
+#define FORM_H
+
+#include <curses.h>
+#include <eti.h>
+#include <ncurses_cfg.h>
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+#ifndef FORM_PRIV_H
+typedef void *FIELD_CELL;
+#endif
+
+#ifndef NCURSES_FIELD_INTERNALS
+#define NCURSES_FIELD_INTERNALS /* nothing */
+#endif
+
+typedef int Form_Options;
+typedef int Field_Options;
+
+	/**********
+	*  _PAGE  *
+	**********/
+
+typedef struct {
+  short pmin;		/* index of first field on page			*/
+  short pmax;		/* index of last field on page			*/
+  short smin;		/* index of top leftmost field on page		*/
+  short smax;		/* index of bottom rightmost field on page	*/
+} _PAGE;
+
+	/**********
+	*  FIELD  *
+	**********/
+
+typedef struct fieldnode {
+  unsigned short	status;		/* flags			*/
+  short			rows;		/* size in rows			*/
+  short			cols;		/* size in cols			*/
+  short			frow;		/* first row			*/
+  short			fcol;		/* first col			*/
+  int			drows;		/* dynamic rows			*/
+  int			dcols;		/* dynamic cols			*/
+  int			maxgrow;	/* maximum field growth		*/
+  int			nrow;		/* off-screen rows		*/
+  short			nbuf;		/* additional buffers		*/
+  short			just;		/* justification		*/
+  short			page;		/* page on form			*/
+  short			index;		/* into form -> field		*/
+  int			pad;		/* pad character		*/
+  chtype		fore;		/* foreground attribute		*/
+  chtype		back;		/* background attribute		*/
+  Field_Options		opts;		/* options			*/
+  struct fieldnode *	snext;		/* sorted order pointer		*/
+  struct fieldnode *	sprev;		/* sorted order pointer		*/
+  struct fieldnode *	link;		/* linked field chain		*/
+  struct formnode *	form;		/* containing form		*/
+  struct typenode *	type;		/* field type			*/
+  void *		arg;		/* argument for type		*/
+  FIELD_CELL *		buf;		/* field buffers		*/
+  void *		usrptr;		/* user pointer			*/
+  /*
+   * The wide-character configuration requires extra information.  Because
+   * there are existing applications that manipulate the members of FIELD
+   * directly, we cannot make the struct opaque.  Offsets of members up to
+   * this point are the same in the narrow- and wide-character configuration.
+   * But note that the type of buf depends on the configuration, and is made
+   * opaque for that reason.
+   */
+  NCURSES_FIELD_INTERNALS
+} FIELD;
+
+
+	/*********
+	*  FORM  *
+	*********/
+
+typedef struct formnode {
+  unsigned short	status;	  	/* flags			*/
+  short			rows;		/* size in rows			*/
+  short			cols;		/* size in cols			*/
+  int			currow;		/* current row in field window	*/
+  int			curcol;		/* current col in field window	*/
+  int			toprow;		/* in scrollable field window	*/
+  int			begincol;	/* in horiz. scrollable field	*/
+  short			maxfield;	/* number of fields		*/
+  short			maxpage;	/* number of pages		*/
+  short			curpage;	/* index into page		*/
+  Form_Options		opts;		/* options			*/
+  WINDOW *		win;		/* window			*/
+  WINDOW *		sub;		/* subwindow			*/
+  WINDOW *		w;		/* window for current field	*/
+  FIELD **		field;		/* field [maxfield]		*/
+  FIELD *		current;	/* current field		*/
+  _PAGE *		page;		/* page [maxpage]		*/
+  void *		usrptr;		/* user pointer			*/
+
+  void			(*forminit)(struct formnode *);
+  void			(*formterm)(struct formnode *);
+  void			(*fieldinit)(struct formnode *);
+  void			(*fieldterm)(struct formnode *);
+
+} FORM;
+
+
+	/**************
+	*  FIELDTYPE  *
+	**************/
+
+typedef struct typenode {
+  unsigned short	status;			/* flags		    */
+  long			ref;			/* reference count	    */
+  struct typenode *	left;			/* ptr to operand for |     */
+  struct typenode *	right;			/* ptr to operand for |     */
+
+  void* (*makearg)(va_list *);			/* make fieldtype arg	    */
+  void* (*copyarg)(const void *);		/* copy fieldtype arg 	    */
+  void	(*freearg)(void *);			/* free fieldtype arg	    */
+
+#if NCURSES_INTEROP_FUNCS
+  union {
+    bool (*ofcheck)(FIELD *,const void *);	/* field validation	    */
+    bool (*gfcheck)(FORM*,FIELD *,const void*);	/* generic field validation */
+  } fieldcheck;
+  union {
+    bool (*occheck)(int,const void *);		/* character validation     */
+    bool (*gccheck)(int,FORM*,
+		    FIELD*,const void*);        /* generic char validation  */
+  } charcheck;
+  union {
+    bool (*onext)(FIELD *,const void *);        /* enumerate next value     */
+    bool (*gnext)(FORM*,FIELD*,const void*);    /* generic enumerate next   */
+  } enum_next;
+  union {
+    bool (*oprev)(FIELD *,const void *);	/* enumerate prev value     */
+    bool (*gprev)(FORM*,FIELD*,const void*);    /* generic enumerate prev   */
+  } enum_prev;
+  void* (*genericarg)(void*);                   /* Alternate Arg method     */
+#else
+  bool	(*fcheck)(FIELD *,const void *);	/* field validation	*/
+  bool	(*ccheck)(int,const void *);		/* character validation */
+
+  bool	(*next)(FIELD *,const void *);		/* enumerate next value */
+  bool	(*prev)(FIELD *,const void *);		/* enumerate prev value */
+#endif
+} FIELDTYPE;
+
+typedef void (*Form_Hook)(FORM *);
+
+	/***************************
+	*  miscellaneous #defines  *
+	***************************/
+
+/* field justification */
+#define NO_JUSTIFICATION	(0)
+#define JUSTIFY_LEFT		(1)
+#define JUSTIFY_CENTER		(2)
+#define JUSTIFY_RIGHT		(3)
+
+/* field options */
+#define O_VISIBLE		(0x0001U)
+#define O_ACTIVE		(0x0002U)
+#define O_PUBLIC		(0x0004U)
+#define O_EDIT			(0x0008U)
+#define O_WRAP			(0x0010U)
+#define O_BLANK			(0x0020U)
+#define O_AUTOSKIP		(0x0040U)
+#define O_NULLOK		(0x0080U)
+#define O_PASSOK		(0x0100U)
+#define O_STATIC		(0x0200U)
+
+/* form options */
+#define O_NL_OVERLOAD		(0x0001U)
+#define O_BS_OVERLOAD		(0x0002U)
+
+/* form driver commands */
+#define REQ_NEXT_PAGE	 (KEY_MAX + 1)	/* move to next page		*/
+#define REQ_PREV_PAGE	 (KEY_MAX + 2)	/* move to previous page	*/
+#define REQ_FIRST_PAGE	 (KEY_MAX + 3)	/* move to first page		*/
+#define REQ_LAST_PAGE	 (KEY_MAX + 4)	/* move to last page		*/
+
+#define REQ_NEXT_FIELD	 (KEY_MAX + 5)	/* move to next field		*/
+#define REQ_PREV_FIELD	 (KEY_MAX + 6)	/* move to previous field	*/
+#define REQ_FIRST_FIELD	 (KEY_MAX + 7)	/* move to first field		*/
+#define REQ_LAST_FIELD	 (KEY_MAX + 8)	/* move to last field		*/
+#define REQ_SNEXT_FIELD	 (KEY_MAX + 9)	/* move to sorted next field	*/
+#define REQ_SPREV_FIELD	 (KEY_MAX + 10)	/* move to sorted prev field	*/
+#define REQ_SFIRST_FIELD (KEY_MAX + 11)	/* move to sorted first field	*/
+#define REQ_SLAST_FIELD	 (KEY_MAX + 12)	/* move to sorted last field	*/
+#define REQ_LEFT_FIELD	 (KEY_MAX + 13)	/* move to left to field	*/
+#define REQ_RIGHT_FIELD	 (KEY_MAX + 14)	/* move to right to field	*/
+#define REQ_UP_FIELD	 (KEY_MAX + 15)	/* move to up to field		*/
+#define REQ_DOWN_FIELD	 (KEY_MAX + 16)	/* move to down to field	*/
+
+#define REQ_NEXT_CHAR	 (KEY_MAX + 17)	/* move to next char in field	*/
+#define REQ_PREV_CHAR	 (KEY_MAX + 18)	/* move to prev char in field	*/
+#define REQ_NEXT_LINE	 (KEY_MAX + 19)	/* move to next line in field	*/
+#define REQ_PREV_LINE	 (KEY_MAX + 20)	/* move to prev line in field	*/
+#define REQ_NEXT_WORD	 (KEY_MAX + 21)	/* move to next word in field	*/
+#define REQ_PREV_WORD	 (KEY_MAX + 22)	/* move to prev word in field	*/
+#define REQ_BEG_FIELD	 (KEY_MAX + 23)	/* move to first char in field	*/
+#define REQ_END_FIELD	 (KEY_MAX + 24)	/* move after last char in fld	*/
+#define REQ_BEG_LINE	 (KEY_MAX + 25)	/* move to beginning of line	*/
+#define REQ_END_LINE	 (KEY_MAX + 26)	/* move after last char in line	*/
+#define REQ_LEFT_CHAR	 (KEY_MAX + 27)	/* move left in field		*/
+#define REQ_RIGHT_CHAR	 (KEY_MAX + 28)	/* move right in field		*/
+#define REQ_UP_CHAR	 (KEY_MAX + 29)	/* move up in field		*/
+#define REQ_DOWN_CHAR	 (KEY_MAX + 30)	/* move down in field		*/
+
+#define REQ_NEW_LINE	 (KEY_MAX + 31)	/* insert/overlay new line	*/
+#define REQ_INS_CHAR	 (KEY_MAX + 32)	/* insert blank char at cursor	*/
+#define REQ_INS_LINE	 (KEY_MAX + 33)	/* insert blank line at cursor	*/
+#define REQ_DEL_CHAR	 (KEY_MAX + 34)	/* delete char at cursor	*/
+#define REQ_DEL_PREV	 (KEY_MAX + 35)	/* delete char before cursor	*/
+#define REQ_DEL_LINE	 (KEY_MAX + 36)	/* delete line at cursor	*/
+#define REQ_DEL_WORD	 (KEY_MAX + 37)	/* delete word at cursor	*/
+#define REQ_CLR_EOL	 (KEY_MAX + 38)	/* clear to end of line		*/
+#define REQ_CLR_EOF	 (KEY_MAX + 39)	/* clear to end of field	*/
+#define REQ_CLR_FIELD	 (KEY_MAX + 40)	/* clear entire field		*/
+#define REQ_OVL_MODE	 (KEY_MAX + 41)	/* begin overlay mode		*/
+#define REQ_INS_MODE	 (KEY_MAX + 42)	/* begin insert mode		*/
+#define REQ_SCR_FLINE	 (KEY_MAX + 43)	/* scroll field forward a line	*/
+#define REQ_SCR_BLINE	 (KEY_MAX + 44)	/* scroll field backward a line	*/
+#define REQ_SCR_FPAGE	 (KEY_MAX + 45)	/* scroll field forward a page	*/
+#define REQ_SCR_BPAGE	 (KEY_MAX + 46)	/* scroll field backward a page	*/
+#define REQ_SCR_FHPAGE	 (KEY_MAX + 47) /* scroll field forward	 half page */
+#define REQ_SCR_BHPAGE	 (KEY_MAX + 48) /* scroll field backward half page */
+#define REQ_SCR_FCHAR	 (KEY_MAX + 49) /* horizontal scroll char	*/
+#define REQ_SCR_BCHAR	 (KEY_MAX + 50) /* horizontal scroll char	*/
+#define REQ_SCR_HFLINE	 (KEY_MAX + 51) /* horizontal scroll line	*/
+#define REQ_SCR_HBLINE	 (KEY_MAX + 52) /* horizontal scroll line	*/
+#define REQ_SCR_HFHALF	 (KEY_MAX + 53) /* horizontal scroll half line	*/
+#define REQ_SCR_HBHALF	 (KEY_MAX + 54) /* horizontal scroll half line	*/
+
+#define REQ_VALIDATION	 (KEY_MAX + 55)	/* validate field		*/
+#define REQ_NEXT_CHOICE	 (KEY_MAX + 56)	/* display next field choice	*/
+#define REQ_PREV_CHOICE	 (KEY_MAX + 57)	/* display prev field choice	*/
+
+#define MIN_FORM_COMMAND (KEY_MAX + 1)	/* used by form_driver		*/
+#define MAX_FORM_COMMAND (KEY_MAX + 57)	/* used by form_driver		*/
+
+#if defined(MAX_COMMAND)
+#  if (MAX_FORM_COMMAND > MAX_COMMAND)
+#    error Something is wrong -- MAX_FORM_COMMAND is greater than MAX_COMMAND
+#  elif (MAX_COMMAND != (KEY_MAX + 128))
+#    error Something is wrong -- MAX_COMMAND is already inconsistently defined.
+#  endif
+#else
+#  define MAX_COMMAND (KEY_MAX + 128)
+#endif
+
+	/*************************
+	*  standard field types  *
+	*************************/
+extern NCURSES_EXPORT_VAR(FIELDTYPE *) TYPE_ALPHA;
+extern NCURSES_EXPORT_VAR(FIELDTYPE *) TYPE_ALNUM;
+extern NCURSES_EXPORT_VAR(FIELDTYPE *) TYPE_ENUM;
+extern NCURSES_EXPORT_VAR(FIELDTYPE *) TYPE_INTEGER;
+extern NCURSES_EXPORT_VAR(FIELDTYPE *) TYPE_NUMERIC;
+extern NCURSES_EXPORT_VAR(FIELDTYPE *) TYPE_REGEXP;
+
+	/************************************
+	*  built-in additional field types  *
+	*  They are not defined in SVr4     *
+	************************************/
+extern NCURSES_EXPORT_VAR(FIELDTYPE *) TYPE_IPV4;      /* Internet IP Version 4 address */
+
+	/***********************
+	*  FIELDTYPE routines  *
+	***********************/
+extern NCURSES_EXPORT(FIELDTYPE *) new_fieldtype (
+		    bool (* const field_check)(FIELD *,const void *),
+		    bool (* const char_check)(int,const void *));
+extern NCURSES_EXPORT(FIELDTYPE *) link_fieldtype(
+		    FIELDTYPE *, FIELDTYPE *);
+
+extern NCURSES_EXPORT(int)	free_fieldtype (FIELDTYPE *);
+extern NCURSES_EXPORT(int)	set_fieldtype_arg (FIELDTYPE *,
+		    void * (* const make_arg)(va_list *),
+		    void * (* const copy_arg)(const void *),
+		    void (* const free_arg)(void *));
+extern NCURSES_EXPORT(int)	 set_fieldtype_choice (FIELDTYPE *,
+		    bool (* const next_choice)(FIELD *,const void *),
+	      	    bool (* const prev_choice)(FIELD *,const void *));
+
+	/*******************
+	*  FIELD routines  *
+	*******************/
+extern NCURSES_EXPORT(FIELD *)	new_field (int,int,int,int,int,int);
+extern NCURSES_EXPORT(FIELD *)	dup_field (FIELD *,int,int);
+extern NCURSES_EXPORT(FIELD *)	link_field (FIELD *,int,int);
+
+extern NCURSES_EXPORT(int)	free_field (FIELD *);
+extern NCURSES_EXPORT(int)	field_info (const FIELD *,int *,int *,int *,int *,int *,int *);
+extern NCURSES_EXPORT(int)	dynamic_field_info (const FIELD *,int *,int *,int *);
+extern NCURSES_EXPORT(int)	set_max_field ( FIELD *,int);
+extern NCURSES_EXPORT(int)	move_field (FIELD *,int,int);
+extern NCURSES_EXPORT(int)	set_field_type (FIELD *,FIELDTYPE *,...);
+extern NCURSES_EXPORT(int)	set_new_page (FIELD *,bool);
+extern NCURSES_EXPORT(int)	set_field_just (FIELD *,int);
+extern NCURSES_EXPORT(int)	field_just (const FIELD *);
+extern NCURSES_EXPORT(int)	set_field_fore (FIELD *,chtype);
+extern NCURSES_EXPORT(int)	set_field_back (FIELD *,chtype);
+extern NCURSES_EXPORT(int)	set_field_pad (FIELD *,int);
+extern NCURSES_EXPORT(int)	field_pad (const FIELD *);
+extern NCURSES_EXPORT(int)	set_field_buffer (FIELD *,int,const char *);
+extern NCURSES_EXPORT(int)	set_field_status (FIELD *,bool);
+extern NCURSES_EXPORT(int)	set_field_userptr (FIELD *, void *);
+extern NCURSES_EXPORT(int)	set_field_opts (FIELD *,Field_Options);
+extern NCURSES_EXPORT(int)	field_opts_on (FIELD *,Field_Options);
+extern NCURSES_EXPORT(int)	field_opts_off (FIELD *,Field_Options);
+
+extern NCURSES_EXPORT(chtype)	field_fore (const FIELD *);
+extern NCURSES_EXPORT(chtype)	field_back (const FIELD *);
+
+extern NCURSES_EXPORT(bool)	new_page (const FIELD *);
+extern NCURSES_EXPORT(bool)	field_status (const FIELD *);
+
+extern NCURSES_EXPORT(void *)	field_arg (const FIELD *);
+
+extern NCURSES_EXPORT(void *)	field_userptr (const FIELD *);
+
+extern NCURSES_EXPORT(FIELDTYPE *)	field_type (const FIELD *);
+
+extern NCURSES_EXPORT(char *)	field_buffer (const FIELD *,int);
+
+extern NCURSES_EXPORT(Field_Options)	field_opts (const FIELD *);
+
+	/******************
+	*  FORM routines  *
+	******************/
+
+extern NCURSES_EXPORT(FORM *)	new_form (FIELD **);
+
+extern NCURSES_EXPORT(FIELD **)	form_fields (const FORM *);
+extern NCURSES_EXPORT(FIELD *)	current_field (const FORM *);
+
+extern NCURSES_EXPORT(WINDOW *)	form_win (const FORM *);
+extern NCURSES_EXPORT(WINDOW *)	form_sub (const FORM *);
+
+extern NCURSES_EXPORT(Form_Hook)	form_init (const FORM *);
+extern NCURSES_EXPORT(Form_Hook)	form_term (const FORM *);
+extern NCURSES_EXPORT(Form_Hook)	field_init (const FORM *);
+extern NCURSES_EXPORT(Form_Hook)	field_term (const FORM *);
+
+extern NCURSES_EXPORT(int)	free_form (FORM *);
+extern NCURSES_EXPORT(int)	set_form_fields (FORM *,FIELD **);
+extern NCURSES_EXPORT(int)	field_count (const FORM *);
+extern NCURSES_EXPORT(int)	set_form_win (FORM *,WINDOW *);
+extern NCURSES_EXPORT(int)	set_form_sub (FORM *,WINDOW *);
+extern NCURSES_EXPORT(int)	set_current_field (FORM *,FIELD *);
+extern NCURSES_EXPORT(int)	field_index (const FIELD *);
+extern NCURSES_EXPORT(int)	set_form_page (FORM *,int);
+extern NCURSES_EXPORT(int)	form_page (const FORM *);
+extern NCURSES_EXPORT(int)	scale_form (const FORM *,int *,int *);
+extern NCURSES_EXPORT(int)	set_form_init (FORM *,Form_Hook);
+extern NCURSES_EXPORT(int)	set_form_term (FORM *,Form_Hook);
+extern NCURSES_EXPORT(int)	set_field_init (FORM *,Form_Hook);
+extern NCURSES_EXPORT(int)	set_field_term (FORM *,Form_Hook);
+extern NCURSES_EXPORT(int)	post_form (FORM *);
+extern NCURSES_EXPORT(int)	unpost_form (FORM *);
+extern NCURSES_EXPORT(int)	pos_form_cursor (FORM *);
+extern NCURSES_EXPORT(int)	form_driver (FORM *,int);
+extern NCURSES_EXPORT(int)	set_form_userptr (FORM *,void *);
+extern NCURSES_EXPORT(int)	set_form_opts (FORM *,Form_Options);
+extern NCURSES_EXPORT(int)	form_opts_on (FORM *,Form_Options);
+extern NCURSES_EXPORT(int)	form_opts_off (FORM *,Form_Options);
+extern NCURSES_EXPORT(int)	form_request_by_name (const char *);
+
+extern NCURSES_EXPORT(const char *)	form_request_name (int);
+
+extern NCURSES_EXPORT(void *)	form_userptr (const FORM *);
+
+extern NCURSES_EXPORT(Form_Options)	form_opts (const FORM *);
+
+extern NCURSES_EXPORT(bool)	data_ahead (const FORM *);
+extern NCURSES_EXPORT(bool)	data_behind (const FORM *);
+
+#if NCURSES_SP_FUNCS
+extern NCURSES_EXPORT(FORM *)	NCURSES_SP_NAME(new_form) (SCREEN*, FIELD **);
+#endif
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif	/* FORM_H */
diff --git a/apps/lib/curses/pdcurses/form/form.priv.h b/apps/lib/curses/pdcurses/form/form.priv.h
new file mode 100644
index 0000000..a118b29
--- /dev/null
+++ b/apps/lib/curses/pdcurses/form/form.priv.h
@@ -0,0 +1,299 @@
+/****************************************************************************
+ * Copyright (c) 1998-2008,2009 Free Software Foundation, Inc.              *
+ *                                                                          *
+ * 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, distribute with modifications, sublicense, and/or sell       *
+ * copies of the Software, and to permit persons to whom the Software is    *
+ * furnished to do so, subject to the following conditions:                 *
+ *                                                                          *
+ * The above copyright notice and this permission notice shall be included  *
+ * in all copies or substantial portions of the Software.                   *
+ *                                                                          *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
+ * IN NO EVENT SHALL THE ABOVE 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.                               *
+ *                                                                          *
+ * Except as contained in this notice, the name(s) of the above copyright   *
+ * holders shall not be used in advertising or otherwise to promote the     *
+ * sale, use or other dealings in this Software without prior written       *
+ * authorization.                                                           *
+ ****************************************************************************/
+
+/****************************************************************************
+ *   Author:  Juergen Pfeifer, 1995,1997                                    *
+ ****************************************************************************/
+
+/* $Id: form.priv.h,v 0.32 2009/11/07 21:26:43 tom Exp $ */
+
+#ifndef FORM_PRIV_H
+#define FORM_PRIV_H 1
+
+#include "../pdcurses/curspriv.h"
+#include "../menu/mf_common.h"
+
+#define UChar(c)	((unsigned char)(c))
+
+#if USE_WIDEC_SUPPORT
+#if HAVE_WCTYPE_H
+#include <wctype.h>
+#endif
+
+#ifndef MB_LEN_MAX
+#define MB_LEN_MAX 8 /* should be >= MB_CUR_MAX, but that may be a function */
+#endif
+
+#define FIELD_CELL NCURSES_CH_T
+
+#define NCURSES_FIELD_INTERNALS char** expanded; WINDOW *working;
+#define NCURSES_FIELD_EXTENSION , (char **)0, (WINDOW *)0
+
+#else
+
+#define FIELD_CELL char
+
+#define NCURSES_FIELD_EXTENSION /* nothing */
+
+#endif
+
+#include "form.h"
+
+	/***********************
+	*   Default objects    *
+	***********************/
+extern NCURSES_EXPORT_VAR(FORM *)      _nc_Default_Form;
+extern NCURSES_EXPORT_VAR(FIELD *)     _nc_Default_Field;
+extern NCURSES_EXPORT_VAR(FIELDTYPE *) _nc_Default_FieldType;
+
+/* form  status values */
+#define _OVLMODE         (0x04U) /* Form is in overlay mode                */
+#define _WINDOW_MODIFIED (0x10U) /* Current field window has been modified */
+#define _FCHECK_REQUIRED (0x20U) /* Current field needs validation         */
+
+/* field status values */
+#define _CHANGED         (0x01U) /* Field has been changed                 */
+#define _NEWTOP          (0x02U) /* Vertical scrolling occurred            */
+#define _NEWPAGE         (0x04U) /* field begins new page of form          */
+#define _MAY_GROW        (0x08U) /* dynamic field may still grow           */
+
+/* fieldtype status values */
+#define _LINKED_TYPE     (0x01U) /* Type is a linked type                  */
+#define _HAS_ARGS        (0x02U) /* Type has arguments                     */
+#define _HAS_CHOICE      (0x04U) /* Type has choice methods                */
+#define _RESIDENT        (0x08U) /* Type is built-in                       */
+#define _GENERIC         (0x10U) /* A generic field type                   */
+
+/* This are the field options required to be a selectable field in field
+   navigation requests */
+#define O_SELECTABLE (O_ACTIVE | O_VISIBLE)
+
+/* If form is NULL replace form argument by default-form */
+#define Normalize_Form(form) \
+  ((form) = (form != 0) ? (form) : _nc_Default_Form)
+
+/* If field is NULL replace field argument by default-field */
+#define Normalize_Field(field) \
+  ((field) = (field != 0) ? (field) : _nc_Default_Field)
+
+#if NCURSES_SP_FUNCS
+#define Get_Form_Screen(form) \
+  ((form)->win ? _nc_screen_of((form->win)):CURRENT_SCREEN)
+#else
+#define Get_Form_Screen(form) CURRENT_SCREEN
+#endif
+
+/* Retrieve forms window */
+#define Get_Form_Window(form) \
+  ((form)->sub != NULL \
+   ? (form)->sub \
+   : ((form)->win != NULL \
+      ? (form)->win \
+      : StdScreen(Get_Form_Screen(form))))
+
+/* Calculate the size for a single buffer for this field */
+#define Buffer_Length(field) ((field)->drows * (field)->dcols)
+
+/* Calculate the total size of all buffers for this field */
+#define Total_Buffer_Size(field) \
+   ( (Buffer_Length(field) + 1) * (1+(field)->nbuf) * sizeof(FIELD_CELL) )
+
+/* Logic to determine whether or not a field is single lined */
+#define Single_Line_Field(field) \
+   (((field)->rows + (field)->nrow) == 1)
+
+/* Logic to determine whether or not a field is selectable */
+#define Field_Is_Selectable(f)     (((unsigned)((f)->opts) & O_SELECTABLE)==O_SELECTABLE)
+#define Field_Is_Not_Selectable(f) (((unsigned)((f)->opts) & O_SELECTABLE)!=O_SELECTABLE)
+
+typedef struct typearg
+  {
+    struct typearg *left;
+    struct typearg *right;
+  }
+TypeArgument;
+
+/* This is a dummy request code (normally invalid) to be used internally
+   with the form_driver() routine to position to the first active field
+   on the form
+*/
+#define FIRST_ACTIVE_MAGIC (-291056)
+
+#define ALL_FORM_OPTS  (                \
+			O_NL_OVERLOAD  |\
+			O_BS_OVERLOAD   )
+
+#define ALL_FIELD_OPTS (Field_Options)( \
+			O_VISIBLE |\
+			O_ACTIVE  |\
+			O_PUBLIC  |\
+			O_EDIT    |\
+			O_WRAP    |\
+			O_BLANK   |\
+			O_AUTOSKIP|\
+			O_NULLOK  |\
+			O_PASSOK  |\
+			O_STATIC   )
+
+#define C_BLANK ' '
+#define is_blank(c) ((c)==C_BLANK)
+
+#define C_ZEROS '\0'
+
+extern NCURSES_EXPORT(TypeArgument *) _nc_Make_Argument (const FIELDTYPE*, va_list*, int*);
+extern NCURSES_EXPORT(TypeArgument *) _nc_Copy_Argument (const FIELDTYPE*, const TypeArgument*, int*);
+extern NCURSES_EXPORT(void) _nc_Free_Argument (const FIELDTYPE*, TypeArgument*);
+extern NCURSES_EXPORT(bool) _nc_Copy_Type (FIELD*, FIELD const *);
+extern NCURSES_EXPORT(void) _nc_Free_Type (FIELD *);
+
+extern NCURSES_EXPORT(int) _nc_Synchronize_Attributes (FIELD*);
+extern NCURSES_EXPORT(int) _nc_Synchronize_Options (FIELD*, Field_Options);
+extern NCURSES_EXPORT(int) _nc_Set_Form_Page (FORM*, int, FIELD*);
+extern NCURSES_EXPORT(int) _nc_Refresh_Current_Field (FORM*);
+extern NCURSES_EXPORT(FIELD *) _nc_First_Active_Field (FORM*);
+extern NCURSES_EXPORT(bool) _nc_Internal_Validation (FORM*);
+extern NCURSES_EXPORT(int) _nc_Set_Current_Field (FORM*, FIELD*);
+extern NCURSES_EXPORT(int) _nc_Position_Form_Cursor (FORM*);
+
+#if NCURSES_INTEROP_FUNCS
+extern NCURSES_EXPORT(FIELDTYPE *) _nc_TYPE_INTEGER(void);
+extern NCURSES_EXPORT(FIELDTYPE *) _nc_TYPE_ALNUM(void);
+extern NCURSES_EXPORT(FIELDTYPE *) _nc_TYPE_ALPHA(void);
+extern NCURSES_EXPORT(FIELDTYPE *) _nc_TYPE_ENUM(void);
+extern NCURSES_EXPORT(FIELDTYPE *) _nc_TYPE_NUMERIC(void);
+extern NCURSES_EXPORT(FIELDTYPE *) _nc_TYPE_REGEXP(void);
+extern NCURSES_EXPORT(FIELDTYPE *) _nc_TYPE_IPV4(void);
+
+extern NCURSES_EXPORT(FIELDTYPE *)
+_nc_generic_fieldtype(bool (*const field_check) (FORM*,
+						 FIELD *,
+						 const void *),
+		      bool (*const char_check)  (int,
+						 FORM*,
+						 FIELD*,
+						 const void *),
+		      bool (*const next)(FORM*,FIELD*,const void*),
+		      bool (*const prev)(FORM*,FIELD*,const void*),
+		      void (*freecallback)(void*));
+extern NCURSES_EXPORT(int) _nc_set_generic_fieldtype(FIELD*, FIELDTYPE*, int (*)(void**));
+extern NCURSES_EXPORT(WINDOW*) _nc_form_cursor(const FORM* , int* , int* );
+
+#define INIT_FT_FUNC(func) {func}
+#else
+#define INIT_FT_FUNC(func) func
+#endif
+
+extern NCURSES_EXPORT(void) _nc_get_fieldbuffer(FORM*, FIELD*, FIELD_CELL*);
+
+#if USE_WIDEC_SUPPORT
+extern NCURSES_EXPORT(wchar_t *) _nc_Widen_String(char *, int *);
+#endif
+
+#ifdef TRACE
+
+#define returnField(code)	TRACE_RETURN(code,field)
+#define returnFieldPtr(code)	TRACE_RETURN(code,field_ptr)
+#define returnForm(code)	TRACE_RETURN(code,form)
+#define returnFieldType(code)	TRACE_RETURN(code,field_type)
+#define returnFormHook(code)	TRACE_RETURN(code,form_hook)
+
+extern NCURSES_EXPORT(FIELD **)	    _nc_retrace_field_ptr (FIELD **);
+extern NCURSES_EXPORT(FIELD *)	    _nc_retrace_field (FIELD *);
+extern NCURSES_EXPORT(FIELDTYPE *)  _nc_retrace_field_type (FIELDTYPE *);
+extern NCURSES_EXPORT(FORM *)       _nc_retrace_form (FORM *);
+extern NCURSES_EXPORT(Form_Hook)    _nc_retrace_form_hook (Form_Hook);
+
+#else /* !TRACE */
+
+#define returnFieldPtr(code)	return code
+#define returnFieldType(code)	return code
+#define returnField(code)	return code
+#define returnForm(code)	return code
+#define returnFormHook(code)	return code
+
+#endif /* TRACE/!TRACE */
+
+/*
+ * Use Check_CTYPE_Field() to simplify FIELDTYPE's that use only the ccheck()
+ * function.
+ */
+#if USE_WIDEC_SUPPORT
+#define Check_CTYPE_Field(result, buffer, width, ccheck) \
+  while (*buffer && *buffer == ' ') \
+    buffer++; \
+  if (*buffer) \
+    { \
+      bool blank = FALSE; \
+      int len; \
+      int n; \
+      wchar_t *list = _nc_Widen_String((char *)buffer, &len); \
+      if (list != 0) \
+	{ \
+	  result = TRUE; \
+	  for (n = 0; n < len; ++n) \
+	    { \
+	      if (blank) \
+		{ \
+		  if (list[n] != ' ') \
+		    { \
+		      result = FALSE; \
+		      break; \
+		    } \
+		} \
+	      else if (list[n] == ' ') \
+		{ \
+		  blank = TRUE; \
+		  result = (n + 1 >= width); \
+		} \
+	      else if (!ccheck(list[n], NULL)) \
+		{ \
+		  result = FALSE; \
+		  break; \
+		} \
+	    } \
+	  free(list); \
+	} \
+    }
+#else
+#define Check_CTYPE_Field(result, buffer, width, ccheck) \
+  while (*buffer && *buffer == ' ') \
+    buffer++; \
+  if (*buffer) \
+    { \
+      unsigned char *s = buffer; \
+      int l = -1; \
+      while (*buffer && ccheck(*buffer, NULL)) \
+	buffer++; \
+      l = (int)(buffer - s); \
+      while (*buffer && *buffer == ' ') \
+	buffer++; \
+      result = ((*buffer || (l < width)) ? FALSE : TRUE); \
+    }
+#endif
+
+#endif /* FORM_PRIV_H */
diff --git a/apps/lib/curses/pdcurses/form/frm_cursor.c b/apps/lib/curses/pdcurses/form/frm_cursor.c
new file mode 100644
index 0000000..091b0fd
--- /dev/null
+++ b/apps/lib/curses/pdcurses/form/frm_cursor.c
@@ -0,0 +1,70 @@
+/****************************************************************************
+ * Copyright (c) 1998-2004,2010 Free Software Foundation, Inc.              *
+ *                                                                          *
+ * 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, distribute with modifications, sublicense, and/or sell       *
+ * copies of the Software, and to permit persons to whom the Software is    *
+ * furnished to do so, subject to the following conditions:                 *
+ *                                                                          *
+ * The above copyright notice and this permission notice shall be included  *
+ * in all copies or substantial portions of the Software.                   *
+ *                                                                          *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
+ * IN NO EVENT SHALL THE ABOVE 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.                               *
+ *                                                                          *
+ * Except as contained in this notice, the name(s) of the above copyright   *
+ * holders shall not be used in advertising or otherwise to promote the     *
+ * sale, use or other dealings in this Software without prior written       *
+ * authorization.                                                           *
+ ****************************************************************************/
+
+/****************************************************************************
+ *   Author:  Juergen Pfeifer, 1995,1997                                    *
+ ****************************************************************************/
+
+#include "form.priv.h"
+
+MODULE_ID("$Id: frm_cursor.c,v 1.10 2010/01/23 21:14:36 tom Exp $")
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  int pos_form_cursor(FORM * form)
+|
+|   Description   :  Moves the form window cursor to the location required
+|                    by the form driver to resume form processing. This may
+|                    be needed after the application calls a curses library
+|                    I/O routine that modifies the cursor position.
+|
+|   Return Values :  E_OK                      - Success
+|                    E_SYSTEM_ERROR            - System error.
+|                    E_BAD_ARGUMENT            - Invalid form pointer
+|                    E_NOT_POSTED              - Form is not posted
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(int)
+pos_form_cursor(FORM *form)
+{
+  int res;
+
+  T((T_CALLED("pos_form_cursor(%p)"), (void *)form));
+
+  if (!form)
+    res = E_BAD_ARGUMENT;
+  else
+    {
+      if (!(form->status & _POSTED))
+	res = E_NOT_POSTED;
+      else
+	res = _nc_Position_Form_Cursor(form);
+    }
+  RETURN(res);
+}
+
+/* frm_cursor.c ends here */
diff --git a/apps/lib/curses/pdcurses/form/frm_data.c b/apps/lib/curses/pdcurses/form/frm_data.c
new file mode 100644
index 0000000..85914eb
--- /dev/null
+++ b/apps/lib/curses/pdcurses/form/frm_data.c
@@ -0,0 +1,193 @@
+/****************************************************************************
+ * Copyright (c) 1998-2005,2010 Free Software Foundation, Inc.              *
+ *                                                                          *
+ * 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, distribute with modifications, sublicense, and/or sell       *
+ * copies of the Software, and to permit persons to whom the Software is    *
+ * furnished to do so, subject to the following conditions:                 *
+ *                                                                          *
+ * The above copyright notice and this permission notice shall be included  *
+ * in all copies or substantial portions of the Software.                   *
+ *                                                                          *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
+ * IN NO EVENT SHALL THE ABOVE 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.                               *
+ *                                                                          *
+ * Except as contained in this notice, the name(s) of the above copyright   *
+ * holders shall not be used in advertising or otherwise to promote the     *
+ * sale, use or other dealings in this Software without prior written       *
+ * authorization.                                                           *
+ ****************************************************************************/
+
+/****************************************************************************
+ *   Author:  Juergen Pfeifer, 1995,1997                                    *
+ ****************************************************************************/
+
+#include "form.priv.h"
+
+MODULE_ID("$Id: frm_data.c,v 1.15 2010/01/23 21:14:36 tom Exp $")
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  bool data_behind(const FORM *form)
+|
+|   Description   :  Check for off-screen data behind. This is nearly trivial
+|                    because the beginning of a field is fixed.
+|
+|   Return Values :  TRUE   - there are off-screen data behind
+|                    FALSE  - there are no off-screen data behind
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(bool)
+data_behind(const FORM *form)
+{
+  bool result = FALSE;
+
+  T((T_CALLED("data_behind(%p)"), (const void *)form));
+
+  if (form && (form->status & _POSTED) && form->current)
+    {
+      FIELD *field;
+
+      field = form->current;
+      if (!Single_Line_Field(field))
+	{
+	  result = (form->toprow == 0) ? FALSE : TRUE;
+	}
+      else
+	{
+	  result = (form->begincol == 0) ? FALSE : TRUE;
+	}
+    }
+  returnBool(result);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static char * Only_Padding(
+|                                    WINDOW *w,
+|                                    int len,
+|                                    int pad)
+|
+|   Description   :  Test if 'length' cells starting at the current position
+|                    contain a padding character.
+|
+|   Return Values :  true if only padding cells are found
++--------------------------------------------------------------------------*/
+NCURSES_INLINE static bool
+Only_Padding(WINDOW *w, int len, int pad)
+{
+  bool result = TRUE;
+  int y, x, j;
+  FIELD_CELL cell;
+
+  getyx(w, y, x);
+  for (j = 0; j < len; ++j)
+    {
+      if (wmove(w, y, x + j) != ERR)
+	{
+#if USE_WIDEC_SUPPORT
+	  if (win_wch(w, &cell) != ERR)
+	    {
+	      if ((chtype)CharOf(cell) != ChCharOf(pad)
+		  || cell.chars[1] != 0)
+		{
+		  result = FALSE;
+		  break;
+		}
+	    }
+#else
+	  cell = winch(w);
+	  if (ChCharOf(cell) != ChCharOf(pad))
+	    {
+	      result = FALSE;
+	      break;
+	    }
+#endif
+	}
+      else
+	{
+	  /* if an error, return true: no non-padding text found */
+	  break;
+	}
+    }
+  /* no need to reset the cursor position; caller does this */
+  return result;
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  bool data_ahead(const FORM *form)
+|
+|   Description   :  Check for off-screen data ahead. This is more difficult
+|                    because a dynamic field has a variable end.
+|
+|   Return Values :  TRUE   - there are off-screen data ahead
+|                    FALSE  - there are no off-screen data ahead
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(bool)
+data_ahead(const FORM *form)
+{
+  bool result = FALSE;
+
+  T((T_CALLED("data_ahead(%p)"), (const void *)form));
+
+  if (form && (form->status & _POSTED) && form->current)
+    {
+      FIELD *field;
+      bool cursor_moved = FALSE;
+      int pos;
+
+      field = form->current;
+      assert(form->w);
+
+      if (Single_Line_Field(field))
+	{
+	  int check_len;
+
+	  pos = form->begincol + field->cols;
+	  while (pos < field->dcols)
+	    {
+	      check_len = field->dcols - pos;
+	      if (check_len >= field->cols)
+		check_len = field->cols;
+	      cursor_moved = TRUE;
+	      wmove(form->w, 0, pos);
+	      if (Only_Padding(form->w, check_len, field->pad))
+		pos += field->cols;
+	      else
+		{
+		  result = TRUE;
+		  break;
+		}
+	    }
+	}
+      else
+	{
+	  pos = form->toprow + field->rows;
+	  while (pos < field->drows)
+	    {
+	      cursor_moved = TRUE;
+	      wmove(form->w, pos, 0);
+	      pos++;
+	      if (!Only_Padding(form->w, field->cols, field->pad))
+		{
+		  result = TRUE;
+		  break;
+		}
+	    }
+	}
+
+      if (cursor_moved)
+	wmove(form->w, form->currow, form->curcol);
+    }
+  returnBool(result);
+}
+
+/* frm_data.c ends here */
diff --git a/apps/lib/curses/pdcurses/form/frm_def.c b/apps/lib/curses/pdcurses/form/frm_def.c
new file mode 100644
index 0000000..54f743b
--- /dev/null
+++ b/apps/lib/curses/pdcurses/form/frm_def.c
@@ -0,0 +1,448 @@
+/****************************************************************************
+ * Copyright (c) 1998-2009,2010 Free Software Foundation, Inc.              *
+ *                                                                          *
+ * 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, distribute with modifications, sublicense, and/or sell       *
+ * copies of the Software, and to permit persons to whom the Software is    *
+ * furnished to do so, subject to the following conditions:                 *
+ *                                                                          *
+ * The above copyright notice and this permission notice shall be included  *
+ * in all copies or substantial portions of the Software.                   *
+ *                                                                          *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
+ * IN NO EVENT SHALL THE ABOVE 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.                               *
+ *                                                                          *
+ * Except as contained in this notice, the name(s) of the above copyright   *
+ * holders shall not be used in advertising or otherwise to promote the     *
+ * sale, use or other dealings in this Software without prior written       *
+ * authorization.                                                           *
+ ****************************************************************************/
+
+/****************************************************************************
+ *   Author:  Juergen Pfeifer, 1995,1997                                    *
+ ****************************************************************************/
+
+#include "form.priv.h"
+
+MODULE_ID("$Id: frm_def.c,v 1.25 2010/01/23 21:14:36 tom Exp $")
+
+/* this can't be readonly */
+static FORM default_form =
+{
+  0,				/* status     */
+  0,				/* rows       */
+  0,				/* cols       */
+  0,				/* currow     */
+  0,				/* curcol     */
+  0,				/* toprow     */
+  0,				/* begincol   */
+  -1,				/* maxfield   */
+  -1,				/* maxpage    */
+  -1,				/* curpage    */
+  ALL_FORM_OPTS,		/* opts       */
+  (WINDOW *)0,			/* win        */
+  (WINDOW *)0,			/* sub        */
+  (WINDOW *)0,			/* w          */
+  (FIELD **)0,			/* field      */
+  (FIELD *)0,			/* current    */
+  (_PAGE *) 0,			/* page       */
+  (char *)0,			/* usrptr     */
+  NULL,				/* forminit   */
+  NULL,				/* formterm   */
+  NULL,				/* fieldinit  */
+  NULL				/* fieldterm  */
+};
+
+NCURSES_EXPORT_VAR(FORM *) _nc_Default_Form = &default_form;
+\f
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static FIELD *Insert_Field_By_Position(
+|                                     FIELD *new_field,
+|                                     FIELD *head )
+|
+|   Description   :  Insert new_field into sorted fieldlist with head "head"
+|                    and return new head of sorted fieldlist. Sorting
+|                    criteria is (row,column). This is a circular list.
+|
+|   Return Values :  New head of sorted fieldlist
++--------------------------------------------------------------------------*/
+static FIELD *
+Insert_Field_By_Position(FIELD *newfield, FIELD *head)
+{
+  FIELD *current, *newhead;
+
+  assert(newfield);
+
+  if (!head)
+    {				/* empty list is trivial */
+      newhead = newfield->snext = newfield->sprev = newfield;
+    }
+  else
+    {
+      newhead = current = head;
+      while ((current->frow < newfield->frow) ||
+	     ((current->frow == newfield->frow) &&
+	      (current->fcol < newfield->fcol)))
+	{
+	  current = current->snext;
+	  if (current == head)
+	    {			/* We cycled through. Reset head to indicate that */
+	      head = (FIELD *)0;
+	      break;
+	    }
+	}
+      /* we leave the loop with current pointing to the field after newfield */
+      newfield->snext = current;
+      newfield->sprev = current->sprev;
+      newfield->snext->sprev = newfield;
+      newfield->sprev->snext = newfield;
+      if (current == head)
+	newhead = newfield;
+    }
+  return (newhead);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static void Disconnect_Fields(FORM *form)
+|
+|   Description   :  Break association between form and array of fields.
+|
+|   Return Values :  -
++--------------------------------------------------------------------------*/
+static void
+Disconnect_Fields(FORM *form)
+{
+  if (form->field)
+    {
+      FIELD **fields;
+
+      for (fields = form->field; *fields; fields++)
+	{
+	  if (form == (*fields)->form)
+	    (*fields)->form = (FORM *)0;
+	}
+
+      form->rows = form->cols = 0;
+      form->maxfield = form->maxpage = -1;
+      form->field = (FIELD **)0;
+      if (form->page)
+	free(form->page);
+      form->page = (_PAGE *) 0;
+    }
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static int Connect_Fields(FORM *form, FIELD **fields)
+|
+|   Description   :  Set association between form and array of fields.
+|
+|   Return Values :  E_OK            - no error
+|                    E_CONNECTED     - a field is already connected
+|                    E_BAD_ARGUMENT  - Invalid form pointer or field array
+|                    E_SYSTEM_ERROR  - not enough memory
++--------------------------------------------------------------------------*/
+static int
+Connect_Fields(FORM *form, FIELD **fields)
+{
+  int field_cnt, j;
+  int page_nr;
+  int maximum_row_in_field, maximum_col_in_field;
+  _PAGE *pg;
+
+  T((T_CALLED("Connect_Fields(%p,%p)"), (void *)form, (void *)fields));
+
+  assert(form);
+
+  form->field = fields;
+  form->maxfield = 0;
+  form->maxpage = 0;
+
+  if (!fields)
+    RETURN(E_OK);
+
+  page_nr = 0;
+  /* store formpointer in fields and count pages */
+  for (field_cnt = 0; fields[field_cnt]; field_cnt++)
+    {
+      if (fields[field_cnt]->form)
+	RETURN(E_CONNECTED);
+      if (field_cnt == 0 ||
+	  (fields[field_cnt]->status & _NEWPAGE))
+	page_nr++;
+      fields[field_cnt]->form = form;
+    }
+  if (field_cnt == 0 || (short)field_cnt < 0)
+    RETURN(E_BAD_ARGUMENT);
+
+  /* allocate page structures */
+  if ((pg = typeMalloc(_PAGE, page_nr)) != (_PAGE *) 0)
+    {
+      T((T_CREATE("_PAGE %p"), (void *)pg));
+      form->page = pg;
+    }
+  else
+    RETURN(E_SYSTEM_ERROR);
+
+  /* Cycle through fields and calculate page boundaries as well as
+     size of the form */
+  for (j = 0; j < field_cnt; j++)
+    {
+      if (j == 0)
+	pg->pmin = j;
+      else
+	{
+	  if (fields[j]->status & _NEWPAGE)
+	    {
+	      pg->pmax = j - 1;
+	      pg++;
+	      pg->pmin = j;
+	    }
+	}
+
+      maximum_row_in_field = fields[j]->frow + fields[j]->rows;
+      maximum_col_in_field = fields[j]->fcol + fields[j]->cols;
+
+      if (form->rows < maximum_row_in_field)
+	form->rows = maximum_row_in_field;
+      if (form->cols < maximum_col_in_field)
+	form->cols = maximum_col_in_field;
+    }
+
+  pg->pmax = field_cnt - 1;
+  form->maxfield = field_cnt;
+  form->maxpage = page_nr;
+
+  /* Sort fields on form pages */
+  for (page_nr = 0; page_nr < form->maxpage; page_nr++)
+    {
+      FIELD *fld = (FIELD *)0;
+
+      for (j = form->page[page_nr].pmin; j <= form->page[page_nr].pmax; j++)
+	{
+	  fields[j]->index = j;
+	  fields[j]->page = page_nr;
+	  fld = Insert_Field_By_Position(fields[j], fld);
+	}
+      if (fld)
+	{
+	  form->page[page_nr].smin = fld->index;
+	  form->page[page_nr].smax = fld->sprev->index;
+	}
+      else
+	{
+	  form->page[page_nr].smin = 0;
+	  form->page[page_nr].smax = 0;
+	}
+    }
+  RETURN(E_OK);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static int Associate_Fields(FORM *form, FIELD **fields)
+|
+|   Description   :  Set association between form and array of fields.
+|                    If there are fields, position to first active field.
+|
+|   Return Values :  E_OK            - success
+|                    E_BAD_ARGUMENT  - Invalid form pointer or field array
+|                    E_CONNECTED     - a field is already connected
+|                    E_SYSTEM_ERROR  - not enough memory
++--------------------------------------------------------------------------*/
+NCURSES_INLINE static int
+Associate_Fields(FORM *form, FIELD **fields)
+{
+  int res = Connect_Fields(form, fields);
+
+  if (res == E_OK)
+    {
+      if (form->maxpage > 0)
+	{
+	  form->curpage = 0;
+	  form_driver(form, FIRST_ACTIVE_MAGIC);
+	}
+      else
+	{
+	  form->curpage = -1;
+	  form->current = (FIELD *)0;
+	}
+    }
+  return (res);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  FORM *new_form_sp(SCREEN* sp, FIELD** fields )
+|
+|   Description   :  Create new form with given array of fields.
+|
+|   Return Values :  Pointer to form. NULL if error occurred.
+!                    Set errno:
+|                    E_OK            - success
+|                    E_BAD_ARGUMENT  - Invalid form pointer or field array
+|                    E_CONNECTED     - a field is already connected
+|                    E_SYSTEM_ERROR  - not enough memory
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(FORM *)
+NCURSES_SP_NAME(new_form) (NCURSES_SP_DCLx FIELD **fields)
+{
+  int err = E_SYSTEM_ERROR;
+  FORM *form = (FORM *)0;
+
+  T((T_CALLED("new_form(%p,%p)"), (void *)SP_PARM, (void *)fields));
+
+  if (IsValidScreen(SP_PARM))
+    {
+      form = typeMalloc(FORM, 1);
+
+      if (form)
+	{
+	  T((T_CREATE("form %p"), (void *)form));
+	  *form = *_nc_Default_Form;
+	  /* This ensures win and sub are always non-null,
+	     so we can derive always the SCREEN that this form is
+	     running on. */
+	  form->win = StdScreen(SP_PARM);
+	  form->sub = StdScreen(SP_PARM);
+	  if ((err = Associate_Fields(form, fields)) != E_OK)
+	    {
+	      free_form(form);
+	      form = (FORM *)0;
+	    }
+	}
+    }
+
+  if (!form)
+    SET_ERROR(err);
+
+  returnForm(form);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  FORM* new_form(FIELD** fields )
+|
+|   Description   :  Create new form with given array of fields.
+|
+|   Return Values :  Pointer to form. NULL if error occurred.
+!                    Set errno:
+|                    E_OK            - success
+|                    E_BAD_ARGUMENT  - Invalid form pointer or field array
+|                    E_CONNECTED     - a field is already connected
+|                    E_SYSTEM_ERROR  - not enough memory
++--------------------------------------------------------------------------*/
+#if NCURSES_SP_FUNCS
+NCURSES_EXPORT(FORM *)
+new_form(FIELD **fields)
+{
+  return NCURSES_SP_NAME(new_form) (CURRENT_SCREEN, fields);
+}
+#endif
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  int free_form( FORM *form )
+|
+|   Description   :  Release internal memory associated with form.
+|
+|   Return Values :  E_OK           - no error
+|                    E_BAD_ARGUMENT - invalid form pointer
+|                    E_POSTED       - form is posted
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(int)
+free_form(FORM *form)
+{
+  T((T_CALLED("free_form(%p)"), (void *)form));
+
+  if (!form)
+    RETURN(E_BAD_ARGUMENT);
+
+  if (form->status & _POSTED)
+    RETURN(E_POSTED);
+
+  Disconnect_Fields(form);
+  if (form->page)
+    free(form->page);
+  free(form);
+
+  RETURN(E_OK);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  int set_form_fields( FORM *form, FIELD **fields )
+|
+|   Description   :  Set a new association of an array of fields to a form
+|
+|   Return Values :  E_OK            - no error
+|                    E_BAD_ARGUMENT  - Invalid form pointer or field array
+|                    E_CONNECTED     - a field is already connected
+|                    E_POSTED        - form is posted
+|                    E_SYSTEM_ERROR  - not enough memory
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(int)
+set_form_fields(FORM *form, FIELD **fields)
+{
+  FIELD **old;
+  int res;
+
+  T((T_CALLED("set_form_fields(%p,%p)"), (void *)form, (void *)fields));
+
+  if (!form)
+    RETURN(E_BAD_ARGUMENT);
+
+  if (form->status & _POSTED)
+    RETURN(E_POSTED);
+
+  old = form->field;
+  Disconnect_Fields(form);
+
+  if ((res = Associate_Fields(form, fields)) != E_OK)
+    Connect_Fields(form, old);
+
+  RETURN(res);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  FIELD **form_fields( const FORM *form )
+|
+|   Description   :  Retrieve array of fields
+|
+|   Return Values :  Pointer to field array
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(FIELD **)
+form_fields(const FORM *form)
+{
+  T((T_CALLED("form_field(%p)"), (const void *)form));
+  returnFieldPtr(Normalize_Form(form)->field);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  int field_count( const FORM *form )
+|
+|   Description   :  Retrieve number of fields
+|
+|   Return Values :  Number of fields, -1 if none are defined
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(int)
+field_count(const FORM *form)
+{
+  T((T_CALLED("field_count(%p)"), (const void *)form));
+
+  returnCode(Normalize_Form(form)->maxfield);
+}
+
+/* frm_def.c ends here */
diff --git a/apps/lib/curses/pdcurses/form/frm_driver.c b/apps/lib/curses/pdcurses/form/frm_driver.c
new file mode 100644
index 0000000..e0892bf
--- /dev/null
+++ b/apps/lib/curses/pdcurses/form/frm_driver.c
@@ -0,0 +1,4646 @@
+/****************************************************************************
+ * Copyright (c) 1998-2009,2010 Free Software Foundation, Inc.              *
+ *                                                                          *
+ * 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, distribute with modifications, sublicense, and/or sell       *
+ * copies of the Software, and to permit persons to whom the Software is    *
+ * furnished to do so, subject to the following conditions:                 *
+ *                                                                          *
+ * The above copyright notice and this permission notice shall be included  *
+ * in all copies or substantial portions of the Software.                   *
+ *                                                                          *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
+ * IN NO EVENT SHALL THE ABOVE 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.                               *
+ *                                                                          *
+ * Except as contained in this notice, the name(s) of the above copyright   *
+ * holders shall not be used in advertising or otherwise to promote the     *
+ * sale, use or other dealings in this Software without prior written       *
+ * authorization.                                                           *
+ ****************************************************************************/
+
+/****************************************************************************
+ *   Author:  Juergen Pfeifer, 1995,1997                                    *
+ ****************************************************************************/
+
+#include "form.priv.h"
+
+MODULE_ID("$Id: frm_driver.c,v 1.98 2010/05/01 21:11:43 tom Exp $")
+
+/*----------------------------------------------------------------------------
+  This is the core module of the form library. It contains the majority
+  of the driver routines as well as the form_driver function.
+
+  Essentially this module is nearly the whole library. This is because
+  all the functions in this module depends on some others in the module,
+  so it makes no sense to split them into separate files because they
+  will always be linked together. The only acceptable concern is turnaround
+  time for this module, but now we have all Pentiums or RISCs, so what!
+
+  The driver routines are grouped into nine generic categories:
+
+   a)   Page Navigation            ( all functions prefixed by PN_ )
+        The current page of the form is left and some new page is
+        entered.
+   b)   Inter-Field Navigation     ( all functions prefixed by FN_ )
+        The current field of the form is left and some new field is
+        entered.
+   c)   Intra-Field Navigation     ( all functions prefixed by IFN_ )
+        The current position in the current field is changed.
+   d)   Vertical Scrolling         ( all functions prefixed by VSC_ )
+        Essentially this is a specialization of Intra-Field navigation.
+        It has to check for a multi-line field.
+   e)   Horizontal Scrolling       ( all functions prefixed by HSC_ )
+        Essentially this is a specialization of Intra-Field navigation.
+        It has to check for a single-line field.
+   f)   Field Editing              ( all functions prefixed by FE_ )
+        The content of the current field is changed
+   g)   Edit Mode requests         ( all functions prefixed by EM_ )
+        Switching between insert and overlay mode
+   h)   Field-Validation requests  ( all functions prefixed by FV_ )
+        Perform verifications of the field.
+   i)   Choice requests            ( all functions prefixed by CR_ )
+        Requests to enumerate possible field values
+  --------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+  Some remarks on the placements of assert() macros :
+  I use them only on "strategic" places, i.e. top level entries where
+  I want to make sure that things are set correctly. Throughout subordinate
+  routines I omit them mostly.
+  --------------------------------------------------------------------------*/
+
+/*
+Some options that may effect compatibility in behavior to SVr4 forms,
+but they are here to allow a more intuitive and user friendly behavior of
+our form implementation. This doesn't affect the API, so we feel it is
+uncritical.
+
+The initial implementation tries to stay very close with the behavior
+of the original SVr4 implementation, although in some areas it is quite
+clear that this isn't the most appropriate way. As far as possible this
+sources will allow you to build a forms lib that behaves quite similar
+to SVr4, but now and in the future we will give you better options.
+Perhaps at some time we will make this configurable at runtime.
+*/
+
+/* Implement a more user-friendly previous/next word behavior */
+#define FRIENDLY_PREV_NEXT_WORD (1)
+/* Fix the wrong behavior for forms with all fields inactive */
+#define FIX_FORM_INACTIVE_BUG (1)
+/* Allow dynamic field growth also when navigating past the end */
+#define GROW_IF_NAVIGATE (1)
+
+#if USE_WIDEC_SUPPORT
+#define myADDNSTR(w, s, n) wadd_wchnstr(w, s, n)
+#define myINSNSTR(w, s, n) wins_wchnstr(w, s, n)
+#define myINNSTR(w, s, n)  fix_wchnstr(w, s, n)
+#define myWCWIDTH(w, y, x) cell_width(w, y, x)
+#else
+#define myADDNSTR(w, s, n) waddnstr(w, s, n)
+#define myINSNSTR(w, s, n) winsnstr(w, s, n)
+#define myINNSTR(w, s, n)  winnstr(w, s, n)
+#define myWCWIDTH(w, y, x) 1
+#endif
+
+/*----------------------------------------------------------------------------
+  Forward references to some internally used static functions
+  --------------------------------------------------------------------------*/
+static int Inter_Field_Navigation(int (*const fct) (FORM *), FORM *form);
+static int FN_Next_Field(FORM *form);
+static int FN_Previous_Field(FORM *form);
+static int FE_New_Line(FORM *);
+static int FE_Delete_Previous(FORM *);
+
+/*----------------------------------------------------------------------------
+  Macro Definitions.
+
+  Some Remarks on that: I use the convention to use UPPERCASE for constants
+  defined by Macros. If I provide a macro as a kind of inline routine to
+  provide some logic, I use my Upper_Lower case style.
+  --------------------------------------------------------------------------*/
+
+/* Calculate the position of a single row in a field buffer */
+#define Position_Of_Row_In_Buffer(field,row) ((row)*(field)->dcols)
+
+/* Calculate start address for the fields buffer# N */
+#define Address_Of_Nth_Buffer(field,N) \
+  ((field)->buf + (N)*(1+Buffer_Length(field)))
+
+/* Calculate the start address of the row in the fields specified buffer# N */
+#define Address_Of_Row_In_Nth_Buffer(field,N,row) \
+  (Address_Of_Nth_Buffer(field,N) + Position_Of_Row_In_Buffer(field,row))
+
+/* Calculate the start address of the row in the fields primary buffer */
+#define Address_Of_Row_In_Buffer(field,row) \
+  Address_Of_Row_In_Nth_Buffer(field,0,row)
+
+/* Calculate the start address of the row in the forms current field
+   buffer# N */
+#define Address_Of_Current_Row_In_Nth_Buffer(form,N) \
+   Address_Of_Row_In_Nth_Buffer((form)->current,N,(form)->currow)
+
+/* Calculate the start address of the row in the forms current field
+   primary buffer */
+#define Address_Of_Current_Row_In_Buffer(form) \
+   Address_Of_Current_Row_In_Nth_Buffer(form,0)
+
+/* Calculate the address of the cursor in the forms current field
+   primary buffer */
+#define Address_Of_Current_Position_In_Nth_Buffer(form,N) \
+   (Address_Of_Current_Row_In_Nth_Buffer(form,N) + (form)->curcol)
+
+/* Calculate the address of the cursor in the forms current field
+   buffer# N */
+#define Address_Of_Current_Position_In_Buffer(form) \
+  Address_Of_Current_Position_In_Nth_Buffer(form,0)
+
+/* Logic to decide whether or not a field is actually a field with
+   vertical or horizontal scrolling */
+#define Is_Scroll_Field(field)          \
+   (((field)->drows > (field)->rows) || \
+    ((field)->dcols > (field)->cols))
+
+/* Logic to decide whether or not a field needs to have an individual window
+   instead of a derived window because it contains invisible parts.
+   This is true for non-public fields and for scrollable fields. */
+#define Has_Invisible_Parts(field)     \
+  (!((field)->opts & O_PUBLIC)      || \
+   Is_Scroll_Field(field))
+
+/* Logic to decide whether or not a field needs justification */
+#define Justification_Allowed(field)        \
+   (((field)->just != NO_JUSTIFICATION)  && \
+    (Single_Line_Field(field))           && \
+    (((field)->dcols == (field)->cols)   && \
+    ((field)->opts & O_STATIC))             )
+
+/* Logic to determine whether or not a dynamic field may still grow */
+#define Growable(field) ((field)->status & _MAY_GROW)
+
+/* Macro to set the attributes for a fields window */
+#define Set_Field_Window_Attributes(field,win) \
+(  wbkgdset((win),(chtype)((field)->pad | (field)->back)), \
+   (void) wattrset((win),(field)->fore) )
+
+/* Logic to decide whether or not a field really appears on the form */
+#define Field_Really_Appears(field)         \
+  ((field->form)                          &&\
+   (field->form->status & _POSTED)        &&\
+   (field->opts & O_VISIBLE)              &&\
+   (field->page == field->form->curpage))
+
+/* Logic to determine whether or not we are on the first position in the
+   current field */
+#define First_Position_In_Current_Field(form) \
+  (((form)->currow==0) && ((form)->curcol==0))
+
+#define Minimum(a,b) (((a)<=(b)) ? (a) : (b))
+#define Maximum(a,b) (((a)>=(b)) ? (a) : (b))
+
+/*----------------------------------------------------------------------------
+  Useful constants
+  --------------------------------------------------------------------------*/
+static FIELD_CELL myBLANK = BLANK;
+static FIELD_CELL myZEROS;
+
+#ifdef TRACE
+static void
+check_pos(FORM *form, int lineno)
+{
+  int y, x;
+
+  if (form && form->w)
+    {
+      getyx(form->w, y, x);
+      if (y != form->currow || x != form->curcol)
+	{
+	  T(("CHECKPOS %s@%d have position %d,%d vs want %d,%d",
+	     __FILE__, lineno,
+	     y, x,
+	     form->currow, form->curcol));
+	}
+    }
+}
+#define CHECKPOS(form) check_pos(form, __LINE__)
+#else
+#define CHECKPOS(form)		/* nothing */
+#endif
+
+/*----------------------------------------------------------------------------
+  Wide-character special functions
+  --------------------------------------------------------------------------*/
+#if USE_WIDEC_SUPPORT
+/* like winsnstr */
+static int
+wins_wchnstr(WINDOW *w, cchar_t *s, int n)
+{
+  int code = ERR;
+  int y, x;
+
+  while (n-- > 0)
+    {
+      getyx(w, y, x);
+      if ((code = wins_wch(w, s++)) != OK)
+	break;
+      if ((code = wmove(w, y, x + 1)) != OK)
+	break;
+    }
+  return code;
+}
+
+/* win_wchnstr is inconsistent with winnstr, since it returns OK rather than
+ * the number of items transferred.
+ */
+static int
+fix_wchnstr(WINDOW *w, cchar_t *s, int n)
+{
+  int x;
+
+  win_wchnstr(w, s, n);
+  /*
+   * This function is used to extract the text only from the window.
+   * Strip attributes and color from the string so they will not be added
+   * back when copying the string to the window.
+   */
+  for (x = 0; x < n; ++x)
+    {
+      RemAttr(s[x], A_ATTRIBUTES);
+      SetPair(s[x], 0);
+    }
+  return n;
+}
+
+/*
+ * Returns the column of the base of the given cell.
+ */
+static int
+cell_base(WINDOW *win, int y, int x)
+{
+  int result = x;
+
+  while (LEGALYX(win, y, x))
+    {
+      cchar_t *data = &(win->_line[y].text[x]);
+
+      if (isWidecBase(CHDEREF(data)) || !isWidecExt(CHDEREF(data)))
+	{
+	  result = x;
+	  break;
+	}
+      --x;
+    }
+  return result;
+}
+
+/*
+ * Returns the number of columns needed for the given cell in a window.
+ */
+static int
+cell_width(WINDOW *win, int y, int x)
+{
+  int result = 1;
+
+  if (LEGALYX(win, y, x))
+    {
+      cchar_t *data = &(win->_line[y].text[x]);
+
+      if (isWidecExt(CHDEREF(data)))
+	{
+	  /* recur, providing the number of columns to the next character */
+	  result = cell_width(win, y, x - 1);
+	}
+      else
+	{
+	  result = wcwidth(CharOf(CHDEREF(data)));
+	}
+    }
+  return result;
+}
+
+/*
+ * There is no wide-character function such as wdel_wch(), so we must find
+ * all of the cells that comprise a multi-column character and delete them
+ * one-by-one.
+ */
+static void
+delete_char(FORM *form)
+{
+  int cells = cell_width(form->w, form->currow, form->curcol);
+
+  form->curcol = cell_base(form->w, form->currow, form->curcol);
+  wmove(form->w, form->currow, form->curcol);
+  while (cells-- > 0)
+    {
+      wdelch(form->w);
+    }
+}
+#define DeleteChar(form) delete_char(form)
+#else
+#define DeleteChar(form) \
+	  wmove((form)->w, (form)->currow, (form)->curcol), \
+	  wdelch((form)->w)
+#endif
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static char *Get_Start_Of_Data(char * buf, int blen)
+|
+|   Description   :  Return pointer to first non-blank position in buffer.
+|                    If buffer is empty return pointer to buffer itself.
+|
+|   Return Values :  Pointer to first non-blank position in buffer
++--------------------------------------------------------------------------*/
+NCURSES_INLINE static FIELD_CELL *
+Get_Start_Of_Data(FIELD_CELL *buf, int blen)
+{
+  FIELD_CELL *p = buf;
+  FIELD_CELL *end = &buf[blen];
+
+  assert(buf && blen >= 0);
+  while ((p < end) && ISBLANK(*p))
+    p++;
+  return ((p == end) ? buf : p);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static char *After_End_Of_Data(char * buf, int blen)
+|
+|   Description   :  Return pointer after last non-blank position in buffer.
+|                    If buffer is empty, return pointer to buffer itself.
+|
+|   Return Values :  Pointer to position after last non-blank position in
+|                    buffer.
++--------------------------------------------------------------------------*/
+NCURSES_INLINE static FIELD_CELL *
+After_End_Of_Data(FIELD_CELL *buf, int blen)
+{
+  FIELD_CELL *p = &buf[blen];
+
+  assert(buf && blen >= 0);
+  while ((p > buf) && ISBLANK(p[-1]))
+    p--;
+  return (p);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static char *Get_First_Whitespace_Character(
+|                                     char * buf, int   blen)
+|
+|   Description   :  Position to the first whitespace character.
+|
+|   Return Values :  Pointer to first whitespace character in buffer.
++--------------------------------------------------------------------------*/
+NCURSES_INLINE static FIELD_CELL *
+Get_First_Whitespace_Character(FIELD_CELL *buf, int blen)
+{
+  FIELD_CELL *p = buf;
+  FIELD_CELL *end = &p[blen];
+
+  assert(buf && blen >= 0);
+  while ((p < end) && !ISBLANK(*p))
+    p++;
+  return ((p == end) ? buf : p);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static char *After_Last_Whitespace_Character(
+|                                     char * buf, int blen)
+|
+|   Description   :  Get the position after the last whitespace character.
+|
+|   Return Values :  Pointer to position after last whitespace character in
+|                    buffer.
++--------------------------------------------------------------------------*/
+NCURSES_INLINE static FIELD_CELL *
+After_Last_Whitespace_Character(FIELD_CELL *buf, int blen)
+{
+  FIELD_CELL *p = &buf[blen];
+
+  assert(buf && blen >= 0);
+  while ((p > buf) && !ISBLANK(p[-1]))
+    p--;
+  return (p);
+}
+
+/* Set this to 1 to use the div_t version. This is a good idea if your
+   compiler has an intrinsic div() support. Unfortunately GNU-C has it
+   not yet.
+   N.B.: This only works if form->curcol follows immediately form->currow
+         and both are of type int.
+*/
+#define USE_DIV_T (0)
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static void Adjust_Cursor_Position(
+|                                       FORM * form, const char * pos)
+|
+|   Description   :  Set current row and column of the form to values
+|                    corresponding to the buffer position.
+|
+|   Return Values :  -
++--------------------------------------------------------------------------*/
+NCURSES_INLINE static void
+Adjust_Cursor_Position(FORM *form, const FIELD_CELL *pos)
+{
+  FIELD *field;
+  int idx;
+
+  field = form->current;
+  assert(pos >= field->buf && field->dcols > 0);
+  idx = (int)(pos - field->buf);
+#if USE_DIV_T
+  *((div_t *) & (form->currow)) = div(idx, field->dcols);
+#else
+  form->currow = idx / field->dcols;
+  form->curcol = idx - field->cols * form->currow;
+#endif
+  if (field->drows < form->currow)
+    form->currow = 0;
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static void Buffer_To_Window(
+|                                      const FIELD  * field,
+|                                      WINDOW * win)
+|
+|   Description   :  Copy the buffer to the window. If it is a multi-line
+|                    field, the buffer is split to the lines of the
+|                    window without any editing.
+|
+|   Return Values :  -
++--------------------------------------------------------------------------*/
+static void
+Buffer_To_Window(const FIELD *field, WINDOW *win)
+{
+  int width, height;
+  int y, x;
+  int len;
+  int row;
+  FIELD_CELL *pBuffer;
+
+  assert(win && field);
+
+  getyx(win, y, x);
+  width = getmaxx(win);
+  height = getmaxy(win);
+
+  for (row = 0, pBuffer = field->buf;
+       row < height;
+       row++, pBuffer += width)
+    {
+      if ((len = (int)(After_End_Of_Data(pBuffer, width) - pBuffer)) > 0)
+	{
+	  wmove(win, row, 0);
+	  myADDNSTR(win, pBuffer, len);
+	}
+    }
+  wmove(win, y, x);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  void _nc_get_fieldbuffer(
+|                                          WINDOW * win,
+|                                          FIELD  * field,
+|                                          FIELD_CELL * buf)
+|
+|   Description   :  Copy the content of the window into the buffer.
+|                    The multiple lines of a window are simply
+|                    concatenated into the buffer. Pad characters in
+|                    the window will be replaced by blanks in the buffer.
+|
+|   Return Values :  -
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(void)
+_nc_get_fieldbuffer(FORM *form, FIELD *field, FIELD_CELL *buf)
+{
+  int pad;
+  int len = 0;
+  FIELD_CELL *p;
+  int row, height;
+  WINDOW *win;
+
+  assert(form && field && buf);
+
+  win = form->w;
+  assert(win);
+
+  pad = field->pad;
+  p = buf;
+  height = getmaxy(win);
+
+  for (row = 0; (row < height) && (row < field->drows); row++)
+    {
+      wmove(win, row, 0);
+      len += myINNSTR(win, p + len, field->dcols);
+    }
+  p[len] = myZEROS;
+
+  /* replace visual padding character by blanks in buffer */
+  if (pad != C_BLANK)
+    {
+      int i;
+
+      for (i = 0; i < len; i++, p++)
+	{
+	  if ((unsigned long)CharOf(*p) == ChCharOf(pad)
+#if USE_WIDEC_SUPPORT
+	      && p->chars[1] == 0
+#endif
+	    )
+	    *p = myBLANK;
+	}
+    }
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static void Window_To_Buffer(
+|                                          FORM   * form,
+|                                          FIELD  * field)
+|
+|   Description   :  Copy the content of the window into the buffer.
+|                    The multiple lines of a window are simply
+|                    concatenated into the buffer. Pad characters in
+|                    the window will be replaced by blanks in the buffer.
+|
+|   Return Values :  -
++--------------------------------------------------------------------------*/
+static void
+Window_To_Buffer(FORM *form, FIELD *field)
+{
+  _nc_get_fieldbuffer(form, field, field->buf);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static void Synchronize_Buffer(FORM * form)
+|
+|   Description   :  If there was a change, copy the content of the
+|                    window into the buffer, so the buffer is synchronized
+|                    with the windows content. We have to indicate that the
+|                    buffer needs validation due to the change.
+|
+|   Return Values :  -
++--------------------------------------------------------------------------*/
+NCURSES_INLINE static void
+Synchronize_Buffer(FORM *form)
+{
+  if (form->status & _WINDOW_MODIFIED)
+    {
+      form->status &= ~_WINDOW_MODIFIED;
+      form->status |= _FCHECK_REQUIRED;
+      Window_To_Buffer(form, form->current);
+      wmove(form->w, form->currow, form->curcol);
+    }
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static bool Field_Grown( FIELD *field, int amount)
+|
+|   Description   :  This function is called for growable dynamic fields
+|                    only. It has to increase the buffers and to allocate
+|                    a new window for this field.
+|                    This function has the side effect to set a new
+|                    field-buffer pointer, the dcols and drows values
+|                    as well as a new current Window for the field.
+|
+|   Return Values :  TRUE     - field successfully increased
+|                    FALSE    - there was some error
++--------------------------------------------------------------------------*/
+static bool
+Field_Grown(FIELD *field, int amount)
+{
+  bool result = FALSE;
+
+  if (field && Growable(field))
+    {
+      bool single_line_field = Single_Line_Field(field);
+      int old_buflen = Buffer_Length(field);
+      int new_buflen;
+      int old_dcols = field->dcols;
+      int old_drows = field->drows;
+      FIELD_CELL *oldbuf = field->buf;
+      FIELD_CELL *newbuf;
+
+      int growth;
+      FORM *form = field->form;
+      bool need_visual_update = ((form != (FORM *)0) &&
+				 (form->status & _POSTED) &&
+				 (form->current == field));
+
+      if (need_visual_update)
+	Synchronize_Buffer(form);
+
+      if (single_line_field)
+	{
+	  growth = field->cols * amount;
+	  if (field->maxgrow)
+	    growth = Minimum(field->maxgrow - field->dcols, growth);
+	  field->dcols += growth;
+	  if (field->dcols == field->maxgrow)
+	    field->status &= ~_MAY_GROW;
+	}
+      else
+	{
+	  growth = (field->rows + field->nrow) * amount;
+	  if (field->maxgrow)
+	    growth = Minimum(field->maxgrow - field->drows, growth);
+	  field->drows += growth;
+	  if (field->drows == field->maxgrow)
+	    field->status &= ~_MAY_GROW;
+	}
+      /* drows, dcols changed, so we get really the new buffer length */
+      new_buflen = Buffer_Length(field);
+      newbuf = (FIELD_CELL *)malloc(Total_Buffer_Size(field));
+      if (!newbuf)
+	{
+	  /* restore to previous state */
+	  field->dcols = old_dcols;
+	  field->drows = old_drows;
+	  if ((single_line_field && (field->dcols != field->maxgrow)) ||
+	      (!single_line_field && (field->drows != field->maxgrow)))
+	    field->status |= _MAY_GROW;
+	}
+      else
+	{
+	  /* Copy all the buffers.  This is the reason why we can't just use
+	   * realloc().
+	   */
+	  int i, j;
+	  FIELD_CELL *old_bp;
+	  FIELD_CELL *new_bp;
+
+	  result = TRUE;	/* allow sharing of recovery on failure */
+
+	  T((T_CREATE("fieldcell %p"), (void *)newbuf));
+	  field->buf = newbuf;
+	  for (i = 0; i <= field->nbuf; i++)
+	    {
+	      new_bp = Address_Of_Nth_Buffer(field, i);
+	      old_bp = oldbuf + i * (1 + old_buflen);
+	      for (j = 0; j < old_buflen; ++j)
+		new_bp[j] = old_bp[j];
+	      while (j < new_buflen)
+		new_bp[j++] = myBLANK;
+	      new_bp[new_buflen] = myZEROS;
+	    }
+
+#if USE_WIDEC_SUPPORT && NCURSES_EXT_FUNCS
+	  if (wresize(field->working, 1, Buffer_Length(field) + 1) == ERR)
+	    result = FALSE;
+#endif
+
+	  if (need_visual_update && result)
+	    {
+	      WINDOW *new_window = newpad(field->drows, field->dcols);
+
+	      if (new_window != 0)
+		{
+		  assert(form != (FORM *)0);
+		  if (form->w)
+		    delwin(form->w);
+		  form->w = new_window;
+		  Set_Field_Window_Attributes(field, form->w);
+		  werase(form->w);
+		  Buffer_To_Window(field, form->w);
+		  untouchwin(form->w);
+		  wmove(form->w, form->currow, form->curcol);
+		}
+	      else
+		result = FALSE;
+	    }
+
+	  if (result)
+	    {
+	      free(oldbuf);
+	      /* reflect changes in linked fields */
+	      if (field != field->link)
+		{
+		  FIELD *linked_field;
+
+		  for (linked_field = field->link;
+		       linked_field != field;
+		       linked_field = linked_field->link)
+		    {
+		      linked_field->buf = field->buf;
+		      linked_field->drows = field->drows;
+		      linked_field->dcols = field->dcols;
+		    }
+		}
+	    }
+	  else
+	    {
+	      /* restore old state */
+	      field->dcols = old_dcols;
+	      field->drows = old_drows;
+	      field->buf = oldbuf;
+	      if ((single_line_field &&
+		   (field->dcols != field->maxgrow)) ||
+		  (!single_line_field &&
+		   (field->drows != field->maxgrow)))
+		field->status |= _MAY_GROW;
+	      free(newbuf);
+	    }
+	}
+    }
+  return (result);
+}
+
+#ifdef NCURSES_MOUSE_VERSION
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  int Field_encloses(FIELD *field, int ry, int rx)
+|
+|   Description   :  Check if the given coordinates lie within the given field.
+|
+|   Return Values :  E_OK              - success
+|                    E_BAD_ARGUMENT    - invalid form pointer
+|                    E_SYSTEM_ERROR    - form has no current field or
+|                                        field-window
++--------------------------------------------------------------------------*/
+static int
+Field_encloses(FIELD *field, int ry, int rx)
+{
+  T((T_CALLED("Field_encloses(%p)"), (void *)field));
+  if (field != 0
+      && field->frow <= ry
+      && (field->frow + field->rows) > ry
+      && field->fcol <= rx
+      && (field->fcol + field->cols) > rx)
+    {
+      RETURN(E_OK);
+    }
+  RETURN(E_INVALID_FIELD);
+}
+#endif
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  int _nc_Position_Form_Cursor(FORM * form)
+|
+|   Description   :  Position the cursor in the window for the current
+|                    field to be in sync. with the currow and curcol
+|                    values.
+|
+|   Return Values :  E_OK              - success
+|                    E_BAD_ARGUMENT    - invalid form pointer
+|                    E_SYSTEM_ERROR    - form has no current field or
+|                                        field-window
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(int)
+_nc_Position_Form_Cursor(FORM *form)
+{
+  FIELD *field;
+  WINDOW *formwin;
+
+  if (!form)
+    return (E_BAD_ARGUMENT);
+
+  if (!form->w || !form->current)
+    return (E_SYSTEM_ERROR);
+
+  field = form->current;
+  formwin = Get_Form_Window(form);
+
+  wmove(form->w, form->currow, form->curcol);
+  if (Has_Invisible_Parts(field))
+    {
+      /* in this case fieldwin isn't derived from formwin, so we have
+         to move the cursor in formwin by hand... */
+      wmove(formwin,
+	    field->frow + form->currow - form->toprow,
+	    field->fcol + form->curcol - form->begincol);
+      wcursyncup(formwin);
+    }
+  else
+    wcursyncup(form->w);
+  return (E_OK);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  int _nc_Refresh_Current_Field(FORM * form)
+|
+|   Description   :  Propagate the changes in the fields window to the
+|                    window of the form.
+|
+|   Return Values :  E_OK              - on success
+|                    E_BAD_ARGUMENT    - invalid form pointer
+|                    E_SYSTEM_ERROR    - general error
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(int)
+_nc_Refresh_Current_Field(FORM *form)
+{
+  WINDOW *formwin;
+  FIELD *field;
+
+  T((T_CALLED("_nc_Refresh_Current_Field(%p)"), (void *)form));
+
+  if (!form)
+    RETURN(E_BAD_ARGUMENT);
+
+  if (!form->w || !form->current)
+    RETURN(E_SYSTEM_ERROR);
+
+  field = form->current;
+  formwin = Get_Form_Window(form);
+
+  if (field->opts & O_PUBLIC)
+    {
+      if (Is_Scroll_Field(field))
+	{
+	  /* Again, in this case the fieldwin isn't derived from formwin,
+	     so we have to perform a copy operation. */
+	  if (Single_Line_Field(field))
+	    {
+	      /* horizontal scrolling */
+	      if (form->curcol < form->begincol)
+		form->begincol = form->curcol;
+	      else
+		{
+		  if (form->curcol >= (form->begincol + field->cols))
+		    form->begincol = form->curcol - field->cols + 1;
+		}
+	      copywin(form->w,
+		      formwin,
+		      0,
+		      form->begincol,
+		      field->frow,
+		      field->fcol,
+		      field->frow,
+		      field->cols + field->fcol - 1,
+		      0);
+	    }
+	  else
+	    {
+	      /* A multi-line, i.e. vertical scrolling field */
+	      int row_after_bottom, first_modified_row, first_unmodified_row;
+
+	      if (field->drows > field->rows)
+		{
+		  row_after_bottom = form->toprow + field->rows;
+		  if (form->currow < form->toprow)
+		    {
+		      form->toprow = form->currow;
+		      field->status |= _NEWTOP;
+		    }
+		  if (form->currow >= row_after_bottom)
+		    {
+		      form->toprow = form->currow - field->rows + 1;
+		      field->status |= _NEWTOP;
+		    }
+		  if (field->status & _NEWTOP)
+		    {
+		      /* means we have to copy whole range */
+		      first_modified_row = form->toprow;
+		      first_unmodified_row = first_modified_row + field->rows;
+		      field->status &= ~_NEWTOP;
+		    }
+		  else
+		    {
+		      /* we try to optimize : finding the range of touched
+		         lines */
+		      first_modified_row = form->toprow;
+		      while (first_modified_row < row_after_bottom)
+			{
+			  if (is_linetouched(form->w, first_modified_row))
+			    break;
+			  first_modified_row++;
+			}
+		      first_unmodified_row = first_modified_row;
+		      while (first_unmodified_row < row_after_bottom)
+			{
+			  if (!is_linetouched(form->w, first_unmodified_row))
+			    break;
+			  first_unmodified_row++;
+			}
+		    }
+		}
+	      else
+		{
+		  first_modified_row = form->toprow;
+		  first_unmodified_row = first_modified_row + field->rows;
+		}
+	      if (first_unmodified_row != first_modified_row)
+		copywin(form->w,
+			formwin,
+			first_modified_row,
+			0,
+			field->frow + first_modified_row - form->toprow,
+			field->fcol,
+			field->frow + first_unmodified_row - form->toprow - 1,
+			field->cols + field->fcol - 1,
+			0);
+	    }
+	  wsyncup(formwin);
+	}
+      else
+	{
+	  /* if the field-window is simply a derived window, i.e. contains no
+	   * invisible parts, the whole thing is trivial
+	   */
+	  wsyncup(form->w);
+	}
+    }
+  untouchwin(form->w);
+  returnCode(_nc_Position_Form_Cursor(form));
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static void Perform_Justification(
+|                                        FIELD  * field,
+|                                        WINDOW * win)
+|
+|   Description   :  Output field with requested justification
+|
+|   Return Values :  -
++--------------------------------------------------------------------------*/
+static void
+Perform_Justification(FIELD *field, WINDOW *win)
+{
+  FIELD_CELL *bp;
+  int len;
+  int col = 0;
+
+  bp = Get_Start_Of_Data(field->buf, Buffer_Length(field));
+  len = (int)(After_End_Of_Data(field->buf, Buffer_Length(field)) - bp);
+
+  if (len > 0)
+    {
+      assert(win && (field->drows == 1) && (field->dcols == field->cols));
+
+      switch (field->just)
+	{
+	case JUSTIFY_LEFT:
+	  break;
+	case JUSTIFY_CENTER:
+	  col = (field->cols - len) / 2;
+	  break;
+	case JUSTIFY_RIGHT:
+	  col = field->cols - len;
+	  break;
+	default:
+	  break;
+	}
+
+      wmove(win, 0, col);
+      myADDNSTR(win, bp, len);
+    }
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static void Undo_Justification(
+|                                     FIELD  * field,
+|                                     WINDOW * win)
+|
+|   Description   :  Display field without any justification, i.e.
+|                    left justified
+|
+|   Return Values :  -
++--------------------------------------------------------------------------*/
+static void
+Undo_Justification(FIELD *field, WINDOW *win)
+{
+  FIELD_CELL *bp;
+  int len;
+
+  bp = Get_Start_Of_Data(field->buf, Buffer_Length(field));
+  len = (int)(After_End_Of_Data(field->buf, Buffer_Length(field)) - bp);
+
+  if (len > 0)
+    {
+      assert(win);
+      wmove(win, 0, 0);
+      myADDNSTR(win, bp, len);
+    }
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static bool Check_Char(FORM  *form,
+|                                           FIELD *field,
+|                                           FIELDTYPE * typ,
+|                                           int ch,
+|                                           TypeArgument *argp)
+|
+|   Description   :  Perform a single character check for character ch
+|                    according to the fieldtype instance.
+|
+|   Return Values :  TRUE             - Character is valid
+|                    FALSE            - Character is invalid
++--------------------------------------------------------------------------*/
+static bool
+Check_Char(FORM *form,
+	   FIELD *field,
+	   FIELDTYPE *typ,
+	   int ch,
+	   TypeArgument *argp)
+{
+  if (typ)
+    {
+      if (typ->status & _LINKED_TYPE)
+	{
+	  assert(argp);
+	  return (
+		   Check_Char(form, field, typ->left, ch, argp->left) ||
+		   Check_Char(form, field, typ->right, ch, argp->right));
+	}
+      else
+	{
+#if NCURSES_INTEROP_FUNCS
+	  if (typ->charcheck.occheck)
+	    {
+	      if (typ->status & _GENERIC)
+		return typ->charcheck.gccheck(ch, form, field, (void *)argp);
+	      else
+		return typ->charcheck.occheck(ch, (void *)argp);
+	    }
+#else
+	  if (typ->ccheck)
+	    return typ->ccheck(ch, (void *)argp);
+#endif
+	}
+    }
+  return (!iscntrl(UChar(ch)) ? TRUE : FALSE);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static int Display_Or_Erase_Field(
+|                                           FIELD * field,
+|                                           bool bEraseFlag)
+|
+|   Description   :  Create a subwindow for the field and display the
+|                    buffer contents (apply justification if required)
+|                    or simply erase the field.
+|
+|   Return Values :  E_OK           - on success
+|                    E_SYSTEM_ERROR - some error (typical no memory)
++--------------------------------------------------------------------------*/
+static int
+Display_Or_Erase_Field(FIELD *field, bool bEraseFlag)
+{
+  WINDOW *win;
+  WINDOW *fwin;
+
+  if (!field)
+    return E_SYSTEM_ERROR;
+
+  fwin = Get_Form_Window(field->form);
+  win = derwin(fwin,
+	       field->rows, field->cols, field->frow, field->fcol);
+
+  if (!win)
+    return E_SYSTEM_ERROR;
+  else
+    {
+      if (field->opts & O_VISIBLE)
+	{
+	  Set_Field_Window_Attributes(field, win);
+	}
+      else
+	{
+	  (void)wattrset(win, WINDOW_ATTRS(fwin));
+	}
+      werase(win);
+    }
+
+  if (!bEraseFlag)
+    {
+      if (field->opts & O_PUBLIC)
+	{
+	  if (Justification_Allowed(field))
+	    Perform_Justification(field, win);
+	  else
+	    Buffer_To_Window(field, win);
+	}
+      field->status &= ~_NEWTOP;
+    }
+  wsyncup(win);
+  delwin(win);
+  return E_OK;
+}
+
+/* Macros to preset the bEraseFlag */
+#define Display_Field(field) Display_Or_Erase_Field(field,FALSE)
+#define Erase_Field(field)   Display_Or_Erase_Field(field,TRUE)
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static int Synchronize_Field(FIELD * field)
+|
+|   Description   :  Synchronize the windows content with the value in
+|                    the buffer.
+|
+|   Return Values :  E_OK                - success
+|                    E_BAD_ARGUMENT      - invalid field pointer
+|                    E_SYSTEM_ERROR      - some severe basic error
++--------------------------------------------------------------------------*/
+static int
+Synchronize_Field(FIELD *field)
+{
+  FORM *form;
+  int res = E_OK;
+
+  if (!field)
+    return (E_BAD_ARGUMENT);
+
+  if (((form = field->form) != (FORM *)0)
+      && Field_Really_Appears(field))
+    {
+      if (field == form->current)
+	{
+	  form->currow = form->curcol = form->toprow = form->begincol = 0;
+	  werase(form->w);
+
+	  if ((field->opts & O_PUBLIC) && Justification_Allowed(field))
+	    Undo_Justification(field, form->w);
+	  else
+	    Buffer_To_Window(field, form->w);
+
+	  field->status |= _NEWTOP;
+	  res = _nc_Refresh_Current_Field(form);
+	}
+      else
+	res = Display_Field(field);
+    }
+  field->status |= _CHANGED;
+  return (res);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static int Synchronize_Linked_Fields(FIELD * field)
+|
+|   Description   :  Propagate the Synchronize_Field function to all linked
+|                    fields. The first error that occurs in the sequence
+|                    of updates is the return value.
+|
+|   Return Values :  E_OK                - success
+|                    E_BAD_ARGUMENT      - invalid field pointer
+|                    E_SYSTEM_ERROR      - some severe basic error
++--------------------------------------------------------------------------*/
+static int
+Synchronize_Linked_Fields(FIELD *field)
+{
+  FIELD *linked_field;
+  int res = E_OK;
+  int syncres;
+
+  if (!field)
+    return (E_BAD_ARGUMENT);
+
+  if (!field->link)
+    return (E_SYSTEM_ERROR);
+
+  for (linked_field = field->link;
+       linked_field != field;
+       linked_field = linked_field->link)
+    {
+      if (((syncres = Synchronize_Field(linked_field)) != E_OK) &&
+	  (res == E_OK))
+	res = syncres;
+    }
+  return (res);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  int _nc_Synchronize_Attributes(FIELD * field)
+|
+|   Description   :  If a fields visual attributes have changed, this
+|                    routine is called to propagate those changes to the
+|                    screen.
+|
+|   Return Values :  E_OK             - success
+|                    E_BAD_ARGUMENT   - invalid field pointer
+|                    E_SYSTEM_ERROR   - some severe basic error
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(int)
+_nc_Synchronize_Attributes(FIELD *field)
+{
+  FORM *form;
+  int res = E_OK;
+  WINDOW *formwin;
+
+  T((T_CALLED("_nc_Synchronize_Attributes(%p)"), (void *)field));
+
+  if (!field)
+    returnCode(E_BAD_ARGUMENT);
+
+  CHECKPOS(field->form);
+  if (((form = field->form) != (FORM *)0)
+      && Field_Really_Appears(field))
+    {
+      if (form->current == field)
+	{
+	  Synchronize_Buffer(form);
+	  Set_Field_Window_Attributes(field, form->w);
+	  werase(form->w);
+	  wmove(form->w, form->currow, form->curcol);
+
+	  if (field->opts & O_PUBLIC)
+	    {
+	      if (Justification_Allowed(field))
+		Undo_Justification(field, form->w);
+	      else
+		Buffer_To_Window(field, form->w);
+	    }
+	  else
+	    {
+	      formwin = Get_Form_Window(form);
+	      copywin(form->w, formwin,
+		      0, 0,
+		      field->frow, field->fcol,
+		      field->rows - 1, field->cols - 1, 0);
+	      wsyncup(formwin);
+	      Buffer_To_Window(field, form->w);
+	      field->status |= _NEWTOP;		/* fake refresh to paint all */
+	      _nc_Refresh_Current_Field(form);
+	    }
+	}
+      else
+	{
+	  res = Display_Field(field);
+	}
+    }
+  CHECKPOS(form);
+  returnCode(res);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  int _nc_Synchronize_Options(FIELD * field,
+|                                                Field_Options newopts)
+|
+|   Description   :  If a fields options have changed, this routine is
+|                    called to propagate these changes to the screen and
+|                    to really change the behavior of the field.
+|
+|   Return Values :  E_OK                - success
+|                    E_BAD_ARGUMENT      - invalid field pointer
+|                    E_CURRENT           - field is the current one
+|                    E_SYSTEM_ERROR      - some severe basic error
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(int)
+_nc_Synchronize_Options(FIELD *field, Field_Options newopts)
+{
+  Field_Options oldopts;
+  Field_Options changed_opts;
+  FORM *form;
+  int res = E_OK;
+
+  T((T_CALLED("_nc_Synchronize_Options(%p,%#x)"), (void *)field, newopts));
+
+  if (!field)
+    returnCode(E_BAD_ARGUMENT);
+
+  oldopts = field->opts;
+  changed_opts = oldopts ^ newopts;
+  field->opts = newopts;
+  form = field->form;
+
+  if (form)
+    {
+      if (form->status & _POSTED)
+	{
+	  if (form->current == field)
+	    {
+	      field->opts = oldopts;
+	      returnCode(E_CURRENT);
+	    }
+	  if ((form->curpage == field->page))
+	    {
+	      if (changed_opts & O_VISIBLE)
+		{
+		  if (newopts & O_VISIBLE)
+		    res = Display_Field(field);
+		  else
+		    res = Erase_Field(field);
+		}
+	      else
+		{
+		  if ((changed_opts & O_PUBLIC) &&
+		      (newopts & O_VISIBLE))
+		    res = Display_Field(field);
+		}
+	    }
+	}
+    }
+
+  if (changed_opts & O_STATIC)
+    {
+      bool single_line_field = Single_Line_Field(field);
+      int res2 = E_OK;
+
+      if (newopts & O_STATIC)
+	{
+	  /* the field becomes now static */
+	  field->status &= ~_MAY_GROW;
+	  /* if actually we have no hidden columns, justification may
+	     occur again */
+	  if (single_line_field &&
+	      (field->cols == field->dcols) &&
+	      (field->just != NO_JUSTIFICATION) &&
+	      Field_Really_Appears(field))
+	    {
+	      res2 = Display_Field(field);
+	    }
+	}
+      else
+	{
+	  /* field is no longer static */
+	  if ((field->maxgrow == 0) ||
+	      (single_line_field && (field->dcols < field->maxgrow)) ||
+	      (!single_line_field && (field->drows < field->maxgrow)))
+	    {
+	      field->status |= _MAY_GROW;
+	      /* a field with justification now changes its behavior,
+	         so we must redisplay it */
+	      if (single_line_field &&
+		  (field->just != NO_JUSTIFICATION) &&
+		  Field_Really_Appears(field))
+		{
+		  res2 = Display_Field(field);
+		}
+	    }
+	}
+      if (res2 != E_OK)
+	res = res2;
+    }
+
+  returnCode(res);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  int _nc_Set_Current_Field(FORM  * form,
+|                                              FIELD * newfield)
+|
+|   Description   :  Make the newfield the new current field.
+|
+|   Return Values :  E_OK              - success
+|                    E_BAD_ARGUMENT    - invalid form or field pointer
+|                    E_SYSTEM_ERROR    - some severe basic error
+|                    E_NOT_CONNECTED   - no fields are connected to the form
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(int)
+_nc_Set_Current_Field(FORM *form, FIELD *newfield)
+{
+  FIELD *field;
+  WINDOW *new_window;
+
+  T((T_CALLED("_nc_Set_Current_Field(%p,%p)"), (void *)form, (void *)newfield));
+
+  if (!form || !newfield || !form->current || (newfield->form != form))
+    returnCode(E_BAD_ARGUMENT);
+
+  if ((form->status & _IN_DRIVER))
+    returnCode(E_BAD_STATE);
+
+  if (!(form->field))
+    returnCode(E_NOT_CONNECTED);
+
+  field = form->current;
+
+  if ((field != newfield) ||
+      !(form->status & _POSTED))
+    {
+      if ((form->w) &&
+	  (field->opts & O_VISIBLE) &&
+	  (field->form->curpage == field->page))
+	{
+	  _nc_Refresh_Current_Field(form);
+	  if (field->opts & O_PUBLIC)
+	    {
+	      if (field->drows > field->rows)
+		{
+		  if (form->toprow == 0)
+		    field->status &= ~_NEWTOP;
+		  else
+		    field->status |= _NEWTOP;
+		}
+	      else
+		{
+		  if (Justification_Allowed(field))
+		    {
+		      Window_To_Buffer(form, field);
+		      werase(form->w);
+		      Perform_Justification(field, form->w);
+		      wsyncup(form->w);
+		    }
+		}
+	    }
+	  delwin(form->w);
+	  form->w = (WINDOW *)0;
+	}
+
+      field = newfield;
+
+      if (Has_Invisible_Parts(field))
+	new_window = newpad(field->drows, field->dcols);
+      else
+	new_window = derwin(Get_Form_Window(form),
+			    field->rows, field->cols, field->frow, field->fcol);
+
+      if (!new_window)
+	returnCode(E_SYSTEM_ERROR);
+
+      form->current = field;
+
+      if (form->w)
+	delwin(form->w);
+      form->w = new_window;
+
+      form->status &= ~_WINDOW_MODIFIED;
+      Set_Field_Window_Attributes(field, form->w);
+
+      if (Has_Invisible_Parts(field))
+	{
+	  werase(form->w);
+	  Buffer_To_Window(field, form->w);
+	}
+      else
+	{
+	  if (Justification_Allowed(field))
+	    {
+	      werase(form->w);
+	      Undo_Justification(field, form->w);
+	      wsyncup(form->w);
+	    }
+	}
+
+      untouchwin(form->w);
+    }
+
+  form->currow = form->curcol = form->toprow = form->begincol = 0;
+  returnCode(E_OK);
+}
+
+/*----------------------------------------------------------------------------
+  Intra-Field Navigation routines
+  --------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static int IFN_Next_Character(FORM * form)
+|
+|   Description   :  Move to the next character in the field. In a multi-line
+|                    field this wraps at the end of the line.
+|
+|   Return Values :  E_OK                - success
+|                    E_REQUEST_DENIED    - at the rightmost position
++--------------------------------------------------------------------------*/
+static int
+IFN_Next_Character(FORM *form)
+{
+  FIELD *field = form->current;
+  int step = myWCWIDTH(form->w, form->currow, form->curcol);
+
+  T((T_CALLED("IFN_Next_Character(%p)"), (void *)form));
+  if ((form->curcol += step) == field->dcols)
+    {
+      if ((++(form->currow)) == field->drows)
+	{
+#if GROW_IF_NAVIGATE
+	  if (!Single_Line_Field(field) && Field_Grown(field, 1))
+	    {
+	      form->curcol = 0;
+	      returnCode(E_OK);
+	    }
+#endif
+	  form->currow--;
+#if GROW_IF_NAVIGATE
+	  if (Single_Line_Field(field) && Field_Grown(field, 1))
+	    returnCode(E_OK);
+#endif
+	  form->curcol -= step;
+	  returnCode(E_REQUEST_DENIED);
+	}
+      form->curcol = 0;
+    }
+  returnCode(E_OK);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static int IFN_Previous_Character(FORM * form)
+|
+|   Description   :  Move to the previous character in the field. In a
+|                    multi-line field this wraps and the beginning of the
+|                    line.
+|
+|   Return Values :  E_OK                - success
+|                    E_REQUEST_DENIED    - at the leftmost position
++--------------------------------------------------------------------------*/
+static int
+IFN_Previous_Character(FORM *form)
+{
+  int amount = myWCWIDTH(form->w, form->currow, form->curcol - 1);
+  int oldcol = form->curcol;
+
+  T((T_CALLED("IFN_Previous_Character(%p)"), (void *)form));
+  if ((form->curcol -= amount) < 0)
+    {
+      if ((--(form->currow)) < 0)
+	{
+	  form->currow++;
+	  form->curcol = oldcol;
+	  returnCode(E_REQUEST_DENIED);
+	}
+      form->curcol = form->current->dcols - 1;
+    }
+  returnCode(E_OK);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static int IFN_Next_Line(FORM * form)
+|
+|   Description   :  Move to the beginning of the next line in the field
+|
+|   Return Values :  E_OK                - success
+|                    E_REQUEST_DENIED    - at the last line
++--------------------------------------------------------------------------*/
+static int
+IFN_Next_Line(FORM *form)
+{
+  FIELD *field = form->current;
+
+  T((T_CALLED("IFN_Next_Line(%p)"), (void *)form));
+  if ((++(form->currow)) == field->drows)
+    {
+#if GROW_IF_NAVIGATE
+      if (!Single_Line_Field(field) && Field_Grown(field, 1))
+	returnCode(E_OK);
+#endif
+      form->currow--;
+      returnCode(E_REQUEST_DENIED);
+    }
+  form->curcol = 0;
+  returnCode(E_OK);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static int IFN_Previous_Line(FORM * form)
+|
+|   Description   :  Move to the beginning of the previous line in the field
+|
+|   Return Values :  E_OK                - success
+|                    E_REQUEST_DENIED    - at the first line
++--------------------------------------------------------------------------*/
+static int
+IFN_Previous_Line(FORM *form)
+{
+  T((T_CALLED("IFN_Previous_Line(%p)"), (void *)form));
+  if ((--(form->currow)) < 0)
+    {
+      form->currow++;
+      returnCode(E_REQUEST_DENIED);
+    }
+  form->curcol = 0;
+  returnCode(E_OK);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static int IFN_Next_Word(FORM * form)
+|
+|   Description   :  Move to the beginning of the next word in the field.
+|
+|   Return Values :  E_OK             - success
+|                    E_REQUEST_DENIED - there is no next word
++--------------------------------------------------------------------------*/
+static int
+IFN_Next_Word(FORM *form)
+{
+  FIELD *field = form->current;
+  FIELD_CELL *bp = Address_Of_Current_Position_In_Buffer(form);
+  FIELD_CELL *s;
+  FIELD_CELL *t;
+
+  T((T_CALLED("IFN_Next_Word(%p)"), (void *)form));
+
+  /* We really need access to the data, so we have to synchronize */
+  Synchronize_Buffer(form);
+
+  /* Go to the first whitespace after the current position (including
+     current position). This is then the starting point to look for the
+     next non-blank data */
+  s = Get_First_Whitespace_Character(bp, Buffer_Length(field) -
+				     (int)(bp - field->buf));
+
+  /* Find the start of the next word */
+  t = Get_Start_Of_Data(s, Buffer_Length(field) -
+			(int)(s - field->buf));
+#if !FRIENDLY_PREV_NEXT_WORD
+  if (s == t)
+    returnCode(E_REQUEST_DENIED);
+  else
+#endif
+    {
+      Adjust_Cursor_Position(form, t);
+      returnCode(E_OK);
+    }
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static int IFN_Previous_Word(FORM * form)
+|
+|   Description   :  Move to the beginning of the previous word in the field.
+|
+|   Return Values :  E_OK             - success
+|                    E_REQUEST_DENIED - there is no previous word
++--------------------------------------------------------------------------*/
+static int
+IFN_Previous_Word(FORM *form)
+{
+  FIELD *field = form->current;
+  FIELD_CELL *bp = Address_Of_Current_Position_In_Buffer(form);
+  FIELD_CELL *s;
+  FIELD_CELL *t;
+  bool again = FALSE;
+
+  T((T_CALLED("IFN_Previous_Word(%p)"), (void *)form));
+
+  /* We really need access to the data, so we have to synchronize */
+  Synchronize_Buffer(form);
+
+  s = After_End_Of_Data(field->buf, (int)(bp - field->buf));
+  /* s points now right after the last non-blank in the buffer before bp.
+     If bp was in a word, s equals bp. In this case we must find the last
+     whitespace in the buffer before bp and repeat the game to really find
+     the previous word! */
+  if (s == bp)
+    again = TRUE;
+
+  /* And next call now goes backward to look for the last whitespace
+     before that, pointing right after this, so it points to the begin
+     of the previous word.
+   */
+  t = After_Last_Whitespace_Character(field->buf, (int)(s - field->buf));
+#if !FRIENDLY_PREV_NEXT_WORD
+  if (s == t)
+    returnCode(E_REQUEST_DENIED);
+#endif
+  if (again)
+    {
+      /* and do it again, replacing bp by t */
+      s = After_End_Of_Data(field->buf, (int)(t - field->buf));
+      t = After_Last_Whitespace_Character(field->buf, (int)(s - field->buf));
+#if !FRIENDLY_PREV_NEXT_WORD
+      if (s == t)
+	returnCode(E_REQUEST_DENIED);
+#endif
+    }
+  Adjust_Cursor_Position(form, t);
+  returnCode(E_OK);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static int IFN_Beginning_Of_Field(FORM * form)
+|
+|   Description   :  Place the cursor at the first non-pad character in
+|                    the field.
+|
+|   Return Values :  E_OK             - success
++--------------------------------------------------------------------------*/
+static int
+IFN_Beginning_Of_Field(FORM *form)
+{
+  FIELD *field = form->current;
+
+  T((T_CALLED("IFN_Beginning_Of_Field(%p)"), (void *)form));
+  Synchronize_Buffer(form);
+  Adjust_Cursor_Position(form,
+			 Get_Start_Of_Data(field->buf, Buffer_Length(field)));
+  returnCode(E_OK);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static int IFN_End_Of_Field(FORM * form)
+|
+|   Description   :  Place the cursor after the last non-pad character in
+|                    the field. If the field occupies the last position in
+|                    the buffer, the cursor is positioned on the last
+|                    character.
+|
+|   Return Values :  E_OK              - success
++--------------------------------------------------------------------------*/
+static int
+IFN_End_Of_Field(FORM *form)
+{
+  FIELD *field = form->current;
+  FIELD_CELL *pos;
+
+  T((T_CALLED("IFN_End_Of_Field(%p)"), (void *)form));
+  Synchronize_Buffer(form);
+  pos = After_End_Of_Data(field->buf, Buffer_Length(field));
+  if (pos == (field->buf + Buffer_Length(field)))
+    pos--;
+  Adjust_Cursor_Position(form, pos);
+  returnCode(E_OK);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static int IFN_Beginning_Of_Line(FORM * form)
+|
+|   Description   :  Place the cursor on the first non-pad character in
+|                    the current line of the field.
+|
+|   Return Values :  E_OK         - success
++--------------------------------------------------------------------------*/
+static int
+IFN_Beginning_Of_Line(FORM *form)
+{
+  FIELD *field = form->current;
+
+  T((T_CALLED("IFN_Beginning_Of_Line(%p)"), (void *)form));
+  Synchronize_Buffer(form);
+  Adjust_Cursor_Position(form,
+			 Get_Start_Of_Data(Address_Of_Current_Row_In_Buffer(form),
+					   field->dcols));
+  returnCode(E_OK);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static int IFN_End_Of_Line(FORM * form)
+|
+|   Description   :  Place the cursor after the last non-pad character in the
+|                    current line of the field. If the field occupies the
+|                    last column in the line, the cursor is positioned on the
+|                    last character of the line.
+|
+|   Return Values :  E_OK        - success
++--------------------------------------------------------------------------*/
+static int
+IFN_End_Of_Line(FORM *form)
+{
+  FIELD *field = form->current;
+  FIELD_CELL *pos;
+  FIELD_CELL *bp;
+
+  T((T_CALLED("IFN_End_Of_Line(%p)"), (void *)form));
+  Synchronize_Buffer(form);
+  bp = Address_Of_Current_Row_In_Buffer(form);
+  pos = After_End_Of_Data(bp, field->dcols);
+  if (pos == (bp + field->dcols))
+    pos--;
+  Adjust_Cursor_Position(form, pos);
+  returnCode(E_OK);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static int IFN_Left_Character(FORM * form)
+|
+|   Description   :  Move one character to the left in the current line.
+|                    This doesn't cycle.
+|
+|   Return Values :  E_OK             - success
+|                    E_REQUEST_DENIED - already in first column
++--------------------------------------------------------------------------*/
+static int
+IFN_Left_Character(FORM *form)
+{
+  int amount = myWCWIDTH(form->w, form->currow, form->curcol - 1);
+  int oldcol = form->curcol;
+
+  T((T_CALLED("IFN_Left_Character(%p)"), (void *)form));
+  if ((form->curcol -= amount) < 0)
+    {
+      form->curcol = oldcol;
+      returnCode(E_REQUEST_DENIED);
+    }
+  returnCode(E_OK);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static int IFN_Right_Character(FORM * form)
+|
+|   Description   :  Move one character to the right in the current line.
+|                    This doesn't cycle.
+|
+|   Return Values :  E_OK              - success
+|                    E_REQUEST_DENIED  - already in last column
++--------------------------------------------------------------------------*/
+static int
+IFN_Right_Character(FORM *form)
+{
+  int amount = myWCWIDTH(form->w, form->currow, form->curcol);
+  int oldcol = form->curcol;
+
+  T((T_CALLED("IFN_Right_Character(%p)"), (void *)form));
+  if ((form->curcol += amount) >= form->current->dcols)
+    {
+#if GROW_IF_NAVIGATE
+      FIELD *field = form->current;
+
+      if (Single_Line_Field(field) && Field_Grown(field, 1))
+	returnCode(E_OK);
+#endif
+      form->curcol = oldcol;
+      returnCode(E_REQUEST_DENIED);
+    }
+  returnCode(E_OK);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static int IFN_Up_Character(FORM * form)
+|
+|   Description   :  Move one line up. This doesn't cycle through the lines
+|                    of the field.
+|
+|   Return Values :  E_OK              - success
+|                    E_REQUEST_DENIED  - already in last column
++--------------------------------------------------------------------------*/
+static int
+IFN_Up_Character(FORM *form)
+{
+  T((T_CALLED("IFN_Up_Character(%p)"), (void *)form));
+  if ((--(form->currow)) < 0)
+    {
+      form->currow++;
+      returnCode(E_REQUEST_DENIED);
+    }
+  returnCode(E_OK);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static int IFN_Down_Character(FORM * form)
+|
+|   Description   :  Move one line down. This doesn't cycle through the
+|                    lines of the field.
+|
+|   Return Values :  E_OK              - success
+|                    E_REQUEST_DENIED  - already in last column
++--------------------------------------------------------------------------*/
+static int
+IFN_Down_Character(FORM *form)
+{
+  FIELD *field = form->current;
+
+  T((T_CALLED("IFN_Down_Character(%p)"), (void *)form));
+  if ((++(form->currow)) == field->drows)
+    {
+#if GROW_IF_NAVIGATE
+      if (!Single_Line_Field(field) && Field_Grown(field, 1))
+	returnCode(E_OK);
+#endif
+      --(form->currow);
+      returnCode(E_REQUEST_DENIED);
+    }
+  returnCode(E_OK);
+}
+/*----------------------------------------------------------------------------
+  END of Intra-Field Navigation routines
+  --------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+  Vertical scrolling helper routines
+  --------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static int VSC_Generic(FORM *form, int nlines)
+|
+|   Description   :  Scroll multi-line field forward (nlines>0) or
+|                    backward (nlines<0) this many lines.
+|
+|   Return Values :  E_OK              - success
+|                    E_REQUEST_DENIED  - can't scroll
++--------------------------------------------------------------------------*/
+static int
+VSC_Generic(FORM *form, int nlines)
+{
+  FIELD *field = form->current;
+  int res = E_REQUEST_DENIED;
+  int rows_to_go = (nlines > 0 ? nlines : -nlines);
+
+  if (nlines > 0)
+    {
+      if ((rows_to_go + form->toprow) > (field->drows - field->rows))
+	rows_to_go = (field->drows - field->rows - form->toprow);
+
+      if (rows_to_go > 0)
+	{
+	  form->currow += rows_to_go;
+	  form->toprow += rows_to_go;
+	  res = E_OK;
+	}
+    }
+  else
+    {
+      if (rows_to_go > form->toprow)
+	rows_to_go = form->toprow;
+
+      if (rows_to_go > 0)
+	{
+	  form->currow -= rows_to_go;
+	  form->toprow -= rows_to_go;
+	  res = E_OK;
+	}
+    }
+  return (res);
+}
+/*----------------------------------------------------------------------------
+  End of Vertical scrolling helper routines
+  --------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+  Vertical scrolling routines
+  --------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static int Vertical_Scrolling(
+|                                           int (* const fct) (FORM *),
+|                                           FORM * form)
+|
+|   Description   :  Performs the generic vertical scrolling routines.
+|                    This has to check for a multi-line field and to set
+|                    the _NEWTOP flag if scrolling really occurred.
+|
+|   Return Values :  Propagated error code from low-level driver calls
++--------------------------------------------------------------------------*/
+static int
+Vertical_Scrolling(int (*const fct) (FORM *), FORM *form)
+{
+  int res = E_REQUEST_DENIED;
+
+  if (!Single_Line_Field(form->current))
+    {
+      res = fct(form);
+      if (res == E_OK)
+	form->current->status |= _NEWTOP;
+    }
+  return (res);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static int VSC_Scroll_Line_Forward(FORM * form)
+|
+|   Description   :  Scroll multi-line field forward a line
+|
+|   Return Values :  E_OK                - success
+|                    E_REQUEST_DENIED    - no data ahead
++--------------------------------------------------------------------------*/
+static int
+VSC_Scroll_Line_Forward(FORM *form)
+{
+  T((T_CALLED("VSC_Scroll_Line_Forward(%p)"), (void *)form));
+  returnCode(VSC_Generic(form, 1));
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static int VSC_Scroll_Line_Backward(FORM * form)
+|
+|   Description   :  Scroll multi-line field backward a line
+|
+|   Return Values :  E_OK                - success
+|                    E_REQUEST_DENIED    - no data behind
++--------------------------------------------------------------------------*/
+static int
+VSC_Scroll_Line_Backward(FORM *form)
+{
+  T((T_CALLED("VSC_Scroll_Line_Backward(%p)"), (void *)form));
+  returnCode(VSC_Generic(form, -1));
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static int VSC_Scroll_Page_Forward(FORM * form)
+|
+|   Description   :  Scroll a multi-line field forward a page
+|
+|   Return Values :  E_OK              - success
+|                    E_REQUEST_DENIED  - no data ahead
++--------------------------------------------------------------------------*/
+static int
+VSC_Scroll_Page_Forward(FORM *form)
+{
+  T((T_CALLED("VSC_Scroll_Page_Forward(%p)"), (void *)form));
+  returnCode(VSC_Generic(form, form->current->rows));
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static int VSC_Scroll_Half_Page_Forward(FORM * form)
+|
+|   Description   :  Scroll a multi-line field forward half a page
+|
+|   Return Values :  E_OK              - success
+|                    E_REQUEST_DENIED  - no data ahead
++--------------------------------------------------------------------------*/
+static int
+VSC_Scroll_Half_Page_Forward(FORM *form)
+{
+  T((T_CALLED("VSC_Scroll_Half_Page_Forward(%p)"), (void *)form));
+  returnCode(VSC_Generic(form, (form->current->rows + 1) / 2));
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static int VSC_Scroll_Page_Backward(FORM * form)
+|
+|   Description   :  Scroll a multi-line field backward a page
+|
+|   Return Values :  E_OK              - success
+|                    E_REQUEST_DENIED  - no data behind
++--------------------------------------------------------------------------*/
+static int
+VSC_Scroll_Page_Backward(FORM *form)
+{
+  T((T_CALLED("VSC_Scroll_Page_Backward(%p)"), (void *)form));
+  returnCode(VSC_Generic(form, -(form->current->rows)));
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static int VSC_Scroll_Half_Page_Backward(FORM * form)
+|
+|   Description   :  Scroll a multi-line field backward half a page
+|
+|   Return Values :  E_OK              - success
+|                    E_REQUEST_DENIED  - no data behind
++--------------------------------------------------------------------------*/
+static int
+VSC_Scroll_Half_Page_Backward(FORM *form)
+{
+  T((T_CALLED("VSC_Scroll_Half_Page_Backward(%p)"), (void *)form));
+  returnCode(VSC_Generic(form, -((form->current->rows + 1) / 2)));
+}
+/*----------------------------------------------------------------------------
+  End of Vertical scrolling routines
+  --------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+  Horizontal scrolling helper routines
+  --------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static int HSC_Generic(FORM *form, int ncolumns)
+|
+|   Description   :  Scroll single-line field forward (ncolumns>0) or
+|                    backward (ncolumns<0) this many columns.
+|
+|   Return Values :  E_OK              - success
+|                    E_REQUEST_DENIED  - can't scroll
++--------------------------------------------------------------------------*/
+static int
+HSC_Generic(FORM *form, int ncolumns)
+{
+  FIELD *field = form->current;
+  int res = E_REQUEST_DENIED;
+  int cols_to_go = (ncolumns > 0 ? ncolumns : -ncolumns);
+
+  if (ncolumns > 0)
+    {
+      if ((cols_to_go + form->begincol) > (field->dcols - field->cols))
+	cols_to_go = field->dcols - field->cols - form->begincol;
+
+      if (cols_to_go > 0)
+	{
+	  form->curcol += cols_to_go;
+	  form->begincol += cols_to_go;
+	  res = E_OK;
+	}
+    }
+  else
+    {
+      if (cols_to_go > form->begincol)
+	cols_to_go = form->begincol;
+
+      if (cols_to_go > 0)
+	{
+	  form->curcol -= cols_to_go;
+	  form->begincol -= cols_to_go;
+	  res = E_OK;
+	}
+    }
+  return (res);
+}
+/*----------------------------------------------------------------------------
+  End of Horizontal scrolling helper routines
+  --------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+  Horizontal scrolling routines
+  --------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static int Horizontal_Scrolling(
+|                                          int (* const fct) (FORM *),
+|                                          FORM * form)
+|
+|   Description   :  Performs the generic horizontal scrolling routines.
+|                    This has to check for a single-line field.
+|
+|   Return Values :  Propagated error code from low-level driver calls
++--------------------------------------------------------------------------*/
+static int
+Horizontal_Scrolling(int (*const fct) (FORM *), FORM *form)
+{
+  if (Single_Line_Field(form->current))
+    return fct(form);
+  else
+    return (E_REQUEST_DENIED);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static int HSC_Scroll_Char_Forward(FORM * form)
+|
+|   Description   :  Scroll single-line field forward a character
+|
+|   Return Values :  E_OK                - success
+|                    E_REQUEST_DENIED    - no data ahead
++--------------------------------------------------------------------------*/
+static int
+HSC_Scroll_Char_Forward(FORM *form)
+{
+  T((T_CALLED("HSC_Scroll_Char_Forward(%p)"), (void *)form));
+  returnCode(HSC_Generic(form, 1));
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static int HSC_Scroll_Char_Backward(FORM * form)
+|
+|   Description   :  Scroll single-line field backward a character
+|
+|   Return Values :  E_OK                - success
+|                    E_REQUEST_DENIED    - no data behind
++--------------------------------------------------------------------------*/
+static int
+HSC_Scroll_Char_Backward(FORM *form)
+{
+  T((T_CALLED("HSC_Scroll_Char_Backward(%p)"), (void *)form));
+  returnCode(HSC_Generic(form, -1));
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static int HSC_Horizontal_Line_Forward(FORM* form)
+|
+|   Description   :  Scroll single-line field forward a line
+|
+|   Return Values :  E_OK                - success
+|                    E_REQUEST_DENIED    - no data ahead
++--------------------------------------------------------------------------*/
+static int
+HSC_Horizontal_Line_Forward(FORM *form)
+{
+  T((T_CALLED("HSC_Horizontal_Line_Forward(%p)"), (void *)form));
+  returnCode(HSC_Generic(form, form->current->cols));
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static int HSC_Horizontal_Half_Line_Forward(FORM* form)
+|
+|   Description   :  Scroll single-line field forward half a line
+|
+|   Return Values :  E_OK               - success
+|                    E_REQUEST_DENIED   - no data ahead
++--------------------------------------------------------------------------*/
+static int
+HSC_Horizontal_Half_Line_Forward(FORM *form)
+{
+  T((T_CALLED("HSC_Horizontal_Half_Line_Forward(%p)"), (void *)form));
+  returnCode(HSC_Generic(form, (form->current->cols + 1) / 2));
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static int HSC_Horizontal_Line_Backward(FORM* form)
+|
+|   Description   :  Scroll single-line field backward a line
+|
+|   Return Values :  E_OK                - success
+|                    E_REQUEST_DENIED    - no data behind
++--------------------------------------------------------------------------*/
+static int
+HSC_Horizontal_Line_Backward(FORM *form)
+{
+  T((T_CALLED("HSC_Horizontal_Line_Backward(%p)"), (void *)form));
+  returnCode(HSC_Generic(form, -(form->current->cols)));
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static int HSC_Horizontal_Half_Line_Backward(FORM* form)
+|
+|   Description   :  Scroll single-line field backward half a line
+|
+|   Return Values :  E_OK                - success
+|                    E_REQUEST_DENIED    - no data behind
++--------------------------------------------------------------------------*/
+static int
+HSC_Horizontal_Half_Line_Backward(FORM *form)
+{
+  T((T_CALLED("HSC_Horizontal_Half_Line_Backward(%p)"), (void *)form));
+  returnCode(HSC_Generic(form, -((form->current->cols + 1) / 2)));
+}
+
+/*----------------------------------------------------------------------------
+  End of Horizontal scrolling routines
+  --------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+  Helper routines for Field Editing
+  --------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static bool Is_There_Room_For_A_Line(FORM * form)
+|
+|   Description   :  Check whether or not there is enough room in the
+|                    buffer to enter a whole line.
+|
+|   Return Values :  TRUE   - there is enough space
+|                    FALSE  - there is not enough space
++--------------------------------------------------------------------------*/
+NCURSES_INLINE static bool
+Is_There_Room_For_A_Line(FORM *form)
+{
+  FIELD *field = form->current;
+  FIELD_CELL *begin_of_last_line, *s;
+
+  Synchronize_Buffer(form);
+  begin_of_last_line = Address_Of_Row_In_Buffer(field, (field->drows - 1));
+  s = After_End_Of_Data(begin_of_last_line, field->dcols);
+  return ((s == begin_of_last_line) ? TRUE : FALSE);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static bool Is_There_Room_For_A_Char_In_Line(FORM * form)
+|
+|   Description   :  Checks whether or not there is room for a new character
+|                    in the current line.
+|
+|   Return Values :  TRUE    - there is room
+|                    FALSE   - there is not enough room (line full)
++--------------------------------------------------------------------------*/
+NCURSES_INLINE static bool
+Is_There_Room_For_A_Char_In_Line(FORM *form)
+{
+  int last_char_in_line;
+
+  wmove(form->w, form->currow, form->current->dcols - 1);
+  last_char_in_line = (int)(winch(form->w) & A_CHARTEXT);
+  wmove(form->w, form->currow, form->curcol);
+  return (((last_char_in_line == form->current->pad) ||
+	   is_blank(last_char_in_line)) ? TRUE : FALSE);
+}
+
+#define There_Is_No_Room_For_A_Char_In_Line(f) \
+  !Is_There_Room_For_A_Char_In_Line(f)
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static int Insert_String(
+|                                             FORM * form,
+|                                             int row,
+|                                             char *txt,
+|                                             int  len )
+|
+|   Description   :  Insert the 'len' characters beginning at pointer 'txt'
+|                    into the 'row' of the 'form'. The insertion occurs
+|                    on the beginning of the row, all other characters are
+|                    moved to the right. After the text a pad character will
+|                    be inserted to separate the text from the rest. If
+|                    necessary the insertion moves characters on the next
+|                    line to make place for the requested insertion string.
+|
+|   Return Values :  E_OK              - success
+|                    E_REQUEST_DENIED  -
+|                    E_SYSTEM_ERROR    - system error
++--------------------------------------------------------------------------*/
+static int
+Insert_String(FORM *form, int row, FIELD_CELL *txt, int len)
+{
+  FIELD *field = form->current;
+  FIELD_CELL *bp = Address_Of_Row_In_Buffer(field, row);
+  int datalen = (int)(After_End_Of_Data(bp, field->dcols) - bp);
+  int freelen = field->dcols - datalen;
+  int requiredlen = len + 1;
+  FIELD_CELL *split;
+  int result = E_REQUEST_DENIED;
+
+  if (freelen >= requiredlen)
+    {
+      wmove(form->w, row, 0);
+      myINSNSTR(form->w, txt, len);
+      wmove(form->w, row, len);
+      myINSNSTR(form->w, &myBLANK, 1);
+      return E_OK;
+    }
+  else
+    {
+      /* we have to move characters on the next line. If we are on the
+         last line this may work, if the field is growable */
+      if ((row == (field->drows - 1)) && Growable(field))
+	{
+	  if (!Field_Grown(field, 1))
+	    return (E_SYSTEM_ERROR);
+	  /* !!!Side-Effect : might be changed due to growth!!! */
+	  bp = Address_Of_Row_In_Buffer(field, row);
+	}
+
+      if (row < (field->drows - 1))
+	{
+	  split =
+	    After_Last_Whitespace_Character(bp,
+					    (int)(Get_Start_Of_Data(bp
+								    + field->dcols
+								    - requiredlen,
+								    requiredlen)
+						  - bp));
+	  /* split points now to the first character of the portion of the
+	     line that must be moved to the next line */
+	  datalen = (int)(split - bp);	/* + freelen has to stay on this line   */
+	  freelen = field->dcols - (datalen + freelen);		/* for the next line */
+
+	  if ((result = Insert_String(form, row + 1, split, freelen)) == E_OK)
+	    {
+	      wmove(form->w, row, datalen);
+	      wclrtoeol(form->w);
+	      wmove(form->w, row, 0);
+	      myINSNSTR(form->w, txt, len);
+	      wmove(form->w, row, len);
+	      myINSNSTR(form->w, &myBLANK, 1);
+	      return E_OK;
+	    }
+	}
+      return (result);
+    }
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static int Wrapping_Not_Necessary_Or_Wrapping_Ok(
+|                                             FORM * form)
+|
+|   Description   :  If a character has been entered into a field, it may
+|                    be that wrapping has to occur. This routine checks
+|                    whether or not wrapping is required and if so, performs
+|                    the wrapping.
+|
+|   Return Values :  E_OK              - no wrapping required or wrapping
+|                                        was successful
+|                    E_REQUEST_DENIED  -
+|                    E_SYSTEM_ERROR    - some system error
++--------------------------------------------------------------------------*/
+static int
+Wrapping_Not_Necessary_Or_Wrapping_Ok(FORM *form)
+{
+  FIELD *field = form->current;
+  int result = E_REQUEST_DENIED;
+  bool Last_Row = ((field->drows - 1) == form->currow);
+
+  if ((field->opts & O_WRAP) &&	/* wrapping wanted     */
+      (!Single_Line_Field(field)) &&	/* must be multi-line  */
+      (There_Is_No_Room_For_A_Char_In_Line(form)) &&	/* line is full        */
+      (!Last_Row || Growable(field)))	/* there are more lines */
+    {
+      FIELD_CELL *bp;
+      FIELD_CELL *split;
+      int chars_to_be_wrapped;
+      int chars_to_remain_on_line;
+
+      if (Last_Row)
+	{
+	  /* the above logic already ensures, that in this case the field
+	     is growable */
+	  if (!Field_Grown(field, 1))
+	    return E_SYSTEM_ERROR;
+	}
+      bp = Address_Of_Current_Row_In_Buffer(form);
+      Window_To_Buffer(form, field);
+      split = After_Last_Whitespace_Character(bp, field->dcols);
+      /* split points to the first character of the sequence to be brought
+         on the next line */
+      chars_to_remain_on_line = (int)(split - bp);
+      chars_to_be_wrapped = field->dcols - chars_to_remain_on_line;
+      if (chars_to_remain_on_line > 0)
+	{
+	  if ((result = Insert_String(form, form->currow + 1, split,
+				      chars_to_be_wrapped)) == E_OK)
+	    {
+	      wmove(form->w, form->currow, chars_to_remain_on_line);
+	      wclrtoeol(form->w);
+	      if (form->curcol >= chars_to_remain_on_line)
+		{
+		  form->currow++;
+		  form->curcol -= chars_to_remain_on_line;
+		}
+	      return E_OK;
+	    }
+	}
+      else
+	return E_OK;
+      if (result != E_OK)
+	{
+	  DeleteChar(form);
+	  Window_To_Buffer(form, field);
+	  result = E_REQUEST_DENIED;
+	}
+    }
+  else
+    result = E_OK;		/* wrapping was not necessary */
+  return (result);
+}
+
+/*----------------------------------------------------------------------------
+  Field Editing routines
+  --------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static int Field_Editing(
+|                                    int (* const fct) (FORM *),
+|                                    FORM * form)
+|
+|   Description   :  Generic routine for field editing requests. The driver
+|                    routines are only called for editable fields, the
+|                    _WINDOW_MODIFIED flag is set if editing occurred.
+|                    This is somewhat special due to the overload semantics
+|                    of the NEW_LINE and DEL_PREV requests.
+|
+|   Return Values :  Error code from low level drivers.
++--------------------------------------------------------------------------*/
+static int
+Field_Editing(int (*const fct) (FORM *), FORM *form)
+{
+  int res = E_REQUEST_DENIED;
+
+  /* We have to deal here with the specific case of the overloaded
+     behavior of New_Line and Delete_Previous requests.
+     They may end up in navigational requests if we are on the first
+     character in a field. But navigation is also allowed on non-
+     editable fields.
+   */
+  if ((fct == FE_Delete_Previous) &&
+      (form->opts & O_BS_OVERLOAD) &&
+      First_Position_In_Current_Field(form))
+    {
+      res = Inter_Field_Navigation(FN_Previous_Field, form);
+    }
+  else
+    {
+      if (fct == FE_New_Line)
+	{
+	  if ((form->opts & O_NL_OVERLOAD) &&
+	      First_Position_In_Current_Field(form))
+	    {
+	      res = Inter_Field_Navigation(FN_Next_Field, form);
+	    }
+	  else
+	    /* FE_New_Line deals itself with the _WINDOW_MODIFIED flag */
+	    res = fct(form);
+	}
+      else
+	{
+	  /* From now on, everything must be editable */
+	  if (form->current->opts & O_EDIT)
+	    {
+	      res = fct(form);
+	      if (res == E_OK)
+		form->status |= _WINDOW_MODIFIED;
+	    }
+	}
+    }
+  return res;
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static int FE_New_Line(FORM * form)
+|
+|   Description   :  Perform a new line request. This is rather complex
+|                    compared to other routines in this code due to the
+|                    rather difficult to understand description in the
+|                    manuals.
+|
+|   Return Values :  E_OK               - success
+|                    E_REQUEST_DENIED   - new line not allowed
+|                    E_SYSTEM_ERROR     - system error
++--------------------------------------------------------------------------*/
+static int
+FE_New_Line(FORM *form)
+{
+  FIELD *field = form->current;
+  FIELD_CELL *bp, *t;
+  bool Last_Row = ((field->drows - 1) == form->currow);
+
+  T((T_CALLED("FE_New_Line(%p)"), (void *)form));
+  if (form->status & _OVLMODE)
+    {
+      if (Last_Row &&
+	  (!(Growable(field) && !Single_Line_Field(field))))
+	{
+	  if (!(form->opts & O_NL_OVERLOAD))
+	    returnCode(E_REQUEST_DENIED);
+	  wmove(form->w, form->currow, form->curcol);
+	  wclrtoeol(form->w);
+	  /* we have to set this here, although it is also
+	     handled in the generic routine. The reason is,
+	     that FN_Next_Field may fail, but the form is
+	     definitively changed */
+	  form->status |= _WINDOW_MODIFIED;
+	  returnCode(Inter_Field_Navigation(FN_Next_Field, form));
+	}
+      else
+	{
+	  if (Last_Row && !Field_Grown(field, 1))
+	    {
+	      /* N.B.: due to the logic in the 'if', LastRow==TRUE
+	         means here that the field is growable and not
+	         a single-line field */
+	      returnCode(E_SYSTEM_ERROR);
+	    }
+	  wmove(form->w, form->currow, form->curcol);
+	  wclrtoeol(form->w);
+	  form->currow++;
+	  form->curcol = 0;
+	  form->status |= _WINDOW_MODIFIED;
+	  returnCode(E_OK);
+	}
+    }
+  else
+    {
+      /* Insert Mode */
+      if (Last_Row &&
+	  !(Growable(field) && !Single_Line_Field(field)))
+	{
+	  if (!(form->opts & O_NL_OVERLOAD))
+	    returnCode(E_REQUEST_DENIED);
+	  returnCode(Inter_Field_Navigation(FN_Next_Field, form));
+	}
+      else
+	{
+	  bool May_Do_It = !Last_Row && Is_There_Room_For_A_Line(form);
+
+	  if (!(May_Do_It || Growable(field)))
+	    returnCode(E_REQUEST_DENIED);
+	  if (!May_Do_It && !Field_Grown(field, 1))
+	    returnCode(E_SYSTEM_ERROR);
+
+	  bp = Address_Of_Current_Position_In_Buffer(form);
+	  t = After_End_Of_Data(bp, field->dcols - form->curcol);
+	  wmove(form->w, form->currow, form->curcol);
+	  wclrtoeol(form->w);
+	  form->currow++;
+	  form->curcol = 0;
+	  wmove(form->w, form->currow, form->curcol);
+	  winsertln(form->w);
+	  myADDNSTR(form->w, bp, (int)(t - bp));
+	  form->status |= _WINDOW_MODIFIED;
+	  returnCode(E_OK);
+	}
+    }
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static int FE_Insert_Character(FORM * form)
+|
+|   Description   :  Insert blank character at the cursor position
+|
+|   Return Values :  E_OK
+|                    E_REQUEST_DENIED
++--------------------------------------------------------------------------*/
+static int
+FE_Insert_Character(FORM *form)
+{
+  FIELD *field = form->current;
+  int result = E_REQUEST_DENIED;
+
+  T((T_CALLED("FE_Insert_Character(%p)"), (void *)form));
+  if (Check_Char(form, field, field->type, (int)C_BLANK,
+		 (TypeArgument *)(field->arg)))
+    {
+      bool There_Is_Room = Is_There_Room_For_A_Char_In_Line(form);
+
+      if (There_Is_Room ||
+	  ((Single_Line_Field(field) && Growable(field))))
+	{
+	  if (!There_Is_Room && !Field_Grown(field, 1))
+	    result = E_SYSTEM_ERROR;
+	  else
+	    {
+	      winsch(form->w, (chtype)C_BLANK);
+	      result = Wrapping_Not_Necessary_Or_Wrapping_Ok(form);
+	    }
+	}
+    }
+  returnCode(result);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static int FE_Insert_Line(FORM * form)
+|
+|   Description   :  Insert a blank line at the cursor position
+|
+|   Return Values :  E_OK               - success
+|                    E_REQUEST_DENIED   - line can not be inserted
++--------------------------------------------------------------------------*/
+static int
+FE_Insert_Line(FORM *form)
+{
+  FIELD *field = form->current;
+  int result = E_REQUEST_DENIED;
+
+  T((T_CALLED("FE_Insert_Line(%p)"), (void *)form));
+  if (Check_Char(form, field,
+		 field->type, (int)C_BLANK, (TypeArgument *)(field->arg)))
+    {
+      bool Maybe_Done = (form->currow != (field->drows - 1)) &&
+      Is_There_Room_For_A_Line(form);
+
+      if (!Single_Line_Field(field) &&
+	  (Maybe_Done || Growable(field)))
+	{
+	  if (!Maybe_Done && !Field_Grown(field, 1))
+	    result = E_SYSTEM_ERROR;
+	  else
+	    {
+	      form->curcol = 0;
+	      winsertln(form->w);
+	      result = E_OK;
+	    }
+	}
+    }
+  returnCode(result);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static int FE_Delete_Character(FORM * form)
+|
+|   Description   :  Delete character at the cursor position
+|
+|   Return Values :  E_OK    - success
++--------------------------------------------------------------------------*/
+static int
+FE_Delete_Character(FORM *form)
+{
+  T((T_CALLED("FE_Delete_Character(%p)"), (void *)form));
+  DeleteChar(form);
+  returnCode(E_OK);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static int FE_Delete_Previous(FORM * form)
+|
+|   Description   :  Delete character before cursor. Again this is a rather
+|                    difficult piece compared to others due to the overloading
+|                    semantics of backspace.
+|                    N.B.: The case of overloaded BS on first field position
+|                          is already handled in the generic routine.
+|
+|   Return Values :  E_OK                - success
+|                    E_REQUEST_DENIED    - Character can't be deleted
++--------------------------------------------------------------------------*/
+static int
+FE_Delete_Previous(FORM *form)
+{
+  FIELD *field = form->current;
+
+  T((T_CALLED("FE_Delete_Previous(%p)"), (void *)form));
+  if (First_Position_In_Current_Field(form))
+    returnCode(E_REQUEST_DENIED);
+
+  if ((--(form->curcol)) < 0)
+    {
+      FIELD_CELL *this_line, *prev_line, *prev_end, *this_end;
+      int this_row = form->currow;
+
+      form->curcol++;
+      if (form->status & _OVLMODE)
+	returnCode(E_REQUEST_DENIED);
+
+      prev_line = Address_Of_Row_In_Buffer(field, (form->currow - 1));
+      this_line = Address_Of_Row_In_Buffer(field, (form->currow));
+      Synchronize_Buffer(form);
+      prev_end = After_End_Of_Data(prev_line, field->dcols);
+      this_end = After_End_Of_Data(this_line, field->dcols);
+      if ((int)(this_end - this_line) >
+	  (field->cols - (int)(prev_end - prev_line)))
+	returnCode(E_REQUEST_DENIED);
+      wmove(form->w, form->currow, form->curcol);
+      wdeleteln(form->w);
+      Adjust_Cursor_Position(form, prev_end);
+      /*
+       * If we did not really move to the previous line, help the user a
+       * little.  It is however a little inconsistent.  Normally, when
+       * backspacing around the point where text wraps to a new line in a
+       * multi-line form, we absorb one keystroke for the wrapping point.  That
+       * is consistent with SVr4 forms.  However, SVr4 does not allow typing
+       * into the last column of the field, and requires the user to enter a
+       * newline to move to the next line.  Therefore it can consistently eat
+       * that keystroke.  Since ncurses allows the last column, it wraps
+       * automatically (given the proper options).  But we cannot eat the
+       * keystroke to back over the wrapping point, since that would put the
+       * cursor past the end of the form field.  In this case, just delete the
+       * character at the end of the field.
+       */
+      if (form->currow == this_row && this_row > 0)
+	{
+	  form->currow -= 1;
+	  form->curcol = field->dcols - 1;
+	  DeleteChar(form);
+	}
+      else
+	{
+	  wmove(form->w, form->currow, form->curcol);
+	  myADDNSTR(form->w, this_line, (int)(this_end - this_line));
+	}
+    }
+  else
+    {
+      DeleteChar(form);
+    }
+  returnCode(E_OK);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static int FE_Delete_Line(FORM * form)
+|
+|   Description   :  Delete line at cursor position.
+|
+|   Return Values :  E_OK  - success
++--------------------------------------------------------------------------*/
+static int
+FE_Delete_Line(FORM *form)
+{
+  T((T_CALLED("FE_Delete_Line(%p)"), (void *)form));
+  form->curcol = 0;
+  wdeleteln(form->w);
+  returnCode(E_OK);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static int FE_Delete_Word(FORM * form)
+|
+|   Description   :  Delete word at cursor position
+|
+|   Return Values :  E_OK               - success
+|                    E_REQUEST_DENIED   - failure
++--------------------------------------------------------------------------*/
+static int
+FE_Delete_Word(FORM *form)
+{
+  FIELD *field = form->current;
+  FIELD_CELL *bp = Address_Of_Current_Row_In_Buffer(form);
+  FIELD_CELL *ep = bp + field->dcols;
+  FIELD_CELL *cp = bp + form->curcol;
+  FIELD_CELL *s;
+
+  T((T_CALLED("FE_Delete_Word(%p)"), (void *)form));
+  Synchronize_Buffer(form);
+  if (ISBLANK(*cp))
+    returnCode(E_REQUEST_DENIED);	/* not in word */
+
+  /* move cursor to begin of word and erase to end of screen-line */
+  Adjust_Cursor_Position(form,
+			 After_Last_Whitespace_Character(bp, form->curcol));
+  wmove(form->w, form->currow, form->curcol);
+  wclrtoeol(form->w);
+
+  /* skip over word in buffer */
+  s = Get_First_Whitespace_Character(cp, (int)(ep - cp));
+  /* to begin of next word    */
+  s = Get_Start_Of_Data(s, (int)(ep - s));
+  if ((s != cp) && !ISBLANK(*s))
+    {
+      /* copy remaining line to window */
+      myADDNSTR(form->w, s, (int)(s - After_End_Of_Data(s, (int)(ep - s))));
+    }
+  returnCode(E_OK);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static int FE_Clear_To_End_Of_Line(FORM * form)
+|
+|   Description   :  Clear to end of current line.
+|
+|   Return Values :  E_OK   - success
++--------------------------------------------------------------------------*/
+static int
+FE_Clear_To_End_Of_Line(FORM *form)
+{
+  T((T_CALLED("FE_Clear_To_End_Of_Line(%p)"), (void *)form));
+  wmove(form->w, form->currow, form->curcol);
+  wclrtoeol(form->w);
+  returnCode(E_OK);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static int FE_Clear_To_End_Of_Field(FORM * form)
+|
+|   Description   :  Clear to end of field.
+|
+|   Return Values :  E_OK   - success
++--------------------------------------------------------------------------*/
+static int
+FE_Clear_To_End_Of_Field(FORM *form)
+{
+  T((T_CALLED("FE_Clear_To_End_Of_Field(%p)"), (void *)form));
+  wmove(form->w, form->currow, form->curcol);
+  wclrtobot(form->w);
+  returnCode(E_OK);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static int FE_Clear_Field(FORM * form)
+|
+|   Description   :  Clear entire field.
+|
+|   Return Values :  E_OK   - success
++--------------------------------------------------------------------------*/
+static int
+FE_Clear_Field(FORM *form)
+{
+  T((T_CALLED("FE_Clear_Field(%p)"), (void *)form));
+  form->currow = form->curcol = 0;
+  werase(form->w);
+  returnCode(E_OK);
+}
+/*----------------------------------------------------------------------------
+  END of Field Editing routines
+  --------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+  Edit Mode routines
+  --------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static int EM_Overlay_Mode(FORM * form)
+|
+|   Description   :  Switch to overlay mode.
+|
+|   Return Values :  E_OK   - success
++--------------------------------------------------------------------------*/
+static int
+EM_Overlay_Mode(FORM *form)
+{
+  T((T_CALLED("EM_Overlay_Mode(%p)"), (void *)form));
+  form->status |= _OVLMODE;
+  returnCode(E_OK);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static int EM_Insert_Mode(FORM * form)
+|
+|   Description   :  Switch to insert mode
+|
+|   Return Values :  E_OK   - success
++--------------------------------------------------------------------------*/
+static int
+EM_Insert_Mode(FORM *form)
+{
+  T((T_CALLED("EM_Insert_Mode(%p)"), (void *)form));
+  form->status &= ~_OVLMODE;
+  returnCode(E_OK);
+}
+
+/*----------------------------------------------------------------------------
+  END of Edit Mode routines
+  --------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+  Helper routines for Choice Requests
+  --------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static bool Next_Choice(FORM * form,
+|                                            FIELDTYPE * typ,
+|                                            FIELD * field,
+|                                            TypeArgument *argp)
+|
+|   Description   :  Get the next field choice. For linked types this is
+|                    done recursively.
+|
+|   Return Values :  TRUE    - next choice successfully retrieved
+|                    FALSE   - couldn't retrieve next choice
++--------------------------------------------------------------------------*/
+static bool
+Next_Choice(FORM *form, FIELDTYPE *typ, FIELD *field, TypeArgument *argp)
+{
+  if (!typ || !(typ->status & _HAS_CHOICE))
+    return FALSE;
+
+  if (typ->status & _LINKED_TYPE)
+    {
+      assert(argp);
+      return (
+	       Next_Choice(form, typ->left, field, argp->left) ||
+	       Next_Choice(form, typ->right, field, argp->right));
+    }
+  else
+    {
+#if NCURSES_INTEROP_FUNCS
+      assert(typ->enum_next.onext);
+      if (typ->status & _GENERIC)
+	return typ->enum_next.gnext(form, field, (void *)argp);
+      else
+	return typ->enum_next.onext(field, (void *)argp);
+#else
+      assert(typ->next);
+      return typ->next(field, (void *)argp);
+#endif
+    }
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static bool Previous_Choice(FORM * form,
+|                                                FIELDTYPE * typ,
+|                                                FIELD * field,
+|                                                TypeArgument *argp)
+|
+|   Description   :  Get the previous field choice. For linked types this
+|                    is done recursively.
+|
+|   Return Values :  TRUE    - previous choice successfully retrieved
+|                    FALSE   - couldn't retrieve previous choice
++--------------------------------------------------------------------------*/
+static bool
+Previous_Choice(FORM *form, FIELDTYPE *typ, FIELD *field, TypeArgument *argp)
+{
+  if (!typ || !(typ->status & _HAS_CHOICE))
+    return FALSE;
+
+  if (typ->status & _LINKED_TYPE)
+    {
+      assert(argp);
+      return (
+	       Previous_Choice(form, typ->left, field, argp->left) ||
+	       Previous_Choice(form, typ->right, field, argp->right));
+    }
+  else
+    {
+#if NCURSES_INTEROP_FUNCS
+      assert(typ->enum_prev.oprev);
+      if (typ->status & _GENERIC)
+	return typ->enum_prev.gprev(form, field, (void *)argp);
+      else
+	return typ->enum_prev.oprev(field, (void *)argp);
+#else
+      assert(typ->prev);
+      return typ->prev(field, (void *)argp);
+#endif
+    }
+}
+/*----------------------------------------------------------------------------
+  End of Helper routines for Choice Requests
+  --------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+  Routines for Choice Requests
+  --------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static int CR_Next_Choice(FORM * form)
+|
+|   Description   :  Get the next field choice.
+|
+|   Return Values :  E_OK              - success
+|                    E_REQUEST_DENIED  - next choice couldn't be retrieved
++--------------------------------------------------------------------------*/
+static int
+CR_Next_Choice(FORM *form)
+{
+  FIELD *field = form->current;
+
+  T((T_CALLED("CR_Next_Choice(%p)"), (void *)form));
+  Synchronize_Buffer(form);
+  returnCode((Next_Choice(form, field->type, field, (TypeArgument *)(field->arg)))
+	     ? E_OK
+	     : E_REQUEST_DENIED);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static int CR_Previous_Choice(FORM * form)
+|
+|   Description   :  Get the previous field choice.
+|
+|   Return Values :  E_OK              - success
+|                    E_REQUEST_DENIED  - prev. choice couldn't be retrieved
++--------------------------------------------------------------------------*/
+static int
+CR_Previous_Choice(FORM *form)
+{
+  FIELD *field = form->current;
+
+  T((T_CALLED("CR_Previous_Choice(%p)"), (void *)form));
+  Synchronize_Buffer(form);
+  returnCode((Previous_Choice(form, field->type, field, (TypeArgument *)(field->arg)))
+	     ? E_OK
+	     : E_REQUEST_DENIED);
+}
+/*----------------------------------------------------------------------------
+  End of Routines for Choice Requests
+  --------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+  Helper routines for Field Validations.
+  --------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static bool Check_Field(FORM* form,
+|                                            FIELDTYPE * typ,
+|                                            FIELD * field,
+|                                            TypeArgument * argp)
+|
+|   Description   :  Check the field according to its fieldtype and its
+|                    actual arguments. For linked fieldtypes this is done
+|                    recursively.
+|
+|   Return Values :  TRUE       - field is valid
+|                    FALSE      - field is invalid.
++--------------------------------------------------------------------------*/
+static bool
+Check_Field(FORM *form, FIELDTYPE *typ, FIELD *field, TypeArgument *argp)
+{
+  if (typ)
+    {
+      if (field->opts & O_NULLOK)
+	{
+	  FIELD_CELL *bp = field->buf;
+
+	  assert(bp);
+	  while (ISBLANK(*bp))
+	    {
+	      bp++;
+	    }
+	  if (CharOf(*bp) == 0)
+	    return TRUE;
+	}
+
+      if (typ->status & _LINKED_TYPE)
+	{
+	  assert(argp);
+	  return (
+		   Check_Field(form, typ->left, field, argp->left) ||
+		   Check_Field(form, typ->right, field, argp->right));
+	}
+      else
+	{
+#if NCURSES_INTEROP_FUNCS
+	  if (typ->fieldcheck.ofcheck)
+	    {
+	      if (typ->status & _GENERIC)
+		return typ->fieldcheck.gfcheck(form, field, (void *)argp);
+	      else
+		return typ->fieldcheck.ofcheck(field, (void *)argp);
+	    }
+#else
+	  if (typ->fcheck)
+	    return typ->fcheck(field, (void *)argp);
+#endif
+	}
+    }
+  return TRUE;
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  bool _nc_Internal_Validation(FORM * form )
+|
+|   Description   :  Validate the current field of the form.
+|
+|   Return Values :  TRUE  - field is valid
+|                    FALSE - field is invalid
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(bool)
+_nc_Internal_Validation(FORM *form)
+{
+  FIELD *field;
+
+  field = form->current;
+
+  Synchronize_Buffer(form);
+  if ((form->status & _FCHECK_REQUIRED) ||
+      (!(field->opts & O_PASSOK)))
+    {
+      if (!Check_Field(form, field->type, field, (TypeArgument *)(field->arg)))
+	return FALSE;
+      form->status &= ~_FCHECK_REQUIRED;
+      field->status |= _CHANGED;
+      Synchronize_Linked_Fields(field);
+    }
+  return TRUE;
+}
+/*----------------------------------------------------------------------------
+  End of Helper routines for Field Validations.
+  --------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+  Routines for Field Validation.
+  --------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static int FV_Validation(FORM * form)
+|
+|   Description   :  Validate the current field of the form.
+|
+|   Return Values :  E_OK             - field valid
+|                    E_INVALID_FIELD  - field not valid
++--------------------------------------------------------------------------*/
+static int
+FV_Validation(FORM *form)
+{
+  T((T_CALLED("FV_Validation(%p)"), (void *)form));
+  if (_nc_Internal_Validation(form))
+    returnCode(E_OK);
+  else
+    returnCode(E_INVALID_FIELD);
+}
+/*----------------------------------------------------------------------------
+  End of routines for Field Validation.
+  --------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+  Helper routines for Inter-Field Navigation
+  --------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static FIELD *Next_Field_On_Page(FIELD * field)
+|
+|   Description   :  Get the next field after the given field on the current
+|                    page. The order of fields is the one defined by the
+|                    fields array. Only visible and active fields are
+|                    counted.
+|
+|   Return Values :  Pointer to the next field.
++--------------------------------------------------------------------------*/
+NCURSES_INLINE static FIELD *
+Next_Field_On_Page(FIELD *field)
+{
+  FORM *form = field->form;
+  FIELD **field_on_page = &form->field[field->index];
+  FIELD **first_on_page = &form->field[form->page[form->curpage].pmin];
+  FIELD **last_on_page = &form->field[form->page[form->curpage].pmax];
+
+  do
+    {
+      field_on_page =
+	(field_on_page == last_on_page) ? first_on_page : field_on_page + 1;
+      if (Field_Is_Selectable(*field_on_page))
+	break;
+    }
+  while (field != (*field_on_page));
+  return (*field_on_page);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  FIELD* _nc_First_Active_Field(FORM * form)
+|
+|   Description   :  Get the first active field on the current page,
+|                    if there are such. If there are none, get the first
+|                    visible field on the page. If there are also none,
+|                    we return the first field on page and hope the best.
+|
+|   Return Values :  Pointer to calculated field.
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(FIELD *)
+_nc_First_Active_Field(FORM *form)
+{
+  FIELD **last_on_page = &form->field[form->page[form->curpage].pmax];
+  FIELD *proposed = Next_Field_On_Page(*last_on_page);
+
+  if (proposed == *last_on_page)
+    {
+      /* there might be the special situation, where there is no
+         active and visible field on the current page. We then select
+         the first visible field on this readonly page
+       */
+      if (Field_Is_Not_Selectable(proposed))
+	{
+	  FIELD **field = &form->field[proposed->index];
+	  FIELD **first = &form->field[form->page[form->curpage].pmin];
+
+	  do
+	    {
+	      field = (field == last_on_page) ? first : field + 1;
+	      if (((*field)->opts & O_VISIBLE))
+		break;
+	    }
+	  while (proposed != (*field));
+
+	  proposed = *field;
+
+	  if ((proposed == *last_on_page) && !(proposed->opts & O_VISIBLE))
+	    {
+	      /* This means, there is also no visible field on the page.
+	         So we propose the first one and hope the very best...
+	         Some very clever user has designed a readonly and invisible
+	         page on this form.
+	       */
+	      proposed = *first;
+	    }
+	}
+    }
+  return (proposed);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static FIELD *Previous_Field_On_Page(FIELD * field)
+|
+|   Description   :  Get the previous field before the given field on the
+|                    current page. The order of fields is the one defined by
+|                    the fields array. Only visible and active fields are
+|                    counted.
+|
+|   Return Values :  Pointer to the previous field.
++--------------------------------------------------------------------------*/
+NCURSES_INLINE static FIELD *
+Previous_Field_On_Page(FIELD *field)
+{
+  FORM *form = field->form;
+  FIELD **field_on_page = &form->field[field->index];
+  FIELD **first_on_page = &form->field[form->page[form->curpage].pmin];
+  FIELD **last_on_page = &form->field[form->page[form->curpage].pmax];
+
+  do
+    {
+      field_on_page =
+	(field_on_page == first_on_page) ? last_on_page : field_on_page - 1;
+      if (Field_Is_Selectable(*field_on_page))
+	break;
+    }
+  while (field != (*field_on_page));
+
+  return (*field_on_page);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static FIELD *Sorted_Next_Field(FIELD * field)
+|
+|   Description   :  Get the next field after the given field on the current
+|                    page. The order of fields is the one defined by the
+|                    (row,column) geometry, rows are major.
+|
+|   Return Values :  Pointer to the next field.
++--------------------------------------------------------------------------*/
+NCURSES_INLINE static FIELD *
+Sorted_Next_Field(FIELD *field)
+{
+  FIELD *field_on_page = field;
+
+  do
+    {
+      field_on_page = field_on_page->snext;
+      if (Field_Is_Selectable(field_on_page))
+	break;
+    }
+  while (field_on_page != field);
+
+  return (field_on_page);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static FIELD *Sorted_Previous_Field(FIELD * field)
+|
+|   Description   :  Get the previous field before the given field on the
+|                    current page. The order of fields is the one defined
+|                    by the (row,column) geometry, rows are major.
+|
+|   Return Values :  Pointer to the previous field.
++--------------------------------------------------------------------------*/
+NCURSES_INLINE static FIELD *
+Sorted_Previous_Field(FIELD *field)
+{
+  FIELD *field_on_page = field;
+
+  do
+    {
+      field_on_page = field_on_page->sprev;
+      if (Field_Is_Selectable(field_on_page))
+	break;
+    }
+  while (field_on_page != field);
+
+  return (field_on_page);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static FIELD *Left_Neighbor_Field(FIELD * field)
+|
+|   Description   :  Get the left neighbor of the field on the same line
+|                    and the same page. Cycles through the line.
+|
+|   Return Values :  Pointer to left neighbor field.
++--------------------------------------------------------------------------*/
+NCURSES_INLINE static FIELD *
+Left_Neighbor_Field(FIELD *field)
+{
+  FIELD *field_on_page = field;
+
+  /* For a field that has really a left neighbor, the while clause
+     immediately fails and the loop is left, positioned at the right
+     neighbor. Otherwise we cycle backwards through the sorted field list
+     until we enter the same line (from the right end).
+   */
+  do
+    {
+      field_on_page = Sorted_Previous_Field(field_on_page);
+    }
+  while (field_on_page->frow != field->frow);
+
+  return (field_on_page);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static FIELD *Right_Neighbor_Field(FIELD * field)
+|
+|   Description   :  Get the right neighbor of the field on the same line
+|                    and the same page.
+|
+|   Return Values :  Pointer to right neighbor field.
++--------------------------------------------------------------------------*/
+NCURSES_INLINE static FIELD *
+Right_Neighbor_Field(FIELD *field)
+{
+  FIELD *field_on_page = field;
+
+  /* See the comments on Left_Neighbor_Field to understand how it works */
+  do
+    {
+      field_on_page = Sorted_Next_Field(field_on_page);
+    }
+  while (field_on_page->frow != field->frow);
+
+  return (field_on_page);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static FIELD *Upper_Neighbor_Field(FIELD * field)
+|
+|   Description   :  Because of the row-major nature of sorting the fields,
+|                    it is more difficult to define whats the upper neighbor
+|                    field really means. We define that it must be on a
+|                    'previous' line (cyclic order!) and is the rightmost
+|                    field laying on the left side of the given field. If
+|                    this set is empty, we take the first field on the line.
+|
+|   Return Values :  Pointer to the upper neighbor field.
++--------------------------------------------------------------------------*/
+static FIELD *
+Upper_Neighbor_Field(FIELD *field)
+{
+  FIELD *field_on_page = field;
+  int frow = field->frow;
+  int fcol = field->fcol;
+
+  /* Walk back to the 'previous' line. The second term in the while clause
+     just guarantees that we stop if we cycled through the line because
+     there might be no 'previous' line if the page has just one line.
+   */
+  do
+    {
+      field_on_page = Sorted_Previous_Field(field_on_page);
+    }
+  while (field_on_page->frow == frow && field_on_page->fcol != fcol);
+
+  if (field_on_page->frow != frow)
+    {
+      /* We really found a 'previous' line. We are positioned at the
+         rightmost field on this line */
+      frow = field_on_page->frow;
+
+      /* We walk to the left as long as we are really right of the
+         field. */
+      while (field_on_page->frow == frow && field_on_page->fcol > fcol)
+	field_on_page = Sorted_Previous_Field(field_on_page);
+
+      /* If we wrapped, just go to the right which is the first field on
+         the row */
+      if (field_on_page->frow != frow)
+	field_on_page = Sorted_Next_Field(field_on_page);
+    }
+
+  return (field_on_page);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static FIELD *Down_Neighbor_Field(FIELD * field)
+|
+|   Description   :  Because of the row-major nature of sorting the fields,
+|                    its more difficult to define whats the down neighbor
+|                    field really means. We define that it must be on a
+|                    'next' line (cyclic order!) and is the leftmost
+|                    field laying on the right side of the given field. If
+|                    this set is empty, we take the last field on the line.
+|
+|   Return Values :  Pointer to the upper neighbor field.
++--------------------------------------------------------------------------*/
+static FIELD *
+Down_Neighbor_Field(FIELD *field)
+{
+  FIELD *field_on_page = field;
+  int frow = field->frow;
+  int fcol = field->fcol;
+
+  /* Walk forward to the 'next' line. The second term in the while clause
+     just guarantees that we stop if we cycled through the line because
+     there might be no 'next' line if the page has just one line.
+   */
+  do
+    {
+      field_on_page = Sorted_Next_Field(field_on_page);
+    }
+  while (field_on_page->frow == frow && field_on_page->fcol != fcol);
+
+  if (field_on_page->frow != frow)
+    {
+      /* We really found a 'next' line. We are positioned at the rightmost
+         field on this line */
+      frow = field_on_page->frow;
+
+      /* We walk to the right as long as we are really left of the
+         field. */
+      while (field_on_page->frow == frow && field_on_page->fcol < fcol)
+	field_on_page = Sorted_Next_Field(field_on_page);
+
+      /* If we wrapped, just go to the left which is the last field on
+         the row */
+      if (field_on_page->frow != frow)
+	field_on_page = Sorted_Previous_Field(field_on_page);
+    }
+
+  return (field_on_page);
+}
+
+/*----------------------------------------------------------------------------
+  Inter-Field Navigation routines
+  --------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static int Inter_Field_Navigation(
+|                                           int (* const fct) (FORM *),
+|                                           FORM * form)
+|
+|   Description   :  Generic behavior for changing the current field, the
+|                    field is left and a new field is entered. So the field
+|                    must be validated and the field init/term hooks must
+|                    be called.
+|
+|   Return Values :  E_OK                - success
+|                    E_INVALID_FIELD     - field is invalid
+|                    some other          - error from subordinate call
++--------------------------------------------------------------------------*/
+static int
+Inter_Field_Navigation(int (*const fct) (FORM *), FORM *form)
+{
+  int res;
+
+  if (!_nc_Internal_Validation(form))
+    res = E_INVALID_FIELD;
+  else
+    {
+      Call_Hook(form, fieldterm);
+      res = fct(form);
+      Call_Hook(form, fieldinit);
+    }
+  return res;
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static int FN_Next_Field(FORM * form)
+|
+|   Description   :  Move to the next field on the current page of the form
+|
+|   Return Values :  E_OK                 - success
+|                    != E_OK              - error from subordinate call
++--------------------------------------------------------------------------*/
+static int
+FN_Next_Field(FORM *form)
+{
+  T((T_CALLED("FN_Next_Field(%p)"), (void *)form));
+  returnCode(_nc_Set_Current_Field(form,
+				   Next_Field_On_Page(form->current)));
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static int FN_Previous_Field(FORM * form)
+|
+|   Description   :  Move to the previous field on the current page of the
+|                    form
+|
+|   Return Values :  E_OK                 - success
+|                    != E_OK              - error from subordinate call
++--------------------------------------------------------------------------*/
+static int
+FN_Previous_Field(FORM *form)
+{
+  T((T_CALLED("FN_Previous_Field(%p)"), (void *)form));
+  returnCode(_nc_Set_Current_Field(form,
+				   Previous_Field_On_Page(form->current)));
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static int FN_First_Field(FORM * form)
+|
+|   Description   :  Move to the first field on the current page of the form
+|
+|   Return Values :  E_OK                 - success
+|                    != E_OK              - error from subordinate call
++--------------------------------------------------------------------------*/
+static int
+FN_First_Field(FORM *form)
+{
+  T((T_CALLED("FN_First_Field(%p)"), (void *)form));
+  returnCode(_nc_Set_Current_Field(form,
+				   Next_Field_On_Page(form->field[form->page[form->curpage].pmax])));
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static int FN_Last_Field(FORM * form)
+|
+|   Description   :  Move to the last field on the current page of the form
+|
+|   Return Values :  E_OK                 - success
+|                    != E_OK              - error from subordinate call
++--------------------------------------------------------------------------*/
+static int
+FN_Last_Field(FORM *form)
+{
+  T((T_CALLED("FN_Last_Field(%p)"), (void *)form));
+  returnCode(
+	      _nc_Set_Current_Field(form,
+				    Previous_Field_On_Page(form->field[form->page[form->curpage].pmin])));
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static int FN_Sorted_Next_Field(FORM * form)
+|
+|   Description   :  Move to the sorted next field on the current page
+|                    of the form.
+|
+|   Return Values :  E_OK            - success
+|                    != E_OK         - error from subordinate call
++--------------------------------------------------------------------------*/
+static int
+FN_Sorted_Next_Field(FORM *form)
+{
+  T((T_CALLED("FN_Sorted_Next_Field(%p)"), (void *)form));
+  returnCode(_nc_Set_Current_Field(form,
+				   Sorted_Next_Field(form->current)));
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static int FN_Sorted_Previous_Field(FORM * form)
+|
+|   Description   :  Move to the sorted previous field on the current page
+|                    of the form.
+|
+|   Return Values :  E_OK            - success
+|                    != E_OK         - error from subordinate call
++--------------------------------------------------------------------------*/
+static int
+FN_Sorted_Previous_Field(FORM *form)
+{
+  T((T_CALLED("FN_Sorted_Previous_Field(%p)"), (void *)form));
+  returnCode(_nc_Set_Current_Field(form,
+				   Sorted_Previous_Field(form->current)));
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static int FN_Sorted_First_Field(FORM * form)
+|
+|   Description   :  Move to the sorted first field on the current page
+|                    of the form.
+|
+|   Return Values :  E_OK            - success
+|                    != E_OK         - error from subordinate call
++--------------------------------------------------------------------------*/
+static int
+FN_Sorted_First_Field(FORM *form)
+{
+  T((T_CALLED("FN_Sorted_First_Field(%p)"), (void *)form));
+  returnCode(_nc_Set_Current_Field(form,
+				   Sorted_Next_Field(form->field[form->page[form->curpage].smax])));
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static int FN_Sorted_Last_Field(FORM * form)
+|
+|   Description   :  Move to the sorted last field on the current page
+|                    of the form.
+|
+|   Return Values :  E_OK            - success
+|                    != E_OK         - error from subordinate call
++--------------------------------------------------------------------------*/
+static int
+FN_Sorted_Last_Field(FORM *form)
+{
+  T((T_CALLED("FN_Sorted_Last_Field(%p)"), (void *)form));
+  returnCode(_nc_Set_Current_Field(form,
+				   Sorted_Previous_Field(form->field[form->page[form->curpage].smin])));
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static int FN_Left_Field(FORM * form)
+|
+|   Description   :  Get the field on the left of the current field on the
+|                    same line and the same page. Cycles through the line.
+|
+|   Return Values :  E_OK            - success
+|                    != E_OK         - error from subordinate call
++--------------------------------------------------------------------------*/
+static int
+FN_Left_Field(FORM *form)
+{
+  T((T_CALLED("FN_Left_Field(%p)"), (void *)form));
+  returnCode(_nc_Set_Current_Field(form,
+				   Left_Neighbor_Field(form->current)));
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static int FN_Right_Field(FORM * form)
+|
+|   Description   :  Get the field on the right of the current field on the
+|                    same line and the same page. Cycles through the line.
+|
+|   Return Values :  E_OK            - success
+|                    != E_OK         - error from subordinate call
++--------------------------------------------------------------------------*/
+static int
+FN_Right_Field(FORM *form)
+{
+  T((T_CALLED("FN_Right_Field(%p)"), (void *)form));
+  returnCode(_nc_Set_Current_Field(form,
+				   Right_Neighbor_Field(form->current)));
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static int FN_Up_Field(FORM * form)
+|
+|   Description   :  Get the upper neighbor of the current field. This
+|                    cycles through the page. See the comments of the
+|                    Upper_Neighbor_Field function to understand how
+|                    'upper' is defined.
+|
+|   Return Values :  E_OK            - success
+|                    != E_OK         - error from subordinate call
++--------------------------------------------------------------------------*/
+static int
+FN_Up_Field(FORM *form)
+{
+  T((T_CALLED("FN_Up_Field(%p)"), (void *)form));
+  returnCode(_nc_Set_Current_Field(form,
+				   Upper_Neighbor_Field(form->current)));
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static int FN_Down_Field(FORM * form)
+|
+|   Description   :  Get the down neighbor of the current field. This
+|                    cycles through the page. See the comments of the
+|                    Down_Neighbor_Field function to understand how
+|                    'down' is defined.
+|
+|   Return Values :  E_OK            - success
+|                    != E_OK         - error from subordinate call
++--------------------------------------------------------------------------*/
+static int
+FN_Down_Field(FORM *form)
+{
+  T((T_CALLED("FN_Down_Field(%p)"), (void *)form));
+  returnCode(_nc_Set_Current_Field(form,
+				   Down_Neighbor_Field(form->current)));
+}
+/*----------------------------------------------------------------------------
+  END of Field Navigation routines
+  --------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+  Helper routines for Page Navigation
+  --------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  int _nc_Set_Form_Page(FORM * form,
+|                                          int page,
+|                                          FIELD * field)
+|
+|   Description   :  Make the given page number the current page and make
+|                    the given field the current field on the page. If
+|                    for the field NULL is given, make the first field on
+|                    the page the current field. The routine acts only
+|                    if the requested page is not the current page.
+|
+|   Return Values :  E_OK                - success
+|                    != E_OK             - error from subordinate call
+|                    E_BAD_ARGUMENT      - invalid field pointer
+|                    E_SYSTEM_ERROR      - some severe basic error
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(int)
+_nc_Set_Form_Page(FORM *form, int page, FIELD *field)
+{
+  int res = E_OK;
+
+  if ((form->curpage != page))
+    {
+      FIELD *last_field, *field_on_page;
+
+      werase(Get_Form_Window(form));
+      form->curpage = page;
+      last_field = field_on_page = form->field[form->page[page].smin];
+      do
+	{
+	  if (field_on_page->opts & O_VISIBLE)
+	    if ((res = Display_Field(field_on_page)) != E_OK)
+	      return (res);
+	  field_on_page = field_on_page->snext;
+	}
+      while (field_on_page != last_field);
+
+      if (field)
+	res = _nc_Set_Current_Field(form, field);
+      else
+	/* N.B.: we don't encapsulate this by Inter_Field_Navigation(),
+	   because this is already executed in a page navigation
+	   context that contains field navigation
+	 */
+	res = FN_First_Field(form);
+    }
+  return (res);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static int Next_Page_Number(const FORM * form)
+|
+|   Description   :  Calculate the page number following the current page
+|                    number. This cycles if the highest page number is
+|                    reached.
+|
+|   Return Values :  The next page number
++--------------------------------------------------------------------------*/
+NCURSES_INLINE static int
+Next_Page_Number(const FORM *form)
+{
+  return (form->curpage + 1) % form->maxpage;
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static int Previous_Page_Number(const FORM * form)
+|
+|   Description   :  Calculate the page number before the current page
+|                    number. This cycles if the first page number is
+|                    reached.
+|
+|   Return Values :  The previous page number
++--------------------------------------------------------------------------*/
+NCURSES_INLINE static int
+Previous_Page_Number(const FORM *form)
+{
+  return (form->curpage != 0 ? form->curpage - 1 : form->maxpage - 1);
+}
+
+/*----------------------------------------------------------------------------
+  Page Navigation routines
+  --------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static int Page_Navigation(
+|                                               int (* const fct) (FORM *),
+|                                               FORM * form)
+|
+|   Description   :  Generic behavior for changing a page. This means
+|                    that the field is left and a new field is entered.
+|                    So the field must be validated and the field init/term
+|                    hooks must be called. Because also the page is changed,
+|                    the forms init/term hooks must be called also.
+|
+|   Return Values :  E_OK                - success
+|                    E_INVALID_FIELD     - field is invalid
+|                    some other          - error from subordinate call
++--------------------------------------------------------------------------*/
+static int
+Page_Navigation(int (*const fct) (FORM *), FORM *form)
+{
+  int res;
+
+  if (!_nc_Internal_Validation(form))
+    res = E_INVALID_FIELD;
+  else
+    {
+      Call_Hook(form, fieldterm);
+      Call_Hook(form, formterm);
+      res = fct(form);
+      Call_Hook(form, forminit);
+      Call_Hook(form, fieldinit);
+    }
+  return res;
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static int PN_Next_Page(FORM * form)
+|
+|   Description   :  Move to the next page of the form
+|
+|   Return Values :  E_OK                - success
+|                    != E_OK             - error from subordinate call
++--------------------------------------------------------------------------*/
+static int
+PN_Next_Page(FORM *form)
+{
+  T((T_CALLED("PN_Next_Page(%p)"), (void *)form));
+  returnCode(_nc_Set_Form_Page(form, Next_Page_Number(form), (FIELD *)0));
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static int PN_Previous_Page(FORM * form)
+|
+|   Description   :  Move to the previous page of the form
+|
+|   Return Values :  E_OK              - success
+|                    != E_OK           - error from subordinate call
++--------------------------------------------------------------------------*/
+static int
+PN_Previous_Page(FORM *form)
+{
+  T((T_CALLED("PN_Previous_Page(%p)"), (void *)form));
+  returnCode(_nc_Set_Form_Page(form, Previous_Page_Number(form), (FIELD *)0));
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static int PN_First_Page(FORM * form)
+|
+|   Description   :  Move to the first page of the form
+|
+|   Return Values :  E_OK              - success
+|                    != E_OK           - error from subordinate call
++--------------------------------------------------------------------------*/
+static int
+PN_First_Page(FORM *form)
+{
+  T((T_CALLED("PN_First_Page(%p)"), (void *)form));
+  returnCode(_nc_Set_Form_Page(form, 0, (FIELD *)0));
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static int PN_Last_Page(FORM * form)
+|
+|   Description   :  Move to the last page of the form
+|
+|   Return Values :  E_OK              - success
+|                    != E_OK           - error from subordinate call
++--------------------------------------------------------------------------*/
+static int
+PN_Last_Page(FORM *form)
+{
+  T((T_CALLED("PN_Last_Page(%p)"), (void *)form));
+  returnCode(_nc_Set_Form_Page(form, form->maxpage - 1, (FIELD *)0));
+}
+
+/*----------------------------------------------------------------------------
+  END of Field Navigation routines
+  --------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+  Helper routines for the core form driver.
+  --------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static int Data_Entry(FORM * form,int c)
+|
+|   Description   :  Enter character c into at the current position of the
+|                    current field of the form.
+|
+|   Return Values :  E_OK              - success
+|                    E_REQUEST_DENIED  - driver could not process the request
+|                    E_SYSTEM_ERROR    -
++--------------------------------------------------------------------------*/
+static int
+Data_Entry(FORM *form, int c)
+{
+  FIELD *field = form->current;
+  int result = E_REQUEST_DENIED;
+
+  T((T_CALLED("Data_Entry(%p,%s)"), (void *)form, _tracechtype((chtype)c)));
+  if ((field->opts & O_EDIT)
+#if FIX_FORM_INACTIVE_BUG
+      && (field->opts & O_ACTIVE)
+#endif
+    )
+    {
+      if ((field->opts & O_BLANK) &&
+	  First_Position_In_Current_Field(form) &&
+	  !(form->status & _FCHECK_REQUIRED) &&
+	  !(form->status & _WINDOW_MODIFIED))
+	werase(form->w);
+
+      if (form->status & _OVLMODE)
+	{
+	  waddch(form->w, (chtype)c);
+	}
+      else
+	/* no _OVLMODE */
+	{
+	  bool There_Is_Room = Is_There_Room_For_A_Char_In_Line(form);
+
+	  if (!(There_Is_Room ||
+		((Single_Line_Field(field) && Growable(field)))))
+	    RETURN(E_REQUEST_DENIED);
+
+	  if (!There_Is_Room && !Field_Grown(field, 1))
+	    RETURN(E_SYSTEM_ERROR);
+
+	  winsch(form->w, (chtype)c);
+	}
+
+      if ((result = Wrapping_Not_Necessary_Or_Wrapping_Ok(form)) == E_OK)
+	{
+	  bool End_Of_Field = (((field->drows - 1) == form->currow) &&
+			       ((field->dcols - 1) == form->curcol));
+
+	  form->status |= _WINDOW_MODIFIED;
+	  if (End_Of_Field && !Growable(field) && (field->opts & O_AUTOSKIP))
+	    result = Inter_Field_Navigation(FN_Next_Field, form);
+	  else
+	    {
+	      if (End_Of_Field && Growable(field) && !Field_Grown(field, 1))
+		result = E_SYSTEM_ERROR;
+	      else
+		{
+#if USE_WIDEC_SUPPORT
+		  /*
+		   * We have just added a byte to the form field.  It may have
+		   * been part of a multibyte character.  If it was, the
+		   * addch_used field is nonzero and we should not try to move
+		   * to a new column.
+		   */
+		  if (WINDOW_EXT(form->w, addch_used) == 0)
+		    IFN_Next_Character(form);
+#else
+		  IFN_Next_Character(form);
+#endif
+		  result = E_OK;
+		}
+	    }
+	}
+    }
+  RETURN(result);
+}
+
+/* Structure to describe the binding of a request code to a function.
+   The member keycode codes the request value as well as the generic
+   routine to use for the request. The code for the generic routine
+   is coded in the upper 16 Bits while the request code is coded in
+   the lower 16 bits.
+
+   In terms of C++ you might think of a request as a class with a
+   virtual method "perform". The different types of request are
+   derived from this base class and overload (or not) the base class
+   implementation of perform.
+*/
+typedef struct
+{
+  int keycode;			/* must be at least 32 bit: hi:mode, lo: key */
+  int (*cmd) (FORM *);		/* low level driver routine for this key     */
+}
+Binding_Info;
+
+/* You may see this is the class-id of the request type class */
+#define ID_PN    (0x00000000)	/* Page navigation           */
+#define ID_FN    (0x00010000)	/* Inter-Field navigation    */
+#define ID_IFN   (0x00020000)	/* Intra-Field navigation    */
+#define ID_VSC   (0x00030000)	/* Vertical Scrolling        */
+#define ID_HSC   (0x00040000)	/* Horizontal Scrolling      */
+#define ID_FE    (0x00050000)	/* Field Editing             */
+#define ID_EM    (0x00060000)	/* Edit Mode                 */
+#define ID_FV    (0x00070000)	/* Field Validation          */
+#define ID_CH    (0x00080000)	/* Choice                    */
+#define ID_Mask  (0xffff0000)
+#define Key_Mask (0x0000ffff)
+#define ID_Shft  (16)
+
+/* This array holds all the Binding Infos */
+/* *INDENT-OFF* */
+static const Binding_Info bindings[MAX_FORM_COMMAND - MIN_FORM_COMMAND + 1] =
+{
+  { REQ_NEXT_PAGE    |ID_PN  ,PN_Next_Page},
+  { REQ_PREV_PAGE    |ID_PN  ,PN_Previous_Page},
+  { REQ_FIRST_PAGE   |ID_PN  ,PN_First_Page},
+  { REQ_LAST_PAGE    |ID_PN  ,PN_Last_Page},
+
+  { REQ_NEXT_FIELD   |ID_FN  ,FN_Next_Field},
+  { REQ_PREV_FIELD   |ID_FN  ,FN_Previous_Field},
+  { REQ_FIRST_FIELD  |ID_FN  ,FN_First_Field},
+  { REQ_LAST_FIELD   |ID_FN  ,FN_Last_Field},
+  { REQ_SNEXT_FIELD  |ID_FN  ,FN_Sorted_Next_Field},
+  { REQ_SPREV_FIELD  |ID_FN  ,FN_Sorted_Previous_Field},
+  { REQ_SFIRST_FIELD |ID_FN  ,FN_Sorted_First_Field},
+  { REQ_SLAST_FIELD  |ID_FN  ,FN_Sorted_Last_Field},
+  { REQ_LEFT_FIELD   |ID_FN  ,FN_Left_Field},
+  { REQ_RIGHT_FIELD  |ID_FN  ,FN_Right_Field},
+  { REQ_UP_FIELD     |ID_FN  ,FN_Up_Field},
+  { REQ_DOWN_FIELD   |ID_FN  ,FN_Down_Field},
+
+  { REQ_NEXT_CHAR    |ID_IFN ,IFN_Next_Character},
+  { REQ_PREV_CHAR    |ID_IFN ,IFN_Previous_Character},
+  { REQ_NEXT_LINE    |ID_IFN ,IFN_Next_Line},
+  { REQ_PREV_LINE    |ID_IFN ,IFN_Previous_Line},
+  { REQ_NEXT_WORD    |ID_IFN ,IFN_Next_Word},
+  { REQ_PREV_WORD    |ID_IFN ,IFN_Previous_Word},
+  { REQ_BEG_FIELD    |ID_IFN ,IFN_Beginning_Of_Field},
+  { REQ_END_FIELD    |ID_IFN ,IFN_End_Of_Field},
+  { REQ_BEG_LINE     |ID_IFN ,IFN_Beginning_Of_Line},
+  { REQ_END_LINE     |ID_IFN ,IFN_End_Of_Line},
+  { REQ_LEFT_CHAR    |ID_IFN ,IFN_Left_Character},
+  { REQ_RIGHT_CHAR   |ID_IFN ,IFN_Right_Character},
+  { REQ_UP_CHAR      |ID_IFN ,IFN_Up_Character},
+  { REQ_DOWN_CHAR    |ID_IFN ,IFN_Down_Character},
+
+  { REQ_NEW_LINE     |ID_FE  ,FE_New_Line},
+  { REQ_INS_CHAR     |ID_FE  ,FE_Insert_Character},
+  { REQ_INS_LINE     |ID_FE  ,FE_Insert_Line},
+  { REQ_DEL_CHAR     |ID_FE  ,FE_Delete_Character},
+  { REQ_DEL_PREV     |ID_FE  ,FE_Delete_Previous},
+  { REQ_DEL_LINE     |ID_FE  ,FE_Delete_Line},
+  { REQ_DEL_WORD     |ID_FE  ,FE_Delete_Word},
+  { REQ_CLR_EOL      |ID_FE  ,FE_Clear_To_End_Of_Line},
+  { REQ_CLR_EOF      |ID_FE  ,FE_Clear_To_End_Of_Field},
+  { REQ_CLR_FIELD    |ID_FE  ,FE_Clear_Field},
+
+  { REQ_OVL_MODE     |ID_EM  ,EM_Overlay_Mode},
+  { REQ_INS_MODE     |ID_EM  ,EM_Insert_Mode},
+
+  { REQ_SCR_FLINE    |ID_VSC ,VSC_Scroll_Line_Forward},
+  { REQ_SCR_BLINE    |ID_VSC ,VSC_Scroll_Line_Backward},
+  { REQ_SCR_FPAGE    |ID_VSC ,VSC_Scroll_Page_Forward},
+  { REQ_SCR_BPAGE    |ID_VSC ,VSC_Scroll_Page_Backward},
+  { REQ_SCR_FHPAGE   |ID_VSC ,VSC_Scroll_Half_Page_Forward},
+  { REQ_SCR_BHPAGE   |ID_VSC ,VSC_Scroll_Half_Page_Backward},
+
+  { REQ_SCR_FCHAR    |ID_HSC ,HSC_Scroll_Char_Forward},
+  { REQ_SCR_BCHAR    |ID_HSC ,HSC_Scroll_Char_Backward},
+  { REQ_SCR_HFLINE   |ID_HSC ,HSC_Horizontal_Line_Forward},
+  { REQ_SCR_HBLINE   |ID_HSC ,HSC_Horizontal_Line_Backward},
+  { REQ_SCR_HFHALF   |ID_HSC ,HSC_Horizontal_Half_Line_Forward},
+  { REQ_SCR_HBHALF   |ID_HSC ,HSC_Horizontal_Half_Line_Backward},
+
+  { REQ_VALIDATION   |ID_FV  ,FV_Validation},
+
+  { REQ_NEXT_CHOICE  |ID_CH  ,CR_Next_Choice},
+  { REQ_PREV_CHOICE  |ID_CH  ,CR_Previous_Choice}
+};
+/* *INDENT-ON* */
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  int form_driver(FORM * form,int  c)
+|
+|   Description   :  This is the workhorse of the forms system. It checks
+|                    to determine whether the character c is a request or
+|                    data. If it is a request, the form driver executes
+|                    the request and returns the result. If it is data
+|                    (printable character), it enters the data into the
+|                    current position in the current field. If it is not
+|                    recognized, the form driver assumes it is an application
+|                    defined command and returns E_UNKNOWN_COMMAND.
+|                    Application defined command should be defined relative
+|                    to MAX_FORM_COMMAND, the maximum value of a request.
+|
+|   Return Values :  E_OK              - success
+|                    E_SYSTEM_ERROR    - system error
+|                    E_BAD_ARGUMENT    - an argument is incorrect
+|                    E_NOT_POSTED      - form is not posted
+|                    E_INVALID_FIELD   - field contents are invalid
+|                    E_BAD_STATE       - called from inside a hook routine
+|                    E_REQUEST_DENIED  - request failed
+|                    E_NOT_CONNECTED   - no fields are connected to the form
+|                    E_UNKNOWN_COMMAND - command not known
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(int)
+form_driver(FORM *form, int c)
+{
+  const Binding_Info *BI = (Binding_Info *) 0;
+  int res = E_UNKNOWN_COMMAND;
+
+  T((T_CALLED("form_driver(%p,%d)"), (void *)form, c));
+
+  if (!form)
+    RETURN(E_BAD_ARGUMENT);
+
+  if (!(form->field))
+    RETURN(E_NOT_CONNECTED);
+
+  assert(form->page);
+
+  if (c == FIRST_ACTIVE_MAGIC)
+    {
+      form->current = _nc_First_Active_Field(form);
+      RETURN(E_OK);
+    }
+
+  assert(form->current &&
+	 form->current->buf &&
+	 (form->current->form == form)
+    );
+
+  if (form->status & _IN_DRIVER)
+    RETURN(E_BAD_STATE);
+
+  if (!(form->status & _POSTED))
+    RETURN(E_NOT_POSTED);
+
+  if ((c >= MIN_FORM_COMMAND && c <= MAX_FORM_COMMAND) &&
+      ((bindings[c - MIN_FORM_COMMAND].keycode & Key_Mask) == c))
+    BI = &(bindings[c - MIN_FORM_COMMAND]);
+
+  if (BI)
+    {
+      typedef int (*Generic_Method) (int (*const) (FORM *), FORM *);
+      static const Generic_Method Generic_Methods[] =
+      {
+	Page_Navigation,	/* overloaded to call field&form hooks */
+	Inter_Field_Navigation,	/* overloaded to call field hooks      */
+	NULL,			/* Intra-Field is generic              */
+	Vertical_Scrolling,	/* Overloaded to check multi-line      */
+	Horizontal_Scrolling,	/* Overloaded to check single-line     */
+	Field_Editing,		/* Overloaded to mark modification     */
+	NULL,			/* Edit Mode is generic                */
+	NULL,			/* Field Validation is generic         */
+	NULL			/* Choice Request is generic           */
+      };
+      size_t nMethods = (sizeof(Generic_Methods) / sizeof(Generic_Methods[0]));
+      size_t method = (BI->keycode >> ID_Shft) & 0xffff;	/* see ID_Mask */
+
+      if ((method >= nMethods) || !(BI->cmd))
+	res = E_SYSTEM_ERROR;
+      else
+	{
+	  Generic_Method fct = Generic_Methods[method];
+
+	  if (fct)
+	    res = fct(BI->cmd, form);
+	  else
+	    res = (BI->cmd) (form);
+	}
+    }
+#ifdef NCURSES_MOUSE_VERSION
+  else if (KEY_MOUSE == c)
+    {
+      MEVENT event;
+      WINDOW *win = form->win ? form->win : StdScreen(Get_Form_Screen(form));
+      WINDOW *sub = form->sub ? form->sub : win;
+
+      getmouse(&event);
+      if ((event.bstate & (BUTTON1_CLICKED |
+			   BUTTON1_DOUBLE_CLICKED |
+			   BUTTON1_TRIPLE_CLICKED))
+	  && wenclose(win, event.y, event.x))
+	{			/* we react only if the click was in the userwin, that means
+				 * inside the form display area or at the decoration window.
+				 */
+	  int ry = event.y, rx = event.x;	/* screen coordinates */
+
+	  res = E_REQUEST_DENIED;
+	  if (mouse_trafo(&ry, &rx, FALSE))
+	    {			/* rx, ry are now "curses" coordinates */
+	      if (ry < sub->_begy)
+		{		/* we clicked above the display region; this is
+				 * interpreted as "scroll up" request
+				 */
+		  if (event.bstate & BUTTON1_CLICKED)
+		    res = form_driver(form, REQ_PREV_FIELD);
+		  else if (event.bstate & BUTTON1_DOUBLE_CLICKED)
+		    res = form_driver(form, REQ_PREV_PAGE);
+		  else if (event.bstate & BUTTON1_TRIPLE_CLICKED)
+		    res = form_driver(form, REQ_FIRST_FIELD);
+		}
+	      else if (ry > sub->_begy + sub->_maxy)
+		{		/* we clicked below the display region; this is
+				 * interpreted as "scroll down" request
+				 */
+		  if (event.bstate & BUTTON1_CLICKED)
+		    res = form_driver(form, REQ_NEXT_FIELD);
+		  else if (event.bstate & BUTTON1_DOUBLE_CLICKED)
+		    res = form_driver(form, REQ_NEXT_PAGE);
+		  else if (event.bstate & BUTTON1_TRIPLE_CLICKED)
+		    res = form_driver(form, REQ_LAST_FIELD);
+		}
+	      else if (wenclose(sub, event.y, event.x))
+		{		/* Inside the area we try to find the hit item */
+		  int i;
+
+		  ry = event.y;
+		  rx = event.x;
+		  if (wmouse_trafo(sub, &ry, &rx, FALSE))
+		    {
+		      int min_field = form->page[form->curpage].pmin;
+		      int max_field = form->page[form->curpage].pmax;
+
+		      for (i = min_field; i <= max_field; ++i)
+			{
+			  FIELD *field = form->field[i];
+
+			  if (Field_Is_Selectable(field)
+			      && Field_encloses(field, ry, rx) == E_OK)
+			    {
+			      res = _nc_Set_Current_Field(form, field);
+			      if (res == E_OK)
+				res = _nc_Position_Form_Cursor(form);
+			      if (res == E_OK
+				  && (event.bstate & BUTTON1_DOUBLE_CLICKED))
+				res = E_UNKNOWN_COMMAND;
+			      break;
+			    }
+			}
+		    }
+		}
+	    }
+	}
+      else
+	res = E_REQUEST_DENIED;
+    }
+#endif /* NCURSES_MOUSE_VERSION */
+  else if (!(c & (~(int)MAX_REGULAR_CHARACTER)))
+    {
+      /*
+       * If we're using 8-bit characters, iscntrl+isprint cover the whole set.
+       * But with multibyte characters, there is a third possibility, i.e.,
+       * parts of characters that build up into printable characters which are
+       * not considered printable.
+       *
+       * FIXME: the wide-character branch should also use Check_Char().
+       */
+#if USE_WIDEC_SUPPORT
+      if (!iscntrl(UChar(c)))
+#else
+      if (isprint(UChar(c)) &&
+	  Check_Char(form, form->current, form->current->type, c,
+		     (TypeArgument *)(form->current->arg)))
+#endif
+	res = Data_Entry(form, c);
+    }
+  _nc_Refresh_Current_Field(form);
+  RETURN(res);
+}
+
+/*----------------------------------------------------------------------------
+  Field-Buffer manipulation routines.
+  The effects of setting a buffer are tightly coupled to the core of the form
+  driver logic. This is especially true in the case of growable fields.
+  So I don't separate this into a separate module.
+  --------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  int set_field_buffer(FIELD *field,
+|                                         int buffer, char *value)
+|
+|   Description   :  Set the given buffer of the field to the given value.
+|                    Buffer 0 stores the displayed content of the field.
+|                    For dynamic fields this may grow the fieldbuffers if
+|                    the length of the value exceeds the current buffer
+|                    length. For buffer 0 only printable values are allowed.
+|                    For static fields, the value needs not to be zero ter-
+|                    minated. It is copied up to the length of the buffer.
+|
+|   Return Values :  E_OK            - success
+|                    E_BAD_ARGUMENT  - invalid argument
+|                    E_SYSTEM_ERROR  - system error
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(int)
+set_field_buffer(FIELD *field, int buffer, const char *value)
+{
+  FIELD_CELL *p;
+  int res = E_OK;
+  unsigned int i;
+  unsigned int len;
+
+#if USE_WIDEC_SUPPORT
+  FIELD_CELL *widevalue = 0;
+#endif
+
+  T((T_CALLED("set_field_buffer(%p,%d,%s)"), (void *)field, buffer, _nc_visbuf(value)));
+
+  if (!field || !value || ((buffer < 0) || (buffer > field->nbuf)))
+    RETURN(E_BAD_ARGUMENT);
+
+  len = Buffer_Length(field);
+
+  if (Growable(field))
+    {
+      /* for a growable field we must assume zero terminated strings, because
+         somehow we have to detect the length of what should be copied.
+       */
+      unsigned int vlen = strlen(value);
+
+      if (vlen > len)
+	{
+	  if (!Field_Grown(field,
+			   (int)(1 + (vlen - len) / ((field->rows + field->nrow)
+						     * field->cols))))
+	    RETURN(E_SYSTEM_ERROR);
+
+#if !USE_WIDEC_SUPPORT
+	  len = vlen;
+#endif
+	}
+    }
+
+  p = Address_Of_Nth_Buffer(field, buffer);
+
+#if USE_WIDEC_SUPPORT
+  /*
+   * Use addstr's logic for converting a string to an array of cchar_t's.
+   * There should be a better way, but this handles nonspacing characters
+   * and other special cases that we really do not want to handle here.
+   */
+#if NCURSES_EXT_FUNCS
+  if (wresize(field->working, 1, Buffer_Length(field) + 1) == ERR)
+#endif
+    {
+      delwin(field->working);
+      field->working = newpad(1, Buffer_Length(field) + 1);
+    }
+  len = Buffer_Length(field);
+  wclear(field->working);
+  (void)mvwaddstr(field->working, 0, 0, value);
+
+  if ((widevalue = typeCalloc(FIELD_CELL, len + 1)) == 0)
+    {
+      RETURN(E_SYSTEM_ERROR);
+    }
+  else
+    {
+      for (i = 0; i < (unsigned)field->drows; ++i)
+	{
+	  (void)mvwin_wchnstr(field->working, 0, i * field->dcols,
+			      widevalue + (i * field->dcols),
+			      field->dcols);
+	}
+      for (i = 0; i < len; ++i)
+	{
+	  if (CharEq(myZEROS, widevalue[i]))
+	    {
+	      while (i < len)
+		p[i++] = myBLANK;
+	      break;
+	    }
+	  p[i] = widevalue[i];
+	}
+      free(widevalue);
+    }
+#else
+  for (i = 0; i < len; ++i)
+    {
+      if (value[i] == '\0')
+	{
+	  while (i < len)
+	    p[i++] = myBLANK;
+	  break;
+	}
+      p[i] = value[i];
+    }
+#endif
+
+  if (buffer == 0)
+    {
+      int syncres;
+
+      if (((syncres = Synchronize_Field(field)) != E_OK) &&
+	  (res == E_OK))
+	res = syncres;
+      if (((syncres = Synchronize_Linked_Fields(field)) != E_OK) &&
+	  (res == E_OK))
+	res = syncres;
+    }
+  RETURN(res);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  char *field_buffer(const FIELD *field,int buffer)
+|
+|   Description   :  Return the address of the buffer for the field.
+|
+|   Return Values :  Pointer to buffer or NULL if arguments were invalid.
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(char *)
+field_buffer(const FIELD *field, int buffer)
+{
+  char *result = 0;
+
+  T((T_CALLED("field_buffer(%p,%d)"), (const void *)field, buffer));
+
+  if (field && (buffer >= 0) && (buffer <= field->nbuf))
+    {
+#if USE_WIDEC_SUPPORT
+      FIELD_CELL *data = Address_Of_Nth_Buffer(field, buffer);
+      unsigned need = 0;
+      int size = Buffer_Length(field);
+      int n;
+
+      /* determine the number of bytes needed to store the expanded string */
+      for (n = 0; n < size; ++n)
+	{
+	  if (!isWidecExt(data[n]) && data[n].chars[0] != L'\0')
+	    {
+	      mbstate_t state;
+	      size_t next;
+
+	      init_mb(state);
+	      next = _nc_wcrtomb(0, data[n].chars[0], &state);
+	      if (!isEILSEQ(next))
+		need += next;
+	    }
+	}
+
+      /* allocate a place to store the expanded string */
+      if (field->expanded[buffer] != 0)
+	free(field->expanded[buffer]);
+      field->expanded[buffer] = typeMalloc(char, need + 1);
+
+      /*
+       * Expand the multibyte data.
+       *
+       * It may also be multi-column data.  In that case, the data for a row
+       * may be null-padded to align to the dcols/drows layout (or it may
+       * contain embedded wide-character extensions).  Change the null-padding
+       * to blanks as needed.
+       */
+      if ((result = field->expanded[buffer]) != 0)
+	{
+	  wclear(field->working);
+	  wmove(field->working, 0, 0);
+	  for (n = 0; n < size; ++n)
+	    {
+	      if (!isWidecExt(data[n]) && data[n].chars[0] != L'\0')
+		wadd_wch(field->working, &data[n]);
+	    }
+	  wmove(field->working, 0, 0);
+	  winnstr(field->working, result, (int)need);
+	}
+#else
+      result = Address_Of_Nth_Buffer(field, buffer);
+#endif
+    }
+  returnPtr(result);
+}
+
+#if USE_WIDEC_SUPPORT
+
+/*---------------------------------------------------------------------------
+| Convert a multibyte string to a wide-character string.  The result must be
+| freed by the caller.
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(wchar_t *)
+_nc_Widen_String(char *source, int *lengthp)
+{
+  wchar_t *result = 0;
+  wchar_t wch;
+  size_t given = strlen(source);
+  size_t tries;
+  int pass;
+  int status;
+
+#ifndef state_unused
+  mbstate_t state;
+#endif
+
+  for (pass = 0; pass < 2; ++pass)
+    {
+      unsigned need = 0;
+      size_t passed = 0;
+
+      while (passed < given)
+	{
+	  bool found = FALSE;
+
+	  for (tries = 1, status = 0; tries <= (given - passed); ++tries)
+	    {
+	      int save = source[passed + tries];
+
+	      source[passed + tries] = 0;
+	      reset_mbytes(state);
+	      status = check_mbytes(wch, source + passed, tries, state);
+	      source[passed + tries] = (char)save;
+
+	      if (status > 0)
+		{
+		  found = TRUE;
+		  break;
+		}
+	    }
+	  if (found)
+	    {
+	      if (pass)
+		{
+		  result[need] = wch;
+		}
+	      passed += status;
+	      ++need;
+	    }
+	  else
+	    {
+	      if (pass)
+		{
+		  result[need] = source[passed];
+		}
+	      ++need;
+	      ++passed;
+	    }
+	}
+
+      if (!pass)
+	{
+	  if (!need)
+	    break;
+	  result = typeCalloc(wchar_t, need);
+
+	  *lengthp = need;
+	  if (result == 0)
+	    break;
+	}
+    }
+
+  return result;
+}
+#endif
+
+/* frm_driver.c ends here */
diff --git a/apps/lib/curses/pdcurses/form/frm_hook.c b/apps/lib/curses/pdcurses/form/frm_hook.c
new file mode 100644
index 0000000..7daa396
--- /dev/null
+++ b/apps/lib/curses/pdcurses/form/frm_hook.c
@@ -0,0 +1,142 @@
+/****************************************************************************
+ * Copyright (c) 1998-2004,2010 Free Software Foundation, Inc.              *
+ *                                                                          *
+ * 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, distribute with modifications, sublicense, and/or sell       *
+ * copies of the Software, and to permit persons to whom the Software is    *
+ * furnished to do so, subject to the following conditions:                 *
+ *                                                                          *
+ * The above copyright notice and this permission notice shall be included  *
+ * in all copies or substantial portions of the Software.                   *
+ *                                                                          *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
+ * IN NO EVENT SHALL THE ABOVE 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.                               *
+ *                                                                          *
+ * Except as contained in this notice, the name(s) of the above copyright   *
+ * holders shall not be used in advertising or otherwise to promote the     *
+ * sale, use or other dealings in this Software without prior written       *
+ * authorization.                                                           *
+ ****************************************************************************/
+
+/****************************************************************************
+ *   Author:  Juergen Pfeifer, 1995,1997                                    *
+ ****************************************************************************/
+
+#include "form.priv.h"
+
+MODULE_ID("$Id: frm_hook.c,v 1.15 2010/01/23 21:12:08 tom Exp $")
+
+/* "Template" macro to generate function to set application specific hook */
+#define GEN_HOOK_SET_FUNCTION( typ, name ) \
+NCURSES_IMPEXP int NCURSES_API set_ ## typ ## _ ## name (FORM *form, Form_Hook func)\
+{\
+   T((T_CALLED("set_" #typ"_"#name"(%p,%p)"), form, func));\
+   (Normalize_Form( form ) -> typ ## name) = func ;\
+   RETURN(E_OK);\
+}
+
+/* "Template" macro to generate function to get application specific hook */
+#define GEN_HOOK_GET_FUNCTION( typ, name ) \
+NCURSES_IMPEXP Form_Hook NCURSES_API typ ## _ ## name ( const FORM *form )\
+{\
+   T((T_CALLED(#typ "_" #name "(%p)"), (const void *) form));\
+   returnFormHook( Normalize_Form( form ) -> typ ## name );\
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  int set_field_init(FORM *form, Form_Hook f)
+|
+|   Description   :  Assigns an application defined initialization function
+|                    to be called when the form is posted and just after
+|                    the current field changes.
+|
+|   Return Values :  E_OK      - success
++--------------------------------------------------------------------------*/
+GEN_HOOK_SET_FUNCTION(field, init)
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  Form_Hook field_init(const FORM *form)
+|
+|   Description   :  Retrieve field initialization routine address.
+|
+|   Return Values :  The address or NULL if no hook defined.
++--------------------------------------------------------------------------*/
+GEN_HOOK_GET_FUNCTION(field, init)
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  int set_field_term(FORM *form, Form_Hook f)
+|
+|   Description   :  Assigns an application defined finalization function
+|                    to be called when the form is unposted and just before
+|                    the current field changes.
+|
+|   Return Values :  E_OK      - success
++--------------------------------------------------------------------------*/
+GEN_HOOK_SET_FUNCTION(field, term)
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  Form_Hook field_term(const FORM *form)
+|
+|   Description   :  Retrieve field finalization routine address.
+|
+|   Return Values :  The address or NULL if no hook defined.
++--------------------------------------------------------------------------*/
+GEN_HOOK_GET_FUNCTION(field, term)
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  int set_form_init(FORM *form, Form_Hook f)
+|
+|   Description   :  Assigns an application defined initialization function
+|                    to be called when the form is posted and just after
+|                    a page change.
+|
+|   Return Values :  E_OK       - success
++--------------------------------------------------------------------------*/
+GEN_HOOK_SET_FUNCTION(form, init)
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  Form_Hook form_init(const FORM *form)
+|
+|   Description   :  Retrieve form initialization routine address.
+|
+|   Return Values :  The address or NULL if no hook defined.
++--------------------------------------------------------------------------*/
+GEN_HOOK_GET_FUNCTION(form, init)
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  int set_form_term(FORM *form, Form_Hook f)
+|
+|   Description   :  Assigns an application defined finalization function
+|                    to be called when the form is unposted and just before
+|                    a page change.
+|
+|   Return Values :  E_OK       - success
++--------------------------------------------------------------------------*/
+GEN_HOOK_SET_FUNCTION(form, term)
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  Form_Hook form_term(const FORM *form)
+|
+|   Description   :  Retrieve form finalization routine address.
+|
+|   Return Values :  The address or NULL if no hook defined.
++--------------------------------------------------------------------------*/
+GEN_HOOK_GET_FUNCTION(form, term)
+
+/* frm_hook.c ends here */
diff --git a/apps/lib/curses/pdcurses/form/frm_opts.c b/apps/lib/curses/pdcurses/form/frm_opts.c
new file mode 100644
index 0000000..d51f345
--- /dev/null
+++ b/apps/lib/curses/pdcurses/form/frm_opts.c
@@ -0,0 +1,127 @@
+/****************************************************************************
+ * Copyright (c) 1998-2005,2010 Free Software Foundation, Inc.              *
+ *                                                                          *
+ * 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, distribute with modifications, sublicense, and/or sell       *
+ * copies of the Software, and to permit persons to whom the Software is    *
+ * furnished to do so, subject to the following conditions:                 *
+ *                                                                          *
+ * The above copyright notice and this permission notice shall be included  *
+ * in all copies or substantial portions of the Software.                   *
+ *                                                                          *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
+ * IN NO EVENT SHALL THE ABOVE 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.                               *
+ *                                                                          *
+ * Except as contained in this notice, the name(s) of the above copyright   *
+ * holders shall not be used in advertising or otherwise to promote the     *
+ * sale, use or other dealings in this Software without prior written       *
+ * authorization.                                                           *
+ ****************************************************************************/
+
+/****************************************************************************
+ *   Author:  Juergen Pfeifer, 1995,1997                                    *
+ ****************************************************************************/
+
+#include "form.priv.h"
+
+MODULE_ID("$Id: frm_opts.c,v 1.15 2010/01/23 21:14:36 tom Exp $")
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  int set_form_opts(FORM *form, Form_Options opts)
+|
+|   Description   :  Turns on the named options and turns off all the
+|                    remaining options for that form.
+|
+|   Return Values :  E_OK              - success
+|                    E_BAD_ARGUMENT    - invalid options
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(int)
+set_form_opts(FORM *form, Form_Options opts)
+{
+  T((T_CALLED("set_form_opts(%p,%d)"), (void *)form, opts));
+
+  opts &= ALL_FORM_OPTS;
+  if (opts & ~ALL_FORM_OPTS)
+    RETURN(E_BAD_ARGUMENT);
+  else
+    {
+      Normalize_Form(form)->opts = opts;
+      RETURN(E_OK);
+    }
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  Form_Options form_opts(const FORM *)
+|
+|   Description   :  Retrieves the current form options.
+|
+|   Return Values :  The option flags.
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(Form_Options)
+form_opts(const FORM *form)
+{
+  T((T_CALLED("form_opts(%p)"), (const void *)form));
+  returnCode((int)(Normalize_Form(form)->opts & ALL_FORM_OPTS));
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  int form_opts_on(FORM *form, Form_Options opts)
+|
+|   Description   :  Turns on the named options; no other options are
+|                    changed.
+|
+|   Return Values :  E_OK            - success
+|                    E_BAD_ARGUMENT  - invalid options
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(int)
+form_opts_on(FORM *form, Form_Options opts)
+{
+  T((T_CALLED("form_opts_on(%p,%d)"), (void *)form, opts));
+
+  opts &= ALL_FORM_OPTS;
+  if (opts & ~ALL_FORM_OPTS)
+    RETURN(E_BAD_ARGUMENT);
+  else
+    {
+      Normalize_Form(form)->opts |= opts;
+      RETURN(E_OK);
+    }
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  int form_opts_off(FORM *form, Form_Options opts)
+|
+|   Description   :  Turns off the named options; no other options are
+|                    changed.
+|
+|   Return Values :  E_OK            - success
+|                    E_BAD_ARGUMENT  - invalid options
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(int)
+form_opts_off(FORM *form, Form_Options opts)
+{
+  T((T_CALLED("form_opts_off(%p,%d)"), (void *)form, opts));
+
+  opts &= ALL_FORM_OPTS;
+  if (opts & ~ALL_FORM_OPTS)
+    RETURN(E_BAD_ARGUMENT);
+  else
+    {
+      Normalize_Form(form)->opts &= ~opts;
+      RETURN(E_OK);
+    }
+}
+
+/* frm_opts.c ends here */
diff --git a/apps/lib/curses/pdcurses/form/frm_page.c b/apps/lib/curses/pdcurses/form/frm_page.c
new file mode 100644
index 0000000..fdbc94c
--- /dev/null
+++ b/apps/lib/curses/pdcurses/form/frm_page.c
@@ -0,0 +1,106 @@
+/****************************************************************************
+ * Copyright (c) 1998-2004,2010 Free Software Foundation, Inc.              *
+ *                                                                          *
+ * 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, distribute with modifications, sublicense, and/or sell       *
+ * copies of the Software, and to permit persons to whom the Software is    *
+ * furnished to do so, subject to the following conditions:                 *
+ *                                                                          *
+ * The above copyright notice and this permission notice shall be included  *
+ * in all copies or substantial portions of the Software.                   *
+ *                                                                          *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
+ * IN NO EVENT SHALL THE ABOVE 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.                               *
+ *                                                                          *
+ * Except as contained in this notice, the name(s) of the above copyright   *
+ * holders shall not be used in advertising or otherwise to promote the     *
+ * sale, use or other dealings in this Software without prior written       *
+ * authorization.                                                           *
+ ****************************************************************************/
+
+/****************************************************************************
+ *   Author:  Juergen Pfeifer, 1995,1997                                    *
+ ****************************************************************************/
+
+#include "form.priv.h"
+
+MODULE_ID("$Id: frm_page.c,v 1.11 2010/01/23 21:14:36 tom Exp $")
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  int set_form_page(FORM * form,int  page)
+|
+|   Description   :  Set the page number of the form.
+|
+|   Return Values :  E_OK              - success
+|                    E_BAD_ARGUMENT    - invalid form pointer or page number
+|                    E_BAD_STATE       - called from a hook routine
+|                    E_INVALID_FIELD   - current field can't be left
+|                    E_SYSTEM_ERROR    - system error
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(int)
+set_form_page(FORM *form, int page)
+{
+  int err = E_OK;
+
+  T((T_CALLED("set_form_page(%p,%d)"), (void *)form, page));
+
+  if (!form || (page < 0) || (page >= form->maxpage))
+    RETURN(E_BAD_ARGUMENT);
+
+  if (!(form->status & _POSTED))
+    {
+      form->curpage = page;
+      form->current = _nc_First_Active_Field(form);
+    }
+  else
+    {
+      if (form->status & _IN_DRIVER)
+	err = E_BAD_STATE;
+      else
+	{
+	  if (form->curpage != page)
+	    {
+	      if (!_nc_Internal_Validation(form))
+		err = E_INVALID_FIELD;
+	      else
+		{
+		  Call_Hook(form, fieldterm);
+		  Call_Hook(form, formterm);
+		  err = _nc_Set_Form_Page(form, page, (FIELD *)0);
+		  Call_Hook(form, forminit);
+		  Call_Hook(form, fieldinit);
+		  _nc_Refresh_Current_Field(form);
+		}
+	    }
+	}
+    }
+  RETURN(err);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  int form_page(const FORM * form)
+|
+|   Description   :  Return the current page of the form.
+|
+|   Return Values :  >= 0  : current page number
+|                    -1    : invalid form pointer
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(int)
+form_page(const FORM *form)
+{
+  T((T_CALLED("form_page(%p)"), (const void *)form));
+
+  returnCode(Normalize_Form(form)->curpage);
+}
+
+/* frm_page.c ends here */
diff --git a/apps/lib/curses/pdcurses/form/frm_post.c b/apps/lib/curses/pdcurses/form/frm_post.c
new file mode 100644
index 0000000..5e9501e
--- /dev/null
+++ b/apps/lib/curses/pdcurses/form/frm_post.c
@@ -0,0 +1,124 @@
+/****************************************************************************
+ * Copyright (c) 1998-2004,2010 Free Software Foundation, Inc.              *
+ *                                                                          *
+ * 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, distribute with modifications, sublicense, and/or sell       *
+ * copies of the Software, and to permit persons to whom the Software is    *
+ * furnished to do so, subject to the following conditions:                 *
+ *                                                                          *
+ * The above copyright notice and this permission notice shall be included  *
+ * in all copies or substantial portions of the Software.                   *
+ *                                                                          *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
+ * IN NO EVENT SHALL THE ABOVE 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.                               *
+ *                                                                          *
+ * Except as contained in this notice, the name(s) of the above copyright   *
+ * holders shall not be used in advertising or otherwise to promote the     *
+ * sale, use or other dealings in this Software without prior written       *
+ * authorization.                                                           *
+ ****************************************************************************/
+
+/****************************************************************************
+ *   Author:  Juergen Pfeifer, 1995,1997                                    *
+ ****************************************************************************/
+
+#include "form.priv.h"
+
+MODULE_ID("$Id: frm_post.c,v 1.10 2010/01/23 21:14:36 tom Exp $")
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  int post_form(FORM * form)
+|
+|   Description   :  Writes the form into its associated subwindow.
+|
+|   Return Values :  E_OK              - success
+|                    E_BAD_ARGUMENT    - invalid form pointer
+|                    E_POSTED          - form already posted
+|                    E_NOT_CONNECTED   - no fields connected to form
+|                    E_NO_ROOM         - form doesn't fit into subwindow
+|                    E_SYSTEM_ERROR    - system error
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(int)
+post_form(FORM *form)
+{
+  WINDOW *formwin;
+  int err;
+  int page;
+
+  T((T_CALLED("post_form(%p)"), (void *)form));
+
+  if (!form)
+    RETURN(E_BAD_ARGUMENT);
+
+  if (form->status & _POSTED)
+    RETURN(E_POSTED);
+
+  if (!(form->field))
+    RETURN(E_NOT_CONNECTED);
+
+  formwin = Get_Form_Window(form);
+  if ((form->cols > getmaxx(formwin)) || (form->rows > getmaxy(formwin)))
+    RETURN(E_NO_ROOM);
+
+  /* reset form->curpage to an invald value. This forces Set_Form_Page
+     to do the page initialization which is required by post_form.
+   */
+  page = form->curpage;
+  form->curpage = -1;
+  if ((err = _nc_Set_Form_Page(form, page, form->current)) != E_OK)
+    RETURN(err);
+
+  form->status |= _POSTED;
+
+  Call_Hook(form, forminit);
+  Call_Hook(form, fieldinit);
+
+  _nc_Refresh_Current_Field(form);
+  RETURN(E_OK);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  int unpost_form(FORM * form)
+|
+|   Description   :  Erase form from its associated subwindow.
+|
+|   Return Values :  E_OK            - success
+|                    E_BAD_ARGUMENT  - invalid form pointer
+|                    E_NOT_POSTED    - form isn't posted
+|                    E_BAD_STATE     - called from a hook routine
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(int)
+unpost_form(FORM *form)
+{
+  T((T_CALLED("unpost_form(%p)"), (void *)form));
+
+  if (!form)
+    RETURN(E_BAD_ARGUMENT);
+
+  if (!(form->status & _POSTED))
+    RETURN(E_NOT_POSTED);
+
+  if (form->status & _IN_DRIVER)
+    RETURN(E_BAD_STATE);
+
+  Call_Hook(form, fieldterm);
+  Call_Hook(form, formterm);
+
+  werase(Get_Form_Window(form));
+  delwin(form->w);
+  form->w = (WINDOW *)0;
+  form->status &= ~_POSTED;
+  RETURN(E_OK);
+}
+
+/* frm_post.c ends here */
diff --git a/apps/lib/curses/pdcurses/form/frm_req_name.c b/apps/lib/curses/pdcurses/form/frm_req_name.c
new file mode 100644
index 0000000..dbef6d7
--- /dev/null
+++ b/apps/lib/curses/pdcurses/form/frm_req_name.c
@@ -0,0 +1,170 @@
+/****************************************************************************
+ * Copyright (c) 1998-2008,2009 Free Software Foundation, Inc.              *
+ *                                                                          *
+ * 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, distribute with modifications, sublicense, and/or sell       *
+ * copies of the Software, and to permit persons to whom the Software is    *
+ * furnished to do so, subject to the following conditions:                 *
+ *                                                                          *
+ * The above copyright notice and this permission notice shall be included  *
+ * in all copies or substantial portions of the Software.                   *
+ *                                                                          *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
+ * IN NO EVENT SHALL THE ABOVE 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.                               *
+ *                                                                          *
+ * Except as contained in this notice, the name(s) of the above copyright   *
+ * holders shall not be used in advertising or otherwise to promote the     *
+ * sale, use or other dealings in this Software without prior written       *
+ * authorization.                                                           *
+ ****************************************************************************/
+
+/****************************************************************************
+ *   Author:  Juergen Pfeifer, 1995,1997                                    *
+ ****************************************************************************/
+
+/***************************************************************************
+* Module form_request_name                                                 *
+* Routines to handle external names of menu requests                       *
+***************************************************************************/
+
+#include "form.priv.h"
+
+MODULE_ID("$Id: frm_req_name.c,v 1.17 2009/10/10 16:17:01 tom Exp $")
+
+static const char *request_names[MAX_FORM_COMMAND - MIN_FORM_COMMAND + 1] =
+{
+  "NEXT_PAGE",
+  "PREV_PAGE",
+  "FIRST_PAGE",
+  "LAST_PAGE",
+
+  "NEXT_FIELD",
+  "PREV_FIELD",
+  "FIRST_FIELD",
+  "LAST_FIELD",
+  "SNEXT_FIELD",
+  "SPREV_FIELD",
+  "SFIRST_FIELD",
+  "SLAST_FIELD",
+  "LEFT_FIELD",
+  "RIGHT_FIELD",
+  "UP_FIELD",
+  "DOWN_FIELD",
+
+  "NEXT_CHAR",
+  "PREV_CHAR",
+  "NEXT_LINE",
+  "PREV_LINE",
+  "NEXT_WORD",
+  "PREV_WORD",
+  "BEG_FIELD",
+  "END_FIELD",
+  "BEG_LINE",
+  "END_LINE",
+  "LEFT_CHAR",
+  "RIGHT_CHAR",
+  "UP_CHAR",
+  "DOWN_CHAR",
+
+  "NEW_LINE",
+  "INS_CHAR",
+  "INS_LINE",
+  "DEL_CHAR",
+  "DEL_PREV",
+  "DEL_LINE",
+  "DEL_WORD",
+  "CLR_EOL",
+  "CLR_EOF",
+  "CLR_FIELD",
+  "OVL_MODE",
+  "INS_MODE",
+  "SCR_FLINE",
+  "SCR_BLINE",
+  "SCR_FPAGE",
+  "SCR_BPAGE",
+  "SCR_FHPAGE",
+  "SCR_BHPAGE",
+  "SCR_FCHAR",
+  "SCR_BCHAR",
+  "SCR_HFLINE",
+  "SCR_HBLINE",
+  "SCR_HFHALF",
+  "SCR_HBHALF",
+
+  "VALIDATION",
+  "NEXT_CHOICE",
+  "PREV_CHOICE"
+};
+
+#define A_SIZE (sizeof(request_names)/sizeof(request_names[0]))
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  const char * form_request_name (int request);
+|
+|   Description   :  Get the external name of a form request.
+|
+|   Return Values :  Pointer to name      - on success
+|                    NULL                 - on invalid request code
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(const char *)
+form_request_name(int request)
+{
+  T((T_CALLED("form_request_name(%d)"), request));
+
+  if ((request < MIN_FORM_COMMAND) || (request > MAX_FORM_COMMAND))
+    {
+      SET_ERROR(E_BAD_ARGUMENT);
+      returnCPtr((const char *)0);
+    }
+  else
+    returnCPtr(request_names[request - MIN_FORM_COMMAND]);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  int form_request_by_name (const char *str);
+|
+|   Description   :  Search for a request with this name.
+|
+|   Return Values :  Request Id       - on success
+|                    E_NO_MATCH       - request not found
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(int)
+form_request_by_name(const char *str)
+{
+  /* because the table is so small, it doesn't really hurt
+     to run sequentially through it.
+   */
+  unsigned int i = 0;
+  char buf[16];
+
+  T((T_CALLED("form_request_by_name(%s)"), _nc_visbuf(str)));
+
+  if (str)
+    {
+      strncpy(buf, str, sizeof(buf));
+      while ((i < sizeof(buf)) && (buf[i] != '\0'))
+	{
+	  buf[i] = (char)toupper(UChar(buf[i]));
+	  i++;
+	}
+
+      for (i = 0; i < A_SIZE; i++)
+	{
+	  if (strncmp(request_names[i], buf, sizeof(buf)) == 0)
+	    returnCode(MIN_FORM_COMMAND + (int)i);
+	}
+    }
+  RETURN(E_NO_MATCH);
+}
+
+/* frm_req_name.c ends here */
diff --git a/apps/lib/curses/pdcurses/form/frm_scale.c b/apps/lib/curses/pdcurses/form/frm_scale.c
new file mode 100644
index 0000000..18a565e
--- /dev/null
+++ b/apps/lib/curses/pdcurses/form/frm_scale.c
@@ -0,0 +1,69 @@
+/****************************************************************************
+ * Copyright (c) 1998-2004,2010 Free Software Foundation, Inc.              *
+ *                                                                          *
+ * 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, distribute with modifications, sublicense, and/or sell       *
+ * copies of the Software, and to permit persons to whom the Software is    *
+ * furnished to do so, subject to the following conditions:                 *
+ *                                                                          *
+ * The above copyright notice and this permission notice shall be included  *
+ * in all copies or substantial portions of the Software.                   *
+ *                                                                          *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
+ * IN NO EVENT SHALL THE ABOVE 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.                               *
+ *                                                                          *
+ * Except as contained in this notice, the name(s) of the above copyright   *
+ * holders shall not be used in advertising or otherwise to promote the     *
+ * sale, use or other dealings in this Software without prior written       *
+ * authorization.                                                           *
+ ****************************************************************************/
+
+/****************************************************************************
+ *   Author:  Juergen Pfeifer, 1995,1997                                    *
+ ****************************************************************************/
+
+#include "form.priv.h"
+
+MODULE_ID("$Id: frm_scale.c,v 1.10 2010/01/23 21:14:36 tom Exp $")
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  int scale_form( const FORM *form, int *rows, int *cols )
+|
+|   Description   :  Retrieve size of form
+|
+|   Return Values :  E_OK              - no error
+|                    E_BAD_ARGUMENT    - invalid form pointer
+|                    E_NOT_CONNECTED   - no fields connected to form
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(int)
+scale_form(const FORM *form, int *rows, int *cols)
+{
+  T((T_CALLED("scale_form(%p,%p,%p)"),
+     (const void *)form,
+     (void *)rows,
+     (void *)cols));
+
+  if (!form)
+    RETURN(E_BAD_ARGUMENT);
+
+  if (!(form->field))
+    RETURN(E_NOT_CONNECTED);
+
+  if (rows)
+    *rows = form->rows;
+  if (cols)
+    *cols = form->cols;
+
+  RETURN(E_OK);
+}
+
+/* frm_scale.c ends here */
diff --git a/apps/lib/curses/pdcurses/form/frm_sub.c b/apps/lib/curses/pdcurses/form/frm_sub.c
new file mode 100644
index 0000000..cf5b82f
--- /dev/null
+++ b/apps/lib/curses/pdcurses/form/frm_sub.c
@@ -0,0 +1,86 @@
+/****************************************************************************
+ * Copyright (c) 1998-2009,2010 Free Software Foundation, Inc.              *
+ *                                                                          *
+ * 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, distribute with modifications, sublicense, and/or sell       *
+ * copies of the Software, and to permit persons to whom the Software is    *
+ * furnished to do so, subject to the following conditions:                 *
+ *                                                                          *
+ * The above copyright notice and this permission notice shall be included  *
+ * in all copies or substantial portions of the Software.                   *
+ *                                                                          *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
+ * IN NO EVENT SHALL THE ABOVE 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.                               *
+ *                                                                          *
+ * Except as contained in this notice, the name(s) of the above copyright   *
+ * holders shall not be used in advertising or otherwise to promote the     *
+ * sale, use or other dealings in this Software without prior written       *
+ * authorization.                                                           *
+ ****************************************************************************/
+
+/****************************************************************************
+ *   Author:  Juergen Pfeifer, 1995-1997,2009                               *
+ ****************************************************************************/
+
+#include "form.priv.h"
+
+MODULE_ID("$Id: frm_sub.c,v 1.12 2010/01/23 21:14:36 tom Exp $")
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  int set_form_sub(FORM *form, WINDOW *win)
+|
+|   Description   :  Set the subwindow of the form to win.
+|
+|   Return Values :  E_OK       - success
+|                    E_POSTED   - form is posted
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(int)
+set_form_sub(FORM *form, WINDOW *win)
+{
+  T((T_CALLED("set_form_sub(%p,%p)"), (void *)form, (void *)win));
+
+  if (form && (form->status & _POSTED))
+    RETURN(E_POSTED);
+  else
+    {
+#if NCURSES_SP_FUNCS
+      FORM *f = Normalize_Form(form);
+
+      f->sub = win ? win : StdScreen(Get_Form_Screen(f));
+      RETURN(E_OK);
+#else
+      Normalize_Form(form)->sub = win;
+      RETURN(E_OK);
+#endif
+    }
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  WINDOW *form_sub(const FORM *)
+|
+|   Description   :  Retrieve the window of the form.
+|
+|   Return Values :  The pointer to the Subwindow.
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(WINDOW *)
+form_sub(const FORM *form)
+{
+  const FORM *f;
+
+  T((T_CALLED("form_sub(%p)"), (const void *)form));
+
+  f = Normalize_Form(form);
+  returnWin(Get_Form_Window(f));
+}
+
+/* frm_sub.c ends here */
diff --git a/apps/lib/curses/pdcurses/form/frm_user.c b/apps/lib/curses/pdcurses/form/frm_user.c
new file mode 100644
index 0000000..5cab224
--- /dev/null
+++ b/apps/lib/curses/pdcurses/form/frm_user.c
@@ -0,0 +1,72 @@
+/****************************************************************************
+ * Copyright (c) 1998-2004,2010 Free Software Foundation, Inc.              *
+ *                                                                          *
+ * 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, distribute with modifications, sublicense, and/or sell       *
+ * copies of the Software, and to permit persons to whom the Software is    *
+ * furnished to do so, subject to the following conditions:                 *
+ *                                                                          *
+ * The above copyright notice and this permission notice shall be included  *
+ * in all copies or substantial portions of the Software.                   *
+ *                                                                          *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
+ * IN NO EVENT SHALL THE ABOVE 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.                               *
+ *                                                                          *
+ * Except as contained in this notice, the name(s) of the above copyright   *
+ * holders shall not be used in advertising or otherwise to promote the     *
+ * sale, use or other dealings in this Software without prior written       *
+ * authorization.                                                           *
+ ****************************************************************************/
+
+/****************************************************************************
+ *   Author:  Juergen Pfeifer, 1995,1997                                    *
+ ****************************************************************************/
+
+#include "form.priv.h"
+
+MODULE_ID("$Id: frm_user.c,v 1.15 2010/01/23 21:14:36 tom Exp $")
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  int set_form_userptr(FORM *form, void *usrptr)
+|
+|   Description   :  Set the pointer that is reserved in any form to store
+|                    application relevant informations
+|
+|   Return Values :  E_OK         - on success
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(int)
+set_form_userptr(FORM *form, void *usrptr)
+{
+  T((T_CALLED("set_form_userptr(%p,%p)"), (void *)form, (void *)usrptr));
+
+  Normalize_Form(form)->usrptr = usrptr;
+  RETURN(E_OK);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  void *form_userptr(const FORM *form)
+|
+|   Description   :  Return the pointer that is reserved in any form to
+|                    store application relevant informations.
+|
+|   Return Values :  Value of pointer. If no such pointer has been set,
+|                    NULL is returned
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(void *)
+form_userptr(const FORM *form)
+{
+  T((T_CALLED("form_userptr(%p)"), (const void *)form));
+  returnVoidPtr(Normalize_Form(form)->usrptr);
+}
+
+/* frm_user.c ends here */
diff --git a/apps/lib/curses/pdcurses/form/frm_win.c b/apps/lib/curses/pdcurses/form/frm_win.c
new file mode 100644
index 0000000..82cf2d3
--- /dev/null
+++ b/apps/lib/curses/pdcurses/form/frm_win.c
@@ -0,0 +1,92 @@
+/****************************************************************************
+ * Copyright (c) 1998-2009,2010 Free Software Foundation, Inc.              *
+ *                                                                          *
+ * 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, distribute with modifications, sublicense, and/or sell       *
+ * copies of the Software, and to permit persons to whom the Software is    *
+ * furnished to do so, subject to the following conditions:                 *
+ *                                                                          *
+ * The above copyright notice and this permission notice shall be included  *
+ * in all copies or substantial portions of the Software.                   *
+ *                                                                          *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
+ * IN NO EVENT SHALL THE ABOVE 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.                               *
+ *                                                                          *
+ * Except as contained in this notice, the name(s) of the above copyright   *
+ * holders shall not be used in advertising or otherwise to promote the     *
+ * sale, use or other dealings in this Software without prior written       *
+ * authorization.                                                           *
+ ****************************************************************************/
+
+/****************************************************************************
+ *   Author:  Juergen Pfeifer, 1995,1997                                    *
+ ****************************************************************************/
+
+#include "form.priv.h"
+
+MODULE_ID("$Id: frm_win.c,v 1.16 2010/01/23 21:14:36 tom Exp $")
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  int set_form_win(FORM *form,WINDOW *win)
+|
+|   Description   :  Set the window of the form to win.
+|
+|   Return Values :  E_OK       - success
+|                    E_POSTED   - form is posted
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(int)
+set_form_win(FORM *form, WINDOW *win)
+{
+  T((T_CALLED("set_form_win(%p,%p)"), (void *)form, (void *)win));
+
+  if (form && (form->status & _POSTED))
+    RETURN(E_POSTED);
+  else
+    {
+#if NCURSES_SP_FUNCS
+      FORM *f = Normalize_Form(form);
+
+      f->win = win ? win : StdScreen(Get_Form_Screen(f));
+      RETURN(E_OK);
+#else
+      Normalize_Form(form)->win = win;
+      RETURN(E_OK);
+#endif
+    }
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  WINDOW *form_win(const FORM *)
+|
+|   Description   :  Retrieve the window of the form.
+|
+|   Return Values :  The pointer to the Window or stdscr if there is none.
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(WINDOW *)
+form_win(const FORM *form)
+{
+  WINDOW *result;
+  const FORM *f;
+
+  T((T_CALLED("form_win(%p)"), (const void *)form));
+
+  f = Normalize_Form(form);
+#if NCURSES_SP_FUNCS
+  result = (f->win ? f->win : StdScreen(Get_Form_Screen(f)));
+#else
+  result = (f->win ? f->win : stdscr);
+#endif
+  returnWin(result);
+}
+
+/* frm_win.c ends here */
diff --git a/apps/lib/curses/pdcurses/form/fty_alnum.c b/apps/lib/curses/pdcurses/form/fty_alnum.c
new file mode 100644
index 0000000..cda23dc
--- /dev/null
+++ b/apps/lib/curses/pdcurses/form/fty_alnum.c
@@ -0,0 +1,202 @@
+/****************************************************************************
+ * Copyright (c) 1998-2009,2010 Free Software Foundation, Inc.              *
+ *                                                                          *
+ * 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, distribute with modifications, sublicense, and/or sell       *
+ * copies of the Software, and to permit persons to whom the Software is    *
+ * furnished to do so, subject to the following conditions:                 *
+ *                                                                          *
+ * The above copyright notice and this permission notice shall be included  *
+ * in all copies or substantial portions of the Software.                   *
+ *                                                                          *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
+ * IN NO EVENT SHALL THE ABOVE 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.                               *
+ *                                                                          *
+ * Except as contained in this notice, the name(s) of the above copyright   *
+ * holders shall not be used in advertising or otherwise to promote the     *
+ * sale, use or other dealings in this Software without prior written       *
+ * authorization.                                                           *
+ ****************************************************************************/
+
+/***************************************************************************
+*                                                                          *
+*  Author : Juergen Pfeifer                                                *
+*                                                                          *
+***************************************************************************/
+
+#include "form.priv.h"
+
+MODULE_ID("$Id: fty_alnum.c,v 1.24 2010/01/23 21:14:36 tom Exp $")
+
+#define thisARG alnumARG
+
+typedef struct
+  {
+    int width;
+  }
+thisARG;
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static void *Generic_This_Type(void *arg)
+|
+|   Description   :  Allocate structure for alphanumeric type argument.
+|
+|   Return Values :  Pointer to argument structure or NULL on error
++--------------------------------------------------------------------------*/
+static void *
+Generic_This_Type(void *arg)
+{
+  thisARG *argp = (thisARG *) 0;
+
+  if (arg)
+    {
+      argp = typeMalloc(thisARG, 1);
+
+      if (argp)
+	{
+	  T((T_CREATE("thisARG %p"), (void *)argp));
+	  argp->width = *((int *)arg);
+	}
+    }
+  return ((void *)argp);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static void *Make_This_Type(va_list *ap)
+|
+|   Description   :  Allocate structure for alphanumeric type argument.
+|
+|   Return Values :  Pointer to argument structure or NULL on error
++--------------------------------------------------------------------------*/
+static void *
+Make_This_Type(va_list *ap)
+{
+  int w = va_arg(*ap, int);
+
+  return Generic_This_Type((void *)&w);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static void *Copy_ThisType(const void *argp)
+|
+|   Description   :  Copy structure for alphanumeric type argument.
+|
+|   Return Values :  Pointer to argument structure or NULL on error.
++--------------------------------------------------------------------------*/
+static void *
+Copy_This_Type(const void *argp)
+{
+  const thisARG *ap = (const thisARG *)argp;
+  thisARG *result = typeMalloc(thisARG, 1);
+
+  if (result)
+    {
+      T((T_CREATE("thisARG %p"), (void *)result));
+      *result = *ap;
+    }
+
+  return ((void *)result);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static void Free_This_Type(void *argp)
+|
+|   Description   :  Free structure for alphanumeric type argument.
+|
+|   Return Values :  -
++--------------------------------------------------------------------------*/
+static void
+Free_This_Type(void *argp)
+{
+  if (argp)
+    free(argp);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static bool Check_This_Character(
+|                                      int c,
+|                                      const void *argp)
+|
+|   Description   :  Check a character for the alphanumeric type.
+|
+|   Return Values :  TRUE  - character is valid
+|                    FALSE - character is invalid
++--------------------------------------------------------------------------*/
+static bool
+Check_This_Character(int c, const void *argp GCC_UNUSED)
+{
+#if USE_WIDEC_SUPPORT
+  if (iswalnum((wint_t) c))
+    return TRUE;
+#endif
+  return (isalnum(UChar(c)) ? TRUE : FALSE);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static bool Check_This_Field(
+|                                      FIELD *field,
+|                                      const void *argp)
+|
+|   Description   :  Validate buffer content to be a valid alphanumeric value
+|
+|   Return Values :  TRUE  - field is valid
+|                    FALSE - field is invalid
++--------------------------------------------------------------------------*/
+static bool
+Check_This_Field(FIELD *field, const void *argp)
+{
+  int width = ((const thisARG *)argp)->width;
+  unsigned char *bp = (unsigned char *)field_buffer(field, 0);
+  bool result = (width < 0);
+
+  Check_CTYPE_Field(result, bp, width, Check_This_Character);
+  return (result);
+}
+
+static FIELDTYPE typeTHIS =
+{
+  _HAS_ARGS | _RESIDENT,
+  1,				/* this is mutable, so we can't be const */
+  (FIELDTYPE *)0,
+  (FIELDTYPE *)0,
+  Make_This_Type,
+  Copy_This_Type,
+  Free_This_Type,
+  INIT_FT_FUNC(Check_This_Field),
+  INIT_FT_FUNC(Check_This_Character),
+  INIT_FT_FUNC(NULL),
+  INIT_FT_FUNC(NULL),
+#if NCURSES_INTEROP_FUNCS
+  Generic_This_Type
+#endif
+};
+
+NCURSES_EXPORT_VAR(FIELDTYPE*) TYPE_ALNUM = &typeTHIS;
+
+#if NCURSES_INTEROP_FUNCS
+/* The next routines are to simplify the use of ncurses from
+   programming languages with restictions on interop with C level
+   constructs (e.g. variable access or va_list + ellipsis constructs)
+*/
+NCURSES_EXPORT(FIELDTYPE *)
+_nc_TYPE_ALNUM(void)
+{
+  return TYPE_ALNUM;
+}
+#endif
+
+/* fty_alnum.c ends here */
diff --git a/apps/lib/curses/pdcurses/form/fty_alpha.c b/apps/lib/curses/pdcurses/form/fty_alpha.c
new file mode 100644
index 0000000..917a9e0
--- /dev/null
+++ b/apps/lib/curses/pdcurses/form/fty_alpha.c
@@ -0,0 +1,202 @@
+/****************************************************************************
+ * Copyright (c) 1998-2009,2010 Free Software Foundation, Inc.              *
+ *                                                                          *
+ * 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, distribute with modifications, sublicense, and/or sell       *
+ * copies of the Software, and to permit persons to whom the Software is    *
+ * furnished to do so, subject to the following conditions:                 *
+ *                                                                          *
+ * The above copyright notice and this permission notice shall be included  *
+ * in all copies or substantial portions of the Software.                   *
+ *                                                                          *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
+ * IN NO EVENT SHALL THE ABOVE 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.                               *
+ *                                                                          *
+ * Except as contained in this notice, the name(s) of the above copyright   *
+ * holders shall not be used in advertising or otherwise to promote the     *
+ * sale, use or other dealings in this Software without prior written       *
+ * authorization.                                                           *
+ ****************************************************************************/
+
+/***************************************************************************
+*                                                                          *
+*  Author : Juergen Pfeifer                                                *
+*                                                                          *
+***************************************************************************/
+
+#include "form.priv.h"
+
+MODULE_ID("$Id: fty_alpha.c,v 1.26 2010/01/23 21:14:36 tom Exp $")
+
+#define thisARG alphaARG
+
+typedef struct
+  {
+    int width;
+  }
+thisARG;
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static void *Generic_This_Type(va_list *ap)
+|
+|   Description   :  Allocate structure for alpha type argument.
+|
+|   Return Values :  Pointer to argument structure or NULL on error
++--------------------------------------------------------------------------*/
+static void *
+Generic_This_Type(void *arg)
+{
+  thisARG *argp = (thisARG *) 0;
+
+  if (arg)
+    {
+      argp = typeMalloc(thisARG, 1);
+
+      if (argp)
+	{
+	  T((T_CREATE("thisARG %p"), (void *)argp));
+	  argp->width = *((int *)arg);
+	}
+    }
+  return ((void *)argp);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static void *Make_This_Type(va_list *ap)
+|
+|   Description   :  Allocate structure for alpha type argument.
+|
+|   Return Values :  Pointer to argument structure or NULL on error
++--------------------------------------------------------------------------*/
+static void *
+Make_This_Type(va_list *ap)
+{
+  int w = va_arg(*ap, int);
+
+  return Generic_This_Type((void *)&w);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static void *Copy_This_Type(const void * argp)
+|
+|   Description   :  Copy structure for alpha type argument.
+|
+|   Return Values :  Pointer to argument structure or NULL on error.
++--------------------------------------------------------------------------*/
+static void *
+Copy_This_Type(const void *argp)
+{
+  const thisARG *ap = (const thisARG *)argp;
+  thisARG *result = typeMalloc(thisARG, 1);
+
+  if (result)
+    {
+      T((T_CREATE("thisARG %p"), (void *)result));
+      *result = *ap;
+    }
+
+  return ((void *)result);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static void Free_This_Type(void *argp)
+|
+|   Description   :  Free structure for alpha type argument.
+|
+|   Return Values :  -
++--------------------------------------------------------------------------*/
+static void
+Free_This_Type(void *argp)
+{
+  if (argp)
+    free(argp);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static bool Check_This_Character(
+|                                      int c,
+|                                      const void *argp)
+|
+|   Description   :  Check a character for the alpha type.
+|
+|   Return Values :  TRUE  - character is valid
+|                    FALSE - character is invalid
++--------------------------------------------------------------------------*/
+static bool
+Check_This_Character(int c, const void *argp GCC_UNUSED)
+{
+#if USE_WIDEC_SUPPORT
+  if (iswalpha((wint_t) c))
+    return TRUE;
+#endif
+  return (isalpha(UChar(c)) ? TRUE : FALSE);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static bool Check_This_Field(
+|                                      FIELD *field,
+|                                      const void *argp)
+|
+|   Description   :  Validate buffer content to be a valid alpha value
+|
+|   Return Values :  TRUE  - field is valid
+|                    FALSE - field is invalid
++--------------------------------------------------------------------------*/
+static bool
+Check_This_Field(FIELD *field, const void *argp)
+{
+  int width = ((const thisARG *)argp)->width;
+  unsigned char *bp = (unsigned char *)field_buffer(field, 0);
+  bool result = (width < 0);
+
+  Check_CTYPE_Field(result, bp, width, Check_This_Character);
+  return (result);
+}
+
+static FIELDTYPE typeTHIS =
+{
+  _HAS_ARGS | _RESIDENT,
+  1,				/* this is mutable, so we can't be const */
+  (FIELDTYPE *)0,
+  (FIELDTYPE *)0,
+  Make_This_Type,
+  Copy_This_Type,
+  Free_This_Type,
+  INIT_FT_FUNC(Check_This_Field),
+  INIT_FT_FUNC(Check_This_Character),
+  INIT_FT_FUNC(NULL),
+  INIT_FT_FUNC(NULL),
+#if NCURSES_INTEROP_FUNCS
+  Generic_This_Type
+#endif
+};
+
+NCURSES_EXPORT_VAR(FIELDTYPE*) TYPE_ALPHA = &typeTHIS;
+
+#if NCURSES_INTEROP_FUNCS
+/* The next routines are to simplify the use of ncurses from
+   programming languages with restictions on interop with C level
+   constructs (e.g. variable access or va_list + ellipsis constructs)
+*/
+NCURSES_EXPORT(FIELDTYPE *)
+_nc_TYPE_ALPHA(void)
+{
+  return TYPE_ALPHA;
+}
+#endif
+
+/* fty_alpha.c ends here */
diff --git a/apps/lib/curses/pdcurses/form/fty_enum.c b/apps/lib/curses/pdcurses/form/fty_enum.c
new file mode 100644
index 0000000..2fd96f0
--- /dev/null
+++ b/apps/lib/curses/pdcurses/form/fty_enum.c
@@ -0,0 +1,442 @@
+/****************************************************************************
+ * Copyright (c) 1998-2009,2010 Free Software Foundation, Inc.              *
+ *                                                                          *
+ * 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, distribute with modifications, sublicense, and/or sell       *
+ * copies of the Software, and to permit persons to whom the Software is    *
+ * furnished to do so, subject to the following conditions:                 *
+ *                                                                          *
+ * The above copyright notice and this permission notice shall be included  *
+ * in all copies or substantial portions of the Software.                   *
+ *                                                                          *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
+ * IN NO EVENT SHALL THE ABOVE 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.                               *
+ *                                                                          *
+ * Except as contained in this notice, the name(s) of the above copyright   *
+ * holders shall not be used in advertising or otherwise to promote the     *
+ * sale, use or other dealings in this Software without prior written       *
+ * authorization.                                                           *
+ ****************************************************************************/
+
+/***************************************************************************
+*                                                                          *
+*  Author : Juergen Pfeifer                                                *
+*                                                                          *
+***************************************************************************/
+
+#include "form.priv.h"
+
+MODULE_ID("$Id: fty_enum.c,v 1.26 2010/05/01 21:11:07 tom Exp $")
+
+typedef struct
+  {
+    char **kwds;
+    int count;
+    bool checkcase;
+    bool checkunique;
+  }
+enumARG;
+
+typedef struct
+  {
+    char **kwds;
+    int ccase;
+    int cunique;
+  }
+enumParams;
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static void *Generic_Enum_Type(void * arg)
+|
+|   Description   :  Allocate structure for enumeration type argument.
+|
+|   Return Values :  Pointer to argument structure or NULL on error
++--------------------------------------------------------------------------*/
+static void *
+Generic_Enum_Type(void *arg)
+{
+  enumARG *argp = (enumARG *)0;
+  enumParams *params = (enumParams *) arg;
+
+  if (params)
+    {
+      argp = typeMalloc(enumARG, 1);
+
+      if (argp)
+	{
+	  int cnt = 0;
+	  char **kp = (char **)0;
+	  char **kwds = (char **)0;
+	  char **kptarget;
+	  int ccase, cunique;
+
+	  T((T_CREATE("enumARG %p"), (void *)argp));
+	  kwds = params->kwds;
+	  ccase = params->ccase;
+	  cunique = params->cunique;
+
+	  argp->checkcase = ccase ? TRUE : FALSE;
+	  argp->checkunique = cunique ? TRUE : FALSE;
+	  argp->kwds = (char **)0;
+
+	  kp = kwds;
+	  while (kp && (*kp++))
+	    cnt++;
+	  argp->count = cnt;
+
+	  if (cnt > 0)
+	    {
+	      /* We copy the keywords, because we can't rely on the fact
+	         that the caller doesn't relocate or free the memory used
+	         for the keywords (maybe he has GC)
+	       */
+	      argp->kwds = typeMalloc(char *, cnt + 1);
+
+	      kp = kwds;
+	      if ((kptarget = argp->kwds) != 0)
+		{
+		  while (kp && (*kp))
+		    {
+		      (*kptarget++) = strdup(*kp++);
+		    }
+		  *kptarget = (char *)0;
+		}
+	    }
+	}
+    }
+  return (void *)argp;
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static void *Make_Enum_Type( va_list * ap )
+|
+|   Description   :  Allocate structure for enumeration type argument.
+|
+|   Return Values :  Pointer to argument structure or NULL on error
++--------------------------------------------------------------------------*/
+static void *
+Make_Enum_Type(va_list *ap)
+{
+  enumParams params;
+
+  params.kwds = va_arg(*ap, char **);
+  params.ccase = va_arg(*ap, int);
+  params.cunique = va_arg(*ap, int);
+
+  return Generic_Enum_Type((void *)&params);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static void *Copy_Enum_Type( const void * argp )
+|
+|   Description   :  Copy structure for enumeration type argument.
+|
+|   Return Values :  Pointer to argument structure or NULL on error.
++--------------------------------------------------------------------------*/
+static void *
+Copy_Enum_Type(const void *argp)
+{
+  enumARG *result = (enumARG *)0;
+
+  if (argp)
+    {
+      const enumARG *ap = (const enumARG *)argp;
+
+      result = typeMalloc(enumARG, 1);
+
+      if (result)
+	{
+	  T((T_CREATE("enumARG %p"), (void *)result));
+	  *result = *ap;
+
+	  if (ap->count > 0)
+	    {
+	      char **kptarget;
+	      char **kp = ap->kwds;
+	      result->kwds = typeMalloc(char *, 1 + ap->count);
+
+	      if ((kptarget = result->kwds) != 0)
+		{
+		  while (kp && (*kp))
+		    {
+		      (*kptarget++) = strdup(*kp++);
+		    }
+		  *kptarget = (char *)0;
+		}
+	    }
+	}
+    }
+  return (void *)result;
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static void Free_Enum_Type( void * argp )
+|
+|   Description   :  Free structure for enumeration type argument.
+|
+|   Return Values :  -
++--------------------------------------------------------------------------*/
+static void
+Free_Enum_Type(void *argp)
+{
+  if (argp)
+    {
+      const enumARG *ap = (const enumARG *)argp;
+
+      if (ap->kwds && ap->count > 0)
+	{
+	  char **kp = ap->kwds;
+	  int cnt = 0;
+
+	  while (kp && (*kp))
+	    {
+	      free(*kp++);
+	      cnt++;
+	    }
+	  assert(cnt == ap->count);
+	  free(ap->kwds);
+	}
+      free(argp);
+    }
+}
+
+#define SKIP_SPACE(x) while(((*(x))!='\0') && (is_blank(*(x)))) (x)++
+#define NOMATCH 0
+#define PARTIAL 1
+#define EXACT   2
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static int Compare(const unsigned char * s,
+|                                       const unsigned char * buf,
+|                                       bool  ccase )
+|
+|   Description   :  Check whether or not the text in 'buf' matches the
+|                    text in 's', at least partial.
+|
+|   Return Values :  NOMATCH   - buffer doesn't match
+|                    PARTIAL   - buffer matches partially
+|                    EXACT     - buffer matches exactly
++--------------------------------------------------------------------------*/
+static int
+Compare(const unsigned char *s, const unsigned char *buf,
+	bool ccase)
+{
+  SKIP_SPACE(buf);		/* Skip leading spaces in both texts */
+  SKIP_SPACE(s);
+
+  if (*buf == '\0')
+    {
+      return (((*s) != '\0') ? NOMATCH : EXACT);
+    }
+  else
+    {
+      if (ccase)
+	{
+	  while (*s++ == *buf)
+	    {
+	      if (*buf++ == '\0')
+		return EXACT;
+	    }
+	}
+      else
+	{
+	  while (toupper(*s++) == toupper(*buf))
+	    {
+	      if (*buf++ == '\0')
+		return EXACT;
+	    }
+	}
+    }
+  /* At this location buf points to the first character where it no longer
+     matches with s. So if only blanks are following, we have a partial
+     match otherwise there is no match */
+  SKIP_SPACE(buf);
+  if (*buf)
+    return NOMATCH;
+
+  /* If it happens that the reference buffer is at its end, the partial
+     match is actually an exact match. */
+  return ((s[-1] != '\0') ? PARTIAL : EXACT);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static bool Check_Enum_Field(
+|                                      FIELD * field,
+|                                      const void  * argp)
+|
+|   Description   :  Validate buffer content to be a valid enumeration value
+|
+|   Return Values :  TRUE  - field is valid
+|                    FALSE - field is invalid
++--------------------------------------------------------------------------*/
+static bool
+Check_Enum_Field(FIELD *field, const void *argp)
+{
+  char **kwds = ((const enumARG *)argp)->kwds;
+  bool ccase = ((const enumARG *)argp)->checkcase;
+  bool unique = ((const enumARG *)argp)->checkunique;
+  unsigned char *bp = (unsigned char *)field_buffer(field, 0);
+  char *s, *t, *p;
+  int res;
+
+  while (kwds && (s = (*kwds++)))
+    {
+      if ((res = Compare((unsigned char *)s, bp, ccase)) != NOMATCH)
+	{
+	  p = t = s;		/* t is at least a partial match */
+	  if ((unique && res != EXACT))
+	    {
+	      while (kwds && (p = *kwds++))
+		{
+		  if ((res = Compare((unsigned char *)p, bp, ccase)) != NOMATCH)
+		    {
+		      if (res == EXACT)
+			{
+			  t = p;
+			  break;
+			}
+		      else
+			t = (char *)0;
+		    }
+		}
+	    }
+	  if (t)
+	    {
+	      set_field_buffer(field, 0, t);
+	      return TRUE;
+	    }
+	  if (!p)
+	    break;
+	}
+    }
+  return FALSE;
+}
+
+static const char *dummy[] =
+{(char *)0};
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static bool Next_Enum(FIELD * field,
+|                                          const void * argp)
+|
+|   Description   :  Check for the next enumeration value
+|
+|   Return Values :  TRUE  - next value found and loaded
+|                    FALSE - no next value loaded
++--------------------------------------------------------------------------*/
+static bool
+Next_Enum(FIELD *field, const void *argp)
+{
+  const enumARG *args = (const enumARG *)argp;
+  char **kwds = args->kwds;
+  bool ccase = args->checkcase;
+  int cnt = args->count;
+  unsigned char *bp = (unsigned char *)field_buffer(field, 0);
+
+  if (kwds)
+    {
+      while (cnt--)
+	{
+	  if (Compare((unsigned char *)(*kwds++), bp, ccase) == EXACT)
+	    break;
+	}
+      if (cnt <= 0)
+	kwds = args->kwds;
+      if ((cnt >= 0) || (Compare((const unsigned char *)dummy, bp, ccase) == EXACT))
+	{
+	  set_field_buffer(field, 0, *kwds);
+	  return TRUE;
+	}
+    }
+  return FALSE;
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static bool Previous_Enum(
+|                                          FIELD * field,
+|                                          const void * argp)
+|
+|   Description   :  Check for the previous enumeration value
+|
+|   Return Values :  TRUE  - previous value found and loaded
+|                    FALSE - no previous value loaded
++--------------------------------------------------------------------------*/
+static bool
+Previous_Enum(FIELD *field, const void *argp)
+{
+  const enumARG *args = (const enumARG *)argp;
+  int cnt = args->count;
+  char **kwds = &args->kwds[cnt - 1];
+  bool ccase = args->checkcase;
+  unsigned char *bp = (unsigned char *)field_buffer(field, 0);
+
+  if (kwds)
+    {
+      while (cnt--)
+	{
+	  if (Compare((unsigned char *)(*kwds--), bp, ccase) == EXACT)
+	    break;
+	}
+
+      if (cnt <= 0)
+	kwds = &args->kwds[args->count - 1];
+
+      if ((cnt >= 0) || (Compare((const unsigned char *)dummy, bp, ccase) == EXACT))
+	{
+	  set_field_buffer(field, 0, *kwds);
+	  return TRUE;
+	}
+    }
+  return FALSE;
+}
+
+static FIELDTYPE typeENUM =
+{
+  _HAS_ARGS | _HAS_CHOICE | _RESIDENT,
+  1,				/* this is mutable, so we can't be const */
+  (FIELDTYPE *)0,
+  (FIELDTYPE *)0,
+  Make_Enum_Type,
+  Copy_Enum_Type,
+  Free_Enum_Type,
+  INIT_FT_FUNC(Check_Enum_Field),
+  INIT_FT_FUNC(NULL),
+  INIT_FT_FUNC(Next_Enum),
+  INIT_FT_FUNC(Previous_Enum),
+#if NCURSES_INTEROP_FUNCS
+  Generic_Enum_Type
+#endif
+};
+
+NCURSES_EXPORT_VAR(FIELDTYPE *)
+TYPE_ENUM = &typeENUM;
+
+#if NCURSES_INTEROP_FUNCS
+/* The next routines are to simplify the use of ncurses from
+   programming languages with restictions on interop with C level
+   constructs (e.g. variable access or va_list + ellipsis constructs)
+*/
+NCURSES_EXPORT(FIELDTYPE *)
+_nc_TYPE_ENUM(void)
+{
+  return TYPE_ENUM;
+}
+#endif
+
+/* fty_enum.c ends here */
diff --git a/apps/lib/curses/pdcurses/form/fty_generic.c b/apps/lib/curses/pdcurses/form/fty_generic.c
new file mode 100644
index 0000000..439afcc
--- /dev/null
+++ b/apps/lib/curses/pdcurses/form/fty_generic.c
@@ -0,0 +1,297 @@
+/****************************************************************************
+ * Copyright (c) 2008-2009,2010 Free Software Foundation, Inc.              *
+ *                                                                          *
+ * 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, distribute with modifications, sublicense, and/or sell       *
+ * copies of the Software, and to permit persons to whom the Software is    *
+ * furnished to do so, subject to the following conditions:                 *
+ *                                                                          *
+ * The above copyright notice and this permission notice shall be included  *
+ * in all copies or substantial portions of the Software.                   *
+ *                                                                          *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
+ * IN NO EVENT SHALL THE ABOVE 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.                               *
+ *                                                                          *
+ * Except as contained in this notice, the name(s) of the above copyright   *
+ * holders shall not be used in advertising or otherwise to promote the     *
+ * sale, use or other dealings in this Software without prior written       *
+ * authorization.                                                           *
+ ****************************************************************************/
+
+/***************************************************************************
+*                                                                          *
+*  Author : Juergen Pfeifer                                                *
+*                                                                          *
+***************************************************************************/
+
+#include "form.priv.h"
+
+MODULE_ID("$Id: fty_generic.c,v 1.5 2010/01/23 21:14:36 tom Exp $")
+
+/*
+ * This is not a full implementation of a field type, but adds some
+ * support for higher level languages with some restrictions to interop
+ * with C language. Especially the collection of arguments for the
+ * various fieldtypes is not based on the vararg C mechanism, but on a
+ * iterator based callback mechanism that allowes the high level language
+ * to provide the arguments as a structure. Most languages have mechanisms
+ * to layout structures so that they can be passed to C.
+ * The languages can register a new generic fieldtype dynamically and store
+ * a handle (key) to the calling object as an argument. Together with that
+ * it can register a freearg callback, so that the high level language
+ * remains in control of the memory management of the arguments they pass.
+ * The design idea is, that the high-level language - typically a OO
+ * language like C# or Java, uses it's own dispatching mechanisms
+ * (polymorphism) to call the proper check routines responsible for the
+ * argument type. So these language implement typically only one generic
+ * fieldtype they register with the forms library using this call.
+ *
+ * For that purpose we have extended the fieldtype struc by a new element
+ * that gets the arguments from a single struct passed by the caller.
+ *
+ */
+#if NCURSES_INTEROP_FUNCS
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static void *Generic_This_Type( void * arg )
+|
+|   Description   :  We interpret the passed arg just as a handle the
+|                    calling language uses to keep track of its allocated
+|                    argument structures. We can simply copy it back.
+|
+|   Return Values :  Pointer to argument structure
++--------------------------------------------------------------------------*/
+static void *
+Generic_This_Type(void *arg)
+{
+  return (arg);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  FIELDTYPE *_nc_generic_fieldtype(
+|                       bool (* const field_check)(FIELD *,const void *),
+|                       bool (* const char_check) (int, const void *),
+|   		        bool (*const next)(FORM*,FIELD*,const void*),
+|		        bool (*const prev)(FORM*,FIELD*,const void*),
+|                       void (*freecallback)(void*))
+|
+|   Description   :  Create a new fieldtype. The application programmer must
+|                    write a field_check and a char_check function and give
+|                    them as input to this call. A callback to allow the
+|                    release of the allocated memory must also be provided.
+|                    For generic field types, we provide some more
+|                    information about the field as parameters.
+|
+|                    If an error occurs, errno is set to
+|                       E_BAD_ARGUMENT  - invalid arguments
+|                       E_SYSTEM_ERROR  - system error (no memory)
+|
+|   Return Values :  Fieldtype pointer or NULL if error occurred
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(FIELDTYPE *)
+_nc_generic_fieldtype(bool (*const field_check) (FORM *, FIELD *, const void *),
+		      bool (*const char_check) (int, FORM *, FIELD *, const
+						void *),
+		      bool (*const next) (FORM *, FIELD *, const void *),
+		      bool (*const prev) (FORM *, FIELD *, const void *),
+		      void (*freecallback) (void *))
+{
+  int code = E_SYSTEM_ERROR;
+  FIELDTYPE *res = (FIELDTYPE *)0;
+
+  T((T_CALLED("_nc_generic_fieldtype(%p,%p,%p,%p,%p)"),
+     field_check, char_check, next, prev, freecallback));
+
+  if (field_check || char_check)
+    {
+      res = typeMalloc(FIELDTYPE, 1);
+
+      if (res)
+	{
+	  *res = *_nc_Default_FieldType;
+	  res->status |= (_HAS_ARGS | _GENERIC);
+	  res->fieldcheck.gfcheck = field_check;
+	  res->charcheck.gccheck = char_check;
+	  res->genericarg = Generic_This_Type;
+	  res->freearg = freecallback;
+	  res->enum_next.gnext = next;
+	  res->enum_prev.gprev = prev;
+	  code = E_OK;
+	}
+    }
+  else
+    code = E_BAD_ARGUMENT;
+
+  if (E_OK != code)
+    SET_ERROR(code);
+
+  returnFieldType(res);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static TypeArgument *GenericArgument(
+|                      const FIELDTYPE* typ,
+|                      int (*argiterator)(void**),
+|                      int* err)
+|
+|   Description   :  The iterator callback must browse through all fieldtype
+|                    parameters that have an argument associated with the
+|                    type. The iterator returns 1 if the operation to get
+|                    the next element was successfull, 0 otherwise. If the
+|                    iterator could move to the next argument, it fills
+|                    the void* pointer representing the argument into the
+|                    location provided as argument to the iterator.
+|                    The err reference is used to keep track of errors.
+|
+|   Return Values :  Pointer to argument structure
++--------------------------------------------------------------------------*/
+static TypeArgument *
+GenericArgument(const FIELDTYPE *typ,
+		int (*argiterator) (void **), int *err)
+{
+  TypeArgument *res = (TypeArgument *)0;
+
+  if (typ != 0 && (typ->status & _HAS_ARGS) != 0 && err != 0 && argiterator != 0)
+    {
+      if (typ->status & _LINKED_TYPE)
+	{
+	  /* Composite fieldtypes keep track internally of their own memory */
+	  TypeArgument *p = typeMalloc(TypeArgument, 1);
+
+	  if (p)
+	    {
+	      p->left = GenericArgument(typ->left, argiterator, err);
+	      p->right = GenericArgument(typ->right, argiterator, err);
+	      return p;
+	    }
+	  else
+	    *err += 1;
+	}
+      else
+	{
+	  assert(typ->genericarg != (void *)0);
+	  if (typ->genericarg == 0)
+	    *err += 1;
+	  else
+	    {
+	      void *argp;
+	      int valid = argiterator(&argp);
+
+	      if (valid == 0 || argp == 0 ||
+		  !(res = (TypeArgument *)typ->genericarg(argp)))
+		{
+		  *err += 1;
+		}
+	    }
+	}
+    }
+  return res;
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  int _nc_set_generic_fieldtype(
+|                      FIELD* field,
+|                      FIELDTYPE* ftyp,
+|                      int (*argiterator)(void**))
+|
+|   Description   :  Assign the fieldtype to the field and use the iterator
+|                    mechanism to get the arguments when a check is
+|                    performed.
+|
+|   Return Values :  E_OK if all went well
+|                    E_SYSTEM_ERROR if an error occurred
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(int)
+_nc_set_generic_fieldtype(FIELD *field,
+			  FIELDTYPE *ftyp,
+			  int (*argiterator) (void **))
+{
+  int code = E_SYSTEM_ERROR;
+  int err = 0;
+
+  if (field)
+    {
+      if (field && field->type)
+	_nc_Free_Type(field);
+
+      field->type = ftyp;
+      if (ftyp)
+	{
+	  if (argiterator)
+	    {
+	      /* The precondition is that the iterator is reset */
+	      field->arg = (void *)GenericArgument(field->type, argiterator, &err);
+
+	      if (err)
+		{
+		  _nc_Free_Argument(field->type, (TypeArgument *)(field->arg));
+		  field->type = (FIELDTYPE *)0;
+		  field->arg = (void *)0;
+		}
+	      else
+		{
+		  code = E_OK;
+		  if (field->type)
+		    field->type->ref++;
+		}
+	    }
+	}
+      else
+	{
+	  field->arg = (void *)0;
+	  code = E_OK;
+	}
+    }
+  return code;
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  WINDOW* _nc_form_cursor(
+|                      FORM* form,
+|                      int *pRow, int *pCol)
+|
+|   Description   :  Get the current position of the form cursor position
+|                    We also return the field window
+|
+|   Return Values :  The fields Window or NULL on error
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(WINDOW *)
+_nc_form_cursor(const FORM *form, int *pRow, int *pCol)
+{
+  int code = E_SYSTEM_ERROR;
+  WINDOW *res = (WINDOW *)0;
+
+  if (!(form == 0 || pRow == 0 || pCol == 0))
+    {
+      *pRow = form->currow;
+      *pCol = form->curcol;
+      res = form->w;
+      code = E_OK;
+    }
+  if (code != E_OK)
+    SET_ERROR(code);
+  return res;
+}
+
+#else
+extern void _nc_fty_generic(void);
+void
+_nc_fty_generic(void)
+{
+}
+#endif
+
+/* fty_generic.c ends here */
diff --git a/apps/lib/curses/pdcurses/form/fty_int.c b/apps/lib/curses/pdcurses/form/fty_int.c
new file mode 100644
index 0000000..0eddedf
--- /dev/null
+++ b/apps/lib/curses/pdcurses/form/fty_int.c
@@ -0,0 +1,293 @@
+/****************************************************************************
+ * Copyright (c) 1998-2009,2010 Free Software Foundation, Inc.              *
+ *                                                                          *
+ * 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, distribute with modifications, sublicense, and/or sell       *
+ * copies of the Software, and to permit persons to whom the Software is    *
+ * furnished to do so, subject to the following conditions:                 *
+ *                                                                          *
+ * The above copyright notice and this permission notice shall be included  *
+ * in all copies or substantial portions of the Software.                   *
+ *                                                                          *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
+ * IN NO EVENT SHALL THE ABOVE 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.                               *
+ *                                                                          *
+ * Except as contained in this notice, the name(s) of the above copyright   *
+ * holders shall not be used in advertising or otherwise to promote the     *
+ * sale, use or other dealings in this Software without prior written       *
+ * authorization.                                                           *
+ ****************************************************************************/
+
+/***************************************************************************
+*                                                                          *
+*  Author : Juergen Pfeifer                                                *
+*                                                                          *
+***************************************************************************/
+
+#include "form.priv.h"
+
+MODULE_ID("$Id: fty_int.c,v 1.25 2010/01/23 21:14:36 tom Exp $")
+
+#if USE_WIDEC_SUPPORT
+#define isDigit(c) (iswdigit((wint_t)(c)) || isdigit(UChar(c)))
+#else
+#define isDigit(c) isdigit(UChar(c))
+#endif
+
+#define thisARG integerARG
+
+typedef struct
+  {
+    int precision;
+    long low;
+    long high;
+  }
+thisARG;
+
+typedef struct
+  {
+    int precision;
+    long low;
+    long high;
+  }
+integerPARM;
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static void *Generic_This_Type( void * arg )
+|
+|   Description   :  Allocate structure for integer type argument.
+|
+|   Return Values :  Pointer to argument structure or NULL on error
++--------------------------------------------------------------------------*/
+static void *
+Generic_This_Type(void *arg)
+{
+  thisARG *argp = (thisARG *) 0;
+  thisARG *param = (thisARG *) arg;
+
+  if (param)
+    {
+      argp = typeMalloc(thisARG, 1);
+
+      if (argp)
+	{
+	  T((T_CREATE("thisARG %p"), (void *)argp));
+	  *argp = *param;
+	}
+    }
+  return (void *)argp;
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static void *Make_This_Type( va_list * ap )
+|
+|   Description   :  Allocate structure for integer type argument.
+|
+|   Return Values :  Pointer to argument structure or NULL on error
++--------------------------------------------------------------------------*/
+static void *
+Make_This_Type(va_list *ap)
+{
+  thisARG arg;
+
+  arg.precision = va_arg(*ap, int);
+  arg.low = va_arg(*ap, long);
+  arg.high = va_arg(*ap, long);
+
+  return Generic_This_Type((void *)&arg);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static void *Copy_This_Type(const void * argp)
+|
+|   Description   :  Copy structure for integer type argument.
+|
+|   Return Values :  Pointer to argument structure or NULL on error.
++--------------------------------------------------------------------------*/
+static void *
+Copy_This_Type(const void *argp)
+{
+  const thisARG *ap = (const thisARG *)argp;
+  thisARG *result = (thisARG *) 0;
+
+  if (argp)
+    {
+      result = typeMalloc(thisARG, 1);
+      if (result)
+	{
+	  T((T_CREATE("thisARG %p"), (void *)result));
+	  *result = *ap;
+	}
+    }
+  return (void *)result;
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static void Free_This_Type(void * argp)
+|
+|   Description   :  Free structure for integer type argument.
+|
+|   Return Values :  -
++--------------------------------------------------------------------------*/
+static void
+Free_This_Type(void *argp)
+{
+  if (argp)
+    free(argp);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static bool Check_This_Field(
+|                                                 FIELD * field,
+|                                                 const void * argp)
+|
+|   Description   :  Validate buffer content to be a valid integer value
+|
+|   Return Values :  TRUE  - field is valid
+|                    FALSE - field is invalid
++--------------------------------------------------------------------------*/
+static bool
+Check_This_Field(FIELD *field, const void *argp)
+{
+  const thisARG *argi = (const thisARG *)argp;
+  long low = argi->low;
+  long high = argi->high;
+  int prec = argi->precision;
+  unsigned char *bp = (unsigned char *)field_buffer(field, 0);
+  char *s = (char *)bp;
+  long val;
+  char buf[100];
+  bool result = FALSE;
+
+  while (*bp && *bp == ' ')
+    bp++;
+  if (*bp)
+    {
+      if (*bp == '-')
+	bp++;
+#if USE_WIDEC_SUPPORT
+      if (*bp)
+	{
+	  bool blank = FALSE;
+	  int len;
+	  int n;
+	  wchar_t *list = _nc_Widen_String((char *)bp, &len);
+
+	  if (list != 0)
+	    {
+	      result = TRUE;
+	      for (n = 0; n < len; ++n)
+		{
+		  if (blank)
+		    {
+		      if (list[n] != ' ')
+			{
+			  result = FALSE;
+			  break;
+			}
+		    }
+		  else if (list[n] == ' ')
+		    {
+		      blank = TRUE;
+		    }
+		  else if (!isDigit(list[n]))
+		    {
+		      result = FALSE;
+		      break;
+		    }
+		}
+	      free(list);
+	    }
+	}
+#else
+      while (*bp)
+	{
+	  if (!isdigit(UChar(*bp)))
+	    break;
+	  bp++;
+	}
+      while (*bp && *bp == ' ')
+	bp++;
+      result = (*bp == '\0');
+#endif
+      if (result)
+	{
+	  val = atol(s);
+	  if (low < high)
+	    {
+	      if (val < low || val > high)
+		result = FALSE;
+	    }
+	  if (result)
+	    {
+	      sprintf(buf, "%.*ld", (prec > 0 ? prec : 0), val);
+	      set_field_buffer(field, 0, buf);
+	    }
+	}
+    }
+  return (result);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static bool Check_This_Character(
+|                                      int c,
+|                                      const void * argp)
+|
+|   Description   :  Check a character for the integer type.
+|
+|   Return Values :  TRUE  - character is valid
+|                    FALSE - character is invalid
++--------------------------------------------------------------------------*/
+static bool
+Check_This_Character(int c, const void *argp GCC_UNUSED)
+{
+  return ((isDigit(UChar(c)) || (c == '-')) ? TRUE : FALSE);
+}
+
+static FIELDTYPE typeTHIS =
+{
+  _HAS_ARGS | _RESIDENT,
+  1,				/* this is mutable, so we can't be const */
+  (FIELDTYPE *)0,
+  (FIELDTYPE *)0,
+  Make_This_Type,
+  Copy_This_Type,
+  Free_This_Type,
+  INIT_FT_FUNC(Check_This_Field),
+  INIT_FT_FUNC(Check_This_Character),
+  INIT_FT_FUNC(NULL),
+  INIT_FT_FUNC(NULL),
+#if NCURSES_INTEROP_FUNCS
+  Generic_This_Type
+#endif
+};
+
+NCURSES_EXPORT_VAR(FIELDTYPE*) TYPE_INTEGER = &typeTHIS;
+
+#if NCURSES_INTEROP_FUNCS
+/* The next routines are to simplify the use of ncurses from
+   programming languages with restictions on interop with C level
+   constructs (e.g. variable access or va_list + ellipsis constructs)
+*/
+NCURSES_EXPORT(FIELDTYPE *)
+_nc_TYPE_INTEGER(void)
+{
+  return TYPE_INTEGER;
+}
+#endif
+
+/* fty_int.c ends here */
diff --git a/apps/lib/curses/pdcurses/form/fty_ipv4.c b/apps/lib/curses/pdcurses/form/fty_ipv4.c
new file mode 100644
index 0000000..3def259
--- /dev/null
+++ b/apps/lib/curses/pdcurses/form/fty_ipv4.c
@@ -0,0 +1,120 @@
+/****************************************************************************
+ * Copyright (c) 1998-2006,2009 Free Software Foundation, Inc.              *
+ *                                                                          *
+ * 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, distribute with modifications, sublicense, and/or sell       *
+ * copies of the Software, and to permit persons to whom the Software is    *
+ * furnished to do so, subject to the following conditions:                 *
+ *                                                                          *
+ * The above copyright notice and this permission notice shall be included  *
+ * in all copies or substantial portions of the Software.                   *
+ *                                                                          *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
+ * IN NO EVENT SHALL THE ABOVE 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.                               *
+ *                                                                          *
+ * Except as contained in this notice, the name(s) of the above copyright   *
+ * holders shall not be used in advertising or otherwise to promote the     *
+ * sale, use or other dealings in this Software without prior written       *
+ * authorization.                                                           *
+ ****************************************************************************/
+
+/***************************************************************************
+*                                                                          *
+*  Author : Per Foreby, perf@efd.lth.se                                    *
+*                                                                          *
+***************************************************************************/
+
+#include "form.priv.h"
+
+MODULE_ID("$Id: fty_ipv4.c,v 1.10 2009/11/07 20:17:58 tom Exp $")
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static bool Check_IPV4_Field(
+|                                      FIELD * field,
+|                                      const void * argp)
+|
+|   Description   :  Validate buffer content to be a valid IP number (Ver. 4)
+|
+|   Return Values :  TRUE  - field is valid
+|                    FALSE - field is invalid
++--------------------------------------------------------------------------*/
+static bool
+Check_IPV4_Field(FIELD *field, const void *argp GCC_UNUSED)
+{
+  char *bp = field_buffer(field, 0);
+  int num = 0, len;
+  unsigned int d1, d2, d3, d4;
+
+  if (isdigit(UChar(*bp)))	/* Must start with digit */
+    {
+      num = sscanf(bp, "%u.%u.%u.%u%n", &d1, &d2, &d3, &d4, &len);
+      if (num == 4)
+	{
+	  bp += len;		/* Make bp point to what sscanf() left */
+	  while (isspace(UChar(*bp)))
+	    bp++;		/* Allow trailing whitespace */
+	}
+    }
+  return ((num != 4 || *bp || d1 > 255 || d2 > 255
+	   || d3 > 255 || d4 > 255) ? FALSE : TRUE);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static bool Check_IPV4_Character(
+|                                      int c,
+|                                      const void *argp )
+|
+|   Description   :  Check a character for unsigned type or period.
+|
+|   Return Values :  TRUE  - character is valid
+|                    FALSE - character is invalid
++--------------------------------------------------------------------------*/
+static bool
+Check_IPV4_Character(int c, const void *argp GCC_UNUSED)
+{
+  return ((isdigit(UChar(c)) || (c == '.')) ? TRUE : FALSE);
+}
+
+static FIELDTYPE typeIPV4 =
+{
+  _RESIDENT,
+  1,				/* this is mutable, so we can't be const */
+  (FIELDTYPE *)0,
+  (FIELDTYPE *)0,
+  NULL,
+  NULL,
+  NULL,
+  INIT_FT_FUNC(Check_IPV4_Field),
+  INIT_FT_FUNC(Check_IPV4_Character),
+  INIT_FT_FUNC(NULL),
+  INIT_FT_FUNC(NULL),
+#if NCURSES_INTEROP_FUNCS
+  NULL
+#endif
+};
+
+NCURSES_EXPORT_VAR(FIELDTYPE*) TYPE_IPV4 = &typeIPV4;
+
+#if NCURSES_INTEROP_FUNCS
+/* The next routines are to simplify the use of ncurses from
+   programming languages with restictions on interop with C level
+   constructs (e.g. variable access or va_list + ellipsis constructs)
+*/
+NCURSES_EXPORT(FIELDTYPE *)
+_nc_TYPE_IPV4(void)
+{
+  return TYPE_IPV4;
+}
+#endif
+
+/* fty_ipv4.c ends here */
diff --git a/apps/lib/curses/pdcurses/form/fty_num.c b/apps/lib/curses/pdcurses/form/fty_num.c
new file mode 100644
index 0000000..4bd7132
--- /dev/null
+++ b/apps/lib/curses/pdcurses/form/fty_num.c
@@ -0,0 +1,339 @@
+/****************************************************************************
+ * Copyright (c) 1998-2009,2010 Free Software Foundation, Inc.              *
+ *                                                                          *
+ * 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, distribute with modifications, sublicense, and/or sell       *
+ * copies of the Software, and to permit persons to whom the Software is    *
+ * furnished to do so, subject to the following conditions:                 *
+ *                                                                          *
+ * The above copyright notice and this permission notice shall be included  *
+ * in all copies or substantial portions of the Software.                   *
+ *                                                                          *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
+ * IN NO EVENT SHALL THE ABOVE 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.                               *
+ *                                                                          *
+ * Except as contained in this notice, the name(s) of the above copyright   *
+ * holders shall not be used in advertising or otherwise to promote the     *
+ * sale, use or other dealings in this Software without prior written       *
+ * authorization.                                                           *
+ ****************************************************************************/
+
+/***************************************************************************
+*                                                                          *
+*  Author : Juergen Pfeifer                                                *
+*                                                                          *
+***************************************************************************/
+
+#include "form.priv.h"
+
+MODULE_ID("$Id: fty_num.c,v 1.28 2010/01/23 21:14:36 tom Exp $")
+
+#if HAVE_LOCALE_H
+#include <locale.h>
+#endif
+
+#if HAVE_LOCALE_H
+#define isDecimalPoint(c) ((c) == ((L && L->decimal_point) ? *(L->decimal_point) : '.'))
+#else
+#define isDecimalPoint(c) ((c) == '.')
+#endif
+
+#if USE_WIDEC_SUPPORT
+#define isDigit(c) (iswdigit((wint_t)(c)) || isdigit(UChar(c)))
+#else
+#define isDigit(c) isdigit(UChar(c))
+#endif
+
+#define thisARG numericARG
+
+typedef struct
+  {
+    int precision;
+    double low;
+    double high;
+    struct lconv *L;
+  }
+thisARG;
+
+typedef struct
+  {
+    int precision;
+    double low;
+    double high;
+  }
+thisPARM;
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static void *Generic_This_Type(void * arg)
+|
+|   Description   :  Allocate structure for numeric type argument.
+|
+|   Return Values :  Pointer to argument structure or NULL on error
++--------------------------------------------------------------------------*/
+static void *
+Generic_This_Type(void *arg)
+{
+  thisARG *argn = (thisARG *) 0;
+  thisPARM *args = (thisPARM *) arg;
+
+  if (args)
+    {
+      argn = typeMalloc(thisARG, 1);
+
+      if (argn)
+	{
+	  T((T_CREATE("thisARG %p"), (void *)argn));
+	  argn->precision = args->precision;
+	  argn->low = args->low;
+	  argn->high = args->high;
+
+#if HAVE_LOCALE_H
+	  argn->L = localeconv();
+#else
+	  argn->L = NULL;
+#endif
+	}
+    }
+  return (void *)argn;
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static void *Make_This_Type(va_list * ap)
+|
+|   Description   :  Allocate structure for numeric type argument.
+|
+|   Return Values :  Pointer to argument structure or NULL on error
++--------------------------------------------------------------------------*/
+static void *
+Make_This_Type(va_list *ap)
+{
+  thisPARM arg;
+
+  arg.precision = va_arg(*ap, int);
+  arg.low = va_arg(*ap, double);
+  arg.high = va_arg(*ap, double);
+
+  return Generic_This_Type((void *)&arg);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static void *Copy_This_Type(const void * argp)
+|
+|   Description   :  Copy structure for numeric type argument.
+|
+|   Return Values :  Pointer to argument structure or NULL on error.
++--------------------------------------------------------------------------*/
+static void *
+Copy_This_Type(const void *argp)
+{
+  const thisARG *ap = (const thisARG *)argp;
+  thisARG *result = (thisARG *) 0;
+
+  if (argp)
+    {
+      result = typeMalloc(thisARG, 1);
+      if (result)
+	{
+	  T((T_CREATE("thisARG %p"), (void *)result));
+	  *result = *ap;
+	}
+    }
+  return (void *)result;
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static void Free_This_Type(void * argp)
+|
+|   Description   :  Free structure for numeric type argument.
+|
+|   Return Values :  -
++--------------------------------------------------------------------------*/
+static void
+Free_This_Type(void *argp)
+{
+  if (argp)
+    free(argp);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static bool Check_This_Field(FIELD * field,
+|                                                 const void * argp)
+|
+|   Description   :  Validate buffer content to be a valid numeric value
+|
+|   Return Values :  TRUE  - field is valid
+|                    FALSE - field is invalid
++--------------------------------------------------------------------------*/
+static bool
+Check_This_Field(FIELD *field, const void *argp)
+{
+  const thisARG *argn = (const thisARG *)argp;
+  double low = argn->low;
+  double high = argn->high;
+  int prec = argn->precision;
+  unsigned char *bp = (unsigned char *)field_buffer(field, 0);
+  char *s = (char *)bp;
+  double val = 0.0;
+  struct lconv *L = argn->L;
+  char buf[64];
+  bool result = FALSE;
+
+  while (*bp && *bp == ' ')
+    bp++;
+  if (*bp)
+    {
+      if (*bp == '-' || *bp == '+')
+	bp++;
+#if USE_WIDEC_SUPPORT
+      if (*bp)
+	{
+	  bool blank = FALSE;
+	  int state = 0;
+	  int len;
+	  int n;
+	  wchar_t *list = _nc_Widen_String((char *)bp, &len);
+
+	  if (list != 0)
+	    {
+	      result = TRUE;
+	      for (n = 0; n < len; ++n)
+		{
+		  if (blank)
+		    {
+		      if (list[n] != ' ')
+			{
+			  result = FALSE;
+			  break;
+			}
+		    }
+		  else if (list[n] == ' ')
+		    {
+		      blank = TRUE;
+		    }
+		  else if (isDecimalPoint(list[n]))
+		    {
+		      if (++state > 1)
+			{
+			  result = FALSE;
+			  break;
+			}
+		    }
+		  else if (!isDigit(list[n]))
+		    {
+		      result = FALSE;
+		      break;
+		    }
+		}
+	      free(list);
+	    }
+	}
+#else
+      while (*bp)
+	{
+	  if (!isdigit(UChar(*bp)))
+	    break;
+	  bp++;
+	}
+      if (isDecimalPoint(*bp))
+	{
+	  bp++;
+	  while (*bp)
+	    {
+	      if (!isdigit(UChar(*bp)))
+		break;
+	      bp++;
+	    }
+	}
+      while (*bp && *bp == ' ')
+	bp++;
+      result = (*bp == '\0');
+#endif
+      if (result)
+	{
+	  val = atof(s);
+	  if (low < high)
+	    {
+	      if (val < low || val > high)
+		result = FALSE;
+	    }
+	  if (result)
+	    {
+	      sprintf(buf, "%.*f", (prec > 0 ? prec : 0), val);
+	      set_field_buffer(field, 0, buf);
+	    }
+	}
+    }
+  return (result);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static bool Check_This_Character(
+|                                      int c,
+|                                      const void * argp)
+|
+|   Description   :  Check a character for the numeric type.
+|
+|   Return Values :  TRUE  - character is valid
+|                    FALSE - character is invalid
++--------------------------------------------------------------------------*/
+static bool
+Check_This_Character(int c, const void *argp)
+{
+  const thisARG *argn = (const thisARG *)argp;
+  struct lconv *L = argn->L;
+
+  return ((isDigit(c) ||
+	   c == '+' ||
+	   c == '-' ||
+	   isDecimalPoint(c))
+	  ? TRUE
+	  : FALSE);
+}
+
+static FIELDTYPE typeTHIS =
+{
+  _HAS_ARGS | _RESIDENT,
+  1,				/* this is mutable, so we can't be const */
+  (FIELDTYPE *)0,
+  (FIELDTYPE *)0,
+  Make_This_Type,
+  Copy_This_Type,
+  Free_This_Type,
+  INIT_FT_FUNC(Check_This_Field),
+  INIT_FT_FUNC(Check_This_Character),
+  INIT_FT_FUNC(NULL),
+  INIT_FT_FUNC(NULL),
+#if NCURSES_INTEROP_FUNCS
+  Generic_This_Type
+#endif
+};
+
+NCURSES_EXPORT_VAR(FIELDTYPE*) TYPE_NUMERIC = &typeTHIS;
+
+#if NCURSES_INTEROP_FUNCS
+/* The next routines are to simplify the use of ncurses from
+   programming languages with restictions on interop with C level
+   constructs (e.g. variable access or va_list + ellipsis constructs)
+*/
+NCURSES_EXPORT(FIELDTYPE *)
+_nc_TYPE_NUMERIC(void)
+{
+  return TYPE_NUMERIC;
+}
+#endif
+
+/* fty_num.c ends here */
diff --git a/apps/lib/curses/pdcurses/form/fty_regex.c b/apps/lib/curses/pdcurses/form/fty_regex.c
new file mode 100644
index 0000000..2c0a4ca
--- /dev/null
+++ b/apps/lib/curses/pdcurses/form/fty_regex.c
@@ -0,0 +1,350 @@
+/****************************************************************************
+ * Copyright (c) 1998-2009,2010 Free Software Foundation, Inc.              *
+ *                                                                          *
+ * 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, distribute with modifications, sublicense, and/or sell       *
+ * copies of the Software, and to permit persons to whom the Software is    *
+ * furnished to do so, subject to the following conditions:                 *
+ *                                                                          *
+ * The above copyright notice and this permission notice shall be included  *
+ * in all copies or substantial portions of the Software.                   *
+ *                                                                          *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
+ * IN NO EVENT SHALL THE ABOVE 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.                               *
+ *                                                                          *
+ * Except as contained in this notice, the name(s) of the above copyright   *
+ * holders shall not be used in advertising or otherwise to promote the     *
+ * sale, use or other dealings in this Software without prior written       *
+ * authorization.                                                           *
+ ****************************************************************************/
+
+/***************************************************************************
+*                                                                          *
+*  Author : Juergen Pfeifer                                                *
+*                                                                          *
+***************************************************************************/
+
+#include "form.priv.h"
+
+MODULE_ID("$Id: fty_regex.c,v 1.24 2010/01/23 21:14:37 tom Exp $")
+
+#if HAVE_REGEX_H_FUNCS		/* We prefer POSIX regex */
+#include <regex.h>
+
+typedef struct
+  {
+    regex_t *pRegExp;
+    unsigned long *refCount;
+  }
+RegExp_Arg;
+
+#elif HAVE_REGEXP_H_FUNCS | HAVE_REGEXPR_H_FUNCS
+#undef RETURN
+static int reg_errno;
+
+static char *
+RegEx_Init(char *instring)
+{
+  reg_errno = 0;
+  return instring;
+}
+
+static char *
+RegEx_Error(int code)
+{
+  reg_errno = code;
+  return 0;
+}
+
+#define INIT 		register char *sp = RegEx_Init(instring);
+#define GETC()		(*sp++)
+#define PEEKC()		(*sp)
+#define UNGETC(c)	(--sp)
+#define RETURN(c)	return(c)
+#define ERROR(c)	return RegEx_Error(c)
+
+#if HAVE_REGEXP_H_FUNCS
+#include <regexp.h>
+#else
+#include <regexpr.h>
+#endif
+
+typedef struct
+{
+  char *compiled_expression;
+  unsigned long *refCount;
+}
+RegExp_Arg;
+
+/* Maximum Length we allow for a compiled regular expression */
+#define MAX_RX_LEN   (2048)
+#define RX_INCREMENT (256)
+
+#endif
+
+#if HAVE_REGEX_H_FUNCS | HAVE_REGEXP_H_FUNCS | HAVE_REGEXPR_H_FUNCS
+# define MAYBE_UNUSED
+#else
+# define MAYBE_UNUSED GCC_UNUSED
+#endif
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static void *Generic_RegularExpression_Type(void * arg)
+|
+|   Description   :  Allocate structure for regex type argument.
+|
+|   Return Values :  Pointer to argument structure or NULL on error
++--------------------------------------------------------------------------*/
+static void *
+Generic_RegularExpression_Type(void *arg MAYBE_UNUSED)
+{
+#if HAVE_REGEX_H_FUNCS
+  char *rx = (char *)arg;
+  RegExp_Arg *preg = (RegExp_Arg *)0;
+
+  if (rx)
+    {
+      preg = typeMalloc(RegExp_Arg, 1);
+
+      if (preg)
+	{
+	  T((T_CREATE("RegExp_Arg %p"), (void *)preg));
+	  if (((preg->pRegExp = typeMalloc(regex_t, 1)) != 0)
+	      && !regcomp(preg->pRegExp, rx,
+			  (REG_EXTENDED | REG_NOSUB | REG_NEWLINE)))
+	    {
+	      T((T_CREATE("regex_t %p"), (void *)preg->pRegExp));
+	      preg->refCount = typeMalloc(unsigned long, 1);
+
+	      *(preg->refCount) = 1;
+	    }
+	  else
+	    {
+	      if (preg->pRegExp)
+		free(preg->pRegExp);
+	      free(preg);
+	      preg = (RegExp_Arg *)0;
+	    }
+	}
+    }
+  return ((void *)preg);
+#elif HAVE_REGEXP_H_FUNCS | HAVE_REGEXPR_H_FUNCS
+  char *rx = (char *)arg;
+  RegExp_Arg *pArg = (RegExp_Arg *)0;
+
+  if (rx)
+    {
+      pArg = typeMalloc(RegExp_Arg, 1);
+
+      if (pArg)
+	{
+	  int blen = RX_INCREMENT;
+
+	  T((T_CREATE("RegExp_Arg %p"), pArg));
+	  pArg->compiled_expression = NULL;
+	  pArg->refCount = typeMalloc(unsigned long, 1);
+
+	  *(pArg->refCount) = 1;
+
+	  do
+	    {
+	      char *buf = typeMalloc(char, blen);
+
+	      if (buf)
+		{
+#if HAVE_REGEXP_H_FUNCS
+		  char *last_pos = compile(rx, buf, &buf[blen], '\0');
+
+#else /* HAVE_REGEXPR_H_FUNCS */
+		  char *last_pos = compile(rx, buf, &buf[blen]);
+#endif
+		  if (reg_errno)
+		    {
+		      free(buf);
+		      if (reg_errno == 50)
+			blen += RX_INCREMENT;
+		      else
+			{
+			  free(pArg);
+			  pArg = NULL;
+			  break;
+			}
+		    }
+		  else
+		    {
+		      pArg->compiled_expression = buf;
+		      break;
+		    }
+		}
+	    }
+	  while (blen <= MAX_RX_LEN);
+	}
+      if (pArg && !pArg->compiled_expression)
+	{
+	  free(pArg);
+	  pArg = NULL;
+	}
+    }
+  return (void *)pArg;
+#else
+  return 0;
+#endif
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static void *Make_RegularExpression_Type(va_list * ap)
+|
+|   Description   :  Allocate structure for regex type argument.
+|
+|   Return Values :  Pointer to argument structure or NULL on error
++--------------------------------------------------------------------------*/
+static void *
+Make_RegularExpression_Type(va_list *ap)
+{
+  char *rx = va_arg(*ap, char *);
+
+  return Generic_RegularExpression_Type((void *)rx);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static void *Copy_RegularExpression_Type(
+|                                      const void * argp)
+|
+|   Description   :  Copy structure for regex type argument.
+|
+|   Return Values :  Pointer to argument structure or NULL on error.
++--------------------------------------------------------------------------*/
+static void *
+Copy_RegularExpression_Type(const void *argp MAYBE_UNUSED)
+{
+#if (HAVE_REGEX_H_FUNCS | HAVE_REGEXP_H_FUNCS | HAVE_REGEXPR_H_FUNCS)
+  const RegExp_Arg *ap = (const RegExp_Arg *)argp;
+  const RegExp_Arg *result = (const RegExp_Arg *)0;
+
+  if (ap)
+    {
+      *(ap->refCount) += 1;
+      result = ap;
+    }
+  return (void *)result;
+#else
+  return 0;
+#endif
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static void Free_RegularExpression_Type(void * argp)
+|
+|   Description   :  Free structure for regex type argument.
+|
+|   Return Values :  -
++--------------------------------------------------------------------------*/
+static void
+Free_RegularExpression_Type(void *argp MAYBE_UNUSED)
+{
+#if HAVE_REGEX_H_FUNCS | HAVE_REGEXP_H_FUNCS | HAVE_REGEXPR_H_FUNCS
+  RegExp_Arg *ap = (RegExp_Arg *)argp;
+
+  if (ap)
+    {
+      if (--(*(ap->refCount)) == 0)
+	{
+#if HAVE_REGEX_H_FUNCS
+	  if (ap->pRegExp)
+	    {
+	      free(ap->refCount);
+	      regfree(ap->pRegExp);
+	    }
+#elif HAVE_REGEXP_H_FUNCS | HAVE_REGEXPR_H_FUNCS
+	  if (ap->compiled_expression)
+	    {
+	      free(ap->refCount);
+	      free(ap->compiled_expression);
+	    }
+#endif
+	  free(ap);
+	}
+    }
+#endif
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static bool Check_RegularExpression_Field(
+|                                      FIELD * field,
+|                                      const void  * argp)
+|
+|   Description   :  Validate buffer content to be a valid regular expression
+|
+|   Return Values :  TRUE  - field is valid
+|                    FALSE - field is invalid
++--------------------------------------------------------------------------*/
+static bool
+Check_RegularExpression_Field(FIELD *field MAYBE_UNUSED,
+			      const void *argp MAYBE_UNUSED)
+{
+  bool match = FALSE;
+
+#if HAVE_REGEX_H_FUNCS
+  const RegExp_Arg *ap = (const RegExp_Arg *)argp;
+
+  if (ap && ap->pRegExp)
+    match = (regexec(ap->pRegExp, field_buffer(field, 0), 0, NULL, 0)
+	     ? FALSE
+	     : TRUE);
+#elif HAVE_REGEXP_H_FUNCS | HAVE_REGEXPR_H_FUNCS
+  RegExp_Arg *ap = (RegExp_Arg *)argp;
+
+  if (ap && ap->compiled_expression)
+    match = (step(field_buffer(field, 0), ap->compiled_expression)
+	     ? TRUE
+	     : FALSE);
+#endif
+  return match;
+}
+
+static FIELDTYPE typeREGEXP =
+{
+  _HAS_ARGS | _RESIDENT,
+  1,				/* this is mutable, so we can't be const */
+  (FIELDTYPE *)0,
+  (FIELDTYPE *)0,
+  Make_RegularExpression_Type,
+  Copy_RegularExpression_Type,
+  Free_RegularExpression_Type,
+  INIT_FT_FUNC(Check_RegularExpression_Field),
+  INIT_FT_FUNC(NULL),
+  INIT_FT_FUNC(NULL),
+  INIT_FT_FUNC(NULL),
+#if NCURSES_INTEROP_FUNCS
+  Generic_RegularExpression_Type
+#endif
+};
+
+NCURSES_EXPORT_VAR(FIELDTYPE*) TYPE_REGEXP = &typeREGEXP;
+
+#if NCURSES_INTEROP_FUNCS
+/* The next routines are to simplify the use of ncurses from
+   programming languages with restictions on interop with C level
+   constructs (e.g. variable access or va_list + ellipsis constructs)
+*/
+NCURSES_EXPORT(FIELDTYPE *)
+_nc_TYPE_REGEXP(void)
+{
+  return TYPE_REGEXP;
+}
+#endif
+
+/* fty_regex.c ends here */
-- 
1.7.10.4


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH 17/20] app: curses: add menu example
  2013-03-06  9:29 ` [PATCH 01/20] Makefile: x_flags prepare for apps support Jean-Christophe PLAGNIOL-VILLARD
                     ` (14 preceding siblings ...)
  2013-03-06  9:29   ` [PATCH 16/20] app: pdcurses: add libform Jean-Christophe PLAGNIOL-VILLARD
@ 2013-03-06  9:29   ` Jean-Christophe PLAGNIOL-VILLARD
  2013-03-06  9:29   ` [PATCH 18/20] app: curses: add panel example Jean-Christophe PLAGNIOL-VILLARD
                     ` (2 subsequent siblings)
  18 siblings, 0 replies; 31+ messages in thread
From: Jean-Christophe PLAGNIOL-VILLARD @ 2013-03-06  9:29 UTC (permalink / raw)
  To: barebox

Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
---
 apps/Kconfig              |    4 ++
 apps/Makefile             |    1 +
 apps/menu_curses/Makefile |   11 ++++
 apps/menu_curses/main.c   |  127 +++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 143 insertions(+)
 create mode 100644 apps/menu_curses/Makefile
 create mode 100644 apps/menu_curses/main.c

diff --git a/apps/Kconfig b/apps/Kconfig
index 7c0b79e..e47f0c2 100644
--- a/apps/Kconfig
+++ b/apps/Kconfig
@@ -45,4 +45,8 @@ config APP_TEST_CURSES
 	bool "test curses"
 	select APP_LIB_CURSES
 
+config APP_TEST_CURSES_MENU
+	bool "test curses menu"
+	depends on APP_LIB_MENU
+
 endif
diff --git a/apps/Makefile b/apps/Makefile
index 3a222d3..47938ec 100644
--- a/apps/Makefile
+++ b/apps/Makefile
@@ -7,6 +7,7 @@ export APP_CPPFLAGS
 
 apps-$(CONFIG_APP_EXAMPLE) += example
 apps-$(CONFIG_APP_TEST_CURSES) += test_curses
+apps-$(CONFIG_APP_TEST_CURSES_MENU) += menu_curses
 
 $(obj)/application: $(apps-lds) $(apps-y)
 
diff --git a/apps/menu_curses/Makefile b/apps/menu_curses/Makefile
new file mode 100644
index 0000000..32c1a04
--- /dev/null
+++ b/apps/menu_curses/Makefile
@@ -0,0 +1,11 @@
+targets := menu_curses.map
+
+# Make sure files are removed during clean
+extra-y       += menu_curses.map
+
+app-y += main.o
+app-final-y = menu_curses
+
+OBJCOPYFLAGS_menu_curses.app = -O binary
+LDFLAGS_apps	:= -Map $(obj)/menu_curses.map
+LDFLAGS_apps	+= -static --gc-sections
diff --git a/apps/menu_curses/main.c b/apps/menu_curses/main.c
new file mode 100644
index 0000000..5b62caa
--- /dev/null
+++ b/apps/menu_curses/main.c
@@ -0,0 +1,127 @@
+#include <string.h>
+#include <malloc.h>
+#include <curses.h>
+#include <menu.h>
+
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
+#define CTRLD 	4
+
+char *choices[] = {
+			"Choice 1",
+			"Choice 2",
+			"Choice 3",
+			"Choice 4",
+			"Choice 5",
+			"Choice 6",
+			"Choice 7",
+			"Choice 8",
+			"Choice 9",
+			"Choice 10",
+			"Exit",
+			(char *)NULL,
+			};
+void print_in_middle(WINDOW *win, int starty, int startx, int width, char *string, chtype color);
+
+int main(int argc, char **argv)
+{	ITEM **my_items;
+	int c;
+	MENU *my_menu;
+	WINDOW *my_menu_win;
+	int n_choices, i;
+
+	/* Initialize curses */
+	initscr();
+	start_color();
+	cbreak();
+	noecho();
+	keypad(stdscr, TRUE);
+	init_pair(1, COLOR_RED, COLOR_BLACK);
+	init_pair(2, COLOR_CYAN, COLOR_BLACK);
+
+	/* Create items */
+	n_choices = ARRAY_SIZE(choices);
+	my_items = (ITEM **)calloc(n_choices, sizeof(ITEM *));
+	for(i = 0; i < n_choices; ++i)
+		my_items[i] = new_item(choices[i], choices[i]);
+
+	/* Crate menu */
+	my_menu = new_menu((ITEM **)my_items);
+
+	/* Create the window to be associated with the menu */
+	my_menu_win = newwin(10, 40, 4, 4);
+	keypad(my_menu_win, TRUE);
+
+	/* Set main window and sub window */
+	set_menu_win(my_menu, my_menu_win);
+	set_menu_sub(my_menu, derwin(my_menu_win, 6, 38, 3, 1));
+	set_menu_format(my_menu, 5, 1);
+
+	/* Set menu mark to the string " * " */
+	set_menu_mark(my_menu, " * ");
+
+	/* Print a border around the main window and print a title */
+	box(my_menu_win, 0, 0);
+	print_in_middle(my_menu_win, 1, 0, 40, "My Menu", COLOR_PAIR(1));
+	mvwaddch(my_menu_win, 2, 0, ACS_LTEE);
+	mvwhline(my_menu_win, 2, 1, ACS_HLINE, 38);
+	mvwaddch(my_menu_win, 2, 39, ACS_RTEE);
+
+	/* Post the menu */
+	post_menu(my_menu);
+	wrefresh(my_menu_win);
+
+	attron(COLOR_PAIR(2));
+	mvprintw(LINES - 2, 0, "Use PageUp and PageDown to scoll down or up a page of items");
+	mvprintw(LINES - 1, 0, "Arrow Keys to navigate (F1 to Exit)");
+	attroff(COLOR_PAIR(2));
+	refresh();
+
+	while((c = wgetch(my_menu_win)) != KEY_F(1)) {
+		switch(c) {
+		case KEY_DOWN:
+			menu_driver(my_menu, REQ_DOWN_ITEM);
+			break;
+		case KEY_UP:
+			menu_driver(my_menu, REQ_UP_ITEM);
+			break;
+		case KEY_NPAGE:
+			menu_driver(my_menu, REQ_SCR_DPAGE);
+			break;
+		case KEY_PPAGE:
+			menu_driver(my_menu, REQ_SCR_UPAGE);
+			break;
+		}
+		wrefresh(my_menu_win);
+	}
+
+	/* Unpost and free all the memory taken up */
+	unpost_menu(my_menu);
+	free_menu(my_menu);
+	for(i = 0; i < n_choices; ++i)
+		free_item(my_items[i]);
+	endwin();
+	return 0;
+}
+
+void print_in_middle(WINDOW *win, int starty, int startx, int width, char *string, chtype color)
+{	int length, x, y;
+	float temp;
+
+	if(win == NULL)
+		win = stdscr;
+	getyx(win, y, x);
+	if(startx != 0)
+		x = startx;
+	if(starty != 0)
+		y = starty;
+	if(width == 0)
+		width = 80;
+
+	length = strlen(string);
+	temp = (width - length)/ 2;
+	x = startx + (int)temp;
+	wattron(win, color);
+	mvwprintw(win, y, x, "%s", string);
+	wattroff(win, color);
+	refresh();
+}
-- 
1.7.10.4


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH 18/20] app: curses: add panel example
  2013-03-06  9:29 ` [PATCH 01/20] Makefile: x_flags prepare for apps support Jean-Christophe PLAGNIOL-VILLARD
                     ` (15 preceding siblings ...)
  2013-03-06  9:29   ` [PATCH 17/20] app: curses: add menu example Jean-Christophe PLAGNIOL-VILLARD
@ 2013-03-06  9:29   ` Jean-Christophe PLAGNIOL-VILLARD
  2013-03-06  9:29   ` [PATCH 19/20] app: curses: add form example Jean-Christophe PLAGNIOL-VILLARD
  2013-03-06  9:29   ` [PATCH 20/20] highbank: enable application support Jean-Christophe PLAGNIOL-VILLARD
  18 siblings, 0 replies; 31+ messages in thread
From: Jean-Christophe PLAGNIOL-VILLARD @ 2013-03-06  9:29 UTC (permalink / raw)
  To: barebox

Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
---
 apps/Kconfig               |    4 ++
 apps/Makefile              |    1 +
 apps/panel_curses/Makefile |   11 +++++
 apps/panel_curses/main.c   |  118 ++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 134 insertions(+)
 create mode 100644 apps/panel_curses/Makefile
 create mode 100644 apps/panel_curses/main.c

diff --git a/apps/Kconfig b/apps/Kconfig
index e47f0c2..532b6fb 100644
--- a/apps/Kconfig
+++ b/apps/Kconfig
@@ -45,6 +45,10 @@ config APP_TEST_CURSES
 	bool "test curses"
 	select APP_LIB_CURSES
 
+config APP_TEST_CURSES_PANEL
+	bool "test curses panel"
+	depends on APP_LIB_PANEL
+
 config APP_TEST_CURSES_MENU
 	bool "test curses menu"
 	depends on APP_LIB_MENU
diff --git a/apps/Makefile b/apps/Makefile
index 47938ec..a26541a 100644
--- a/apps/Makefile
+++ b/apps/Makefile
@@ -8,6 +8,7 @@ export APP_CPPFLAGS
 apps-$(CONFIG_APP_EXAMPLE) += example
 apps-$(CONFIG_APP_TEST_CURSES) += test_curses
 apps-$(CONFIG_APP_TEST_CURSES_MENU) += menu_curses
+apps-$(CONFIG_APP_TEST_CURSES_PANEL) += panel_curses
 
 $(obj)/application: $(apps-lds) $(apps-y)
 
diff --git a/apps/panel_curses/Makefile b/apps/panel_curses/Makefile
new file mode 100644
index 0000000..b52c808
--- /dev/null
+++ b/apps/panel_curses/Makefile
@@ -0,0 +1,11 @@
+targets := panel_curses.map
+
+# Make sure files are removed during clean
+extra-y       += panel_curses.map
+
+app-y += main.o
+app-final-y = panel_curses
+
+OBJCOPYFLAGS_panel_curses.app = -O binary
+LDFLAGS_apps	:= -Map $(obj)/panel_curses.map
+LDFLAGS_apps	+= -static --gc-sections
diff --git a/apps/panel_curses/main.c b/apps/panel_curses/main.c
new file mode 100644
index 0000000..4be732f
--- /dev/null
+++ b/apps/panel_curses/main.c
@@ -0,0 +1,118 @@
+#include <panel.h>
+#include <string.h>
+
+#define NLINES 10
+#define NCOLS 40
+
+void init_wins(WINDOW **wins, int n);
+void win_show(WINDOW *win, char *label, int label_color);
+void print_in_middle(WINDOW *win, int starty, int startx, int width, char *string, chtype color);
+
+int main(int argc, char **argv)
+{	WINDOW *my_wins[3];
+	PANEL  *my_panels[3];
+	PANEL  *top;
+	int ch;
+
+	/* Initialize curses */
+	initscr();
+	start_color();
+	cbreak();
+	noecho();
+	keypad(stdscr, TRUE);
+
+	/* Initialize all the colors */
+	init_pair(1, COLOR_RED, COLOR_BLACK);
+	init_pair(2, COLOR_GREEN, COLOR_BLACK);
+	init_pair(3, COLOR_BLUE, COLOR_BLACK);
+	init_pair(4, COLOR_CYAN, COLOR_BLACK);
+
+	init_wins(my_wins, 3);
+	
+	/* Attach a panel to each window */ 	/* Order is bottom up */
+	my_panels[0] = new_panel(my_wins[0]); 	/* Push 0, order: stdscr-0 */
+	my_panels[1] = new_panel(my_wins[1]); 	/* Push 1, order: stdscr-0-1 */
+	my_panels[2] = new_panel(my_wins[2]); 	/* Push 2, order: stdscr-0-1-2 */
+
+	/* Set up the user pointers to the next panel */
+	set_panel_userptr(my_panels[0], my_panels[1]);
+	set_panel_userptr(my_panels[1], my_panels[2]);
+	set_panel_userptr(my_panels[2], my_panels[0]);
+
+	/* Update the stacking order. 2nd panel will be on top */
+	update_panels();
+
+	/* Show it on the screen */
+	attron(COLOR_PAIR(4));
+	mvprintw(LINES - 2, 0, "Use tab to browse through the windows (F1 to Exit)");
+	attroff(COLOR_PAIR(4));
+	doupdate();
+
+	top = my_panels[2];
+	while((ch = getch()) != KEY_F(1))
+	{	switch(ch)
+		{	case 9:
+				top = (PANEL *)panel_userptr(top);
+				top_panel(top);
+				break;
+		}
+		update_panels();
+		doupdate();
+	}
+	endwin();
+	return 0;
+}
+
+/* Put all the windows */
+void init_wins(WINDOW **wins, int n)
+{	int x, y, i;
+	char label[80];
+
+	y = 2;
+	x = 10;
+	for(i = 0; i < n; ++i)
+	{	wins[i] = newwin(NLINES, NCOLS, y, x);
+		sprintf(label, "Window Number %d", i + 1);
+		win_show(wins[i], label, i + 1);
+		y += 3;
+		x += 7;
+	}
+}
+
+/* Show the window with a border and a label */
+void win_show(WINDOW *win, char *label, int label_color)
+{	int startx, starty, height, width;
+
+	getbegyx(win, starty, startx);
+	getmaxyx(win, height, width);
+
+	box(win, 0, 0);
+	mvwaddch(win, 2, 0, ACS_LTEE); 
+	mvwhline(win, 2, 1, ACS_HLINE, width - 2); 
+	mvwaddch(win, 2, width - 1, ACS_RTEE); 
+	
+	print_in_middle(win, 1, 0, width, label, COLOR_PAIR(label_color));
+}
+
+void print_in_middle(WINDOW *win, int starty, int startx, int width, char *string, chtype color)
+{	int length, x, y;
+	float temp;
+
+	if(win == NULL)
+		win = stdscr;
+	getyx(win, y, x);
+	if(startx != 0)
+		x = startx;
+	if(starty != 0)
+		y = starty;
+	if(width == 0)
+		width = 80;
+
+	length = strlen(string);
+	temp = (width - length)/ 2;
+	x = startx + (int)temp;
+	wattron(win, color);
+	mvwprintw(win, y, x, "%s", string);
+	wattroff(win, color);
+	refresh();
+}
-- 
1.7.10.4


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH 19/20] app: curses: add form example
  2013-03-06  9:29 ` [PATCH 01/20] Makefile: x_flags prepare for apps support Jean-Christophe PLAGNIOL-VILLARD
                     ` (16 preceding siblings ...)
  2013-03-06  9:29   ` [PATCH 18/20] app: curses: add panel example Jean-Christophe PLAGNIOL-VILLARD
@ 2013-03-06  9:29   ` Jean-Christophe PLAGNIOL-VILLARD
  2013-03-06  9:29   ` [PATCH 20/20] highbank: enable application support Jean-Christophe PLAGNIOL-VILLARD
  18 siblings, 0 replies; 31+ messages in thread
From: Jean-Christophe PLAGNIOL-VILLARD @ 2013-03-06  9:29 UTC (permalink / raw)
  To: barebox

Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
---
 apps/Kconfig              |    4 ++
 apps/Makefile             |    1 +
 apps/form_curses/Makefile |   11 +++++
 apps/form_curses/main.c   |  113 +++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 129 insertions(+)
 create mode 100644 apps/form_curses/Makefile
 create mode 100644 apps/form_curses/main.c

diff --git a/apps/Kconfig b/apps/Kconfig
index 532b6fb..208978b 100644
--- a/apps/Kconfig
+++ b/apps/Kconfig
@@ -53,4 +53,8 @@ config APP_TEST_CURSES_MENU
 	bool "test curses menu"
 	depends on APP_LIB_MENU
 
+config APP_TEST_CURSES_FORM
+	bool "test curses form"
+	depends on APP_LIB_FORM
+
 endif
diff --git a/apps/Makefile b/apps/Makefile
index a26541a..f7696f0 100644
--- a/apps/Makefile
+++ b/apps/Makefile
@@ -9,6 +9,7 @@ apps-$(CONFIG_APP_EXAMPLE) += example
 apps-$(CONFIG_APP_TEST_CURSES) += test_curses
 apps-$(CONFIG_APP_TEST_CURSES_MENU) += menu_curses
 apps-$(CONFIG_APP_TEST_CURSES_PANEL) += panel_curses
+apps-$(CONFIG_APP_TEST_CURSES_FORM) += form_curses
 
 $(obj)/application: $(apps-lds) $(apps-y)
 
diff --git a/apps/form_curses/Makefile b/apps/form_curses/Makefile
new file mode 100644
index 0000000..9166c9d
--- /dev/null
+++ b/apps/form_curses/Makefile
@@ -0,0 +1,11 @@
+targets := form_curses.map
+
+# Make sure files are removed during clean
+extra-y       += form_curses.map
+
+app-y += main.o
+app-final-y = form_curses
+
+OBJCOPYFLAGS_form_curses.app = -O binary
+LDFLAGS_apps	:= -Map $(obj)/form_curses.map
+LDFLAGS_apps	+= -static --gc-sections
diff --git a/apps/form_curses/main.c b/apps/form_curses/main.c
new file mode 100644
index 0000000..d737a20
--- /dev/null
+++ b/apps/form_curses/main.c
@@ -0,0 +1,113 @@
+#include <form.h>
+#include <string.h>
+
+void print_in_middle(WINDOW *win, int starty, int startx, int width, char *string, chtype color);
+
+int main(int argc, char **argv)
+{
+	FIELD *field[3];
+	FORM  *my_form;
+	WINDOW *my_form_win;
+	int ch, rows, cols;
+	
+	/* Initialize curses */
+	initscr();
+	start_color();
+	cbreak();
+	noecho();
+	keypad(stdscr, TRUE);
+
+	/* Initialize few color pairs */
+   	init_pair(1, COLOR_RED, COLOR_BLACK);
+
+	/* Initialize the fields */
+	field[0] = new_field(1, 10, 6, 1, 0, 0);
+	field[1] = new_field(1, 10, 8, 1, 0, 0);
+	field[2] = NULL;
+
+	/* Set field options */
+	set_field_back(field[0], A_UNDERLINE);
+	field_opts_off(field[0], O_AUTOSKIP); /* Don't go to next field when this */
+					      /* Field is filled up 		*/
+	set_field_back(field[1], A_UNDERLINE); 
+	field_opts_off(field[1], O_AUTOSKIP);
+	
+	/* Create the form and post it */
+	my_form = new_form(field);
+	
+	/* Calculate the area required for the form */
+	scale_form(my_form, &rows, &cols);
+
+	/* Create the window to be associated with the form */
+        my_form_win = newwin(rows + 4, cols + 4, 4, 4);
+        keypad(my_form_win, TRUE);
+
+	/* Set main window and sub window */
+        set_form_win(my_form, my_form_win);
+        set_form_sub(my_form, derwin(my_form_win, rows, cols, 2, 2));
+
+	/* Print a border around the main window and print a title */
+        box(my_form_win, 0, 0);
+	print_in_middle(my_form_win, 1, 0, cols + 4, "My Form", COLOR_PAIR(1));
+	
+	post_form(my_form);
+	wrefresh(my_form_win);
+
+	mvprintw(LINES - 2, 0, "Use UP, DOWN arrow keys to switch between fields");
+	refresh();
+
+	/* Loop through to get user requests */
+	while((ch = wgetch(my_form_win)) != KEY_F(1))
+	{	switch(ch)
+		{	case KEY_DOWN:
+				/* Go to next field */
+				form_driver(my_form, REQ_NEXT_FIELD);
+				/* Go to the end of the present buffer */
+				/* Leaves nicely at the last character */
+				form_driver(my_form, REQ_END_LINE);
+				break;
+			case KEY_UP:
+				/* Go to previous field */
+				form_driver(my_form, REQ_PREV_FIELD);
+				form_driver(my_form, REQ_END_LINE);
+				break;
+			default:
+				/* If this is a normal character, it gets */
+				/* Printed				  */	
+				form_driver(my_form, ch);
+				break;
+		}
+	}
+
+	/* Un post form and free the memory */
+	unpost_form(my_form);
+	free_form(my_form);
+	free_field(field[0]);
+	free_field(field[1]); 
+
+	endwin();
+	return 0;
+}
+
+void print_in_middle(WINDOW *win, int starty, int startx, int width, char *string, chtype color)
+{	int length, x, y;
+	float temp;
+
+	if(win == NULL)
+		win = stdscr;
+	getyx(win, y, x);
+	if(startx != 0)
+		x = startx;
+	if(starty != 0)
+		y = starty;
+	if(width == 0)
+		width = 80;
+
+	length = strlen(string);
+	temp = (width - length)/ 2;
+	x = startx + (int)temp;
+	wattron(win, color);
+	mvwprintw(win, y, x, "%s", string);
+	wattroff(win, color);
+	refresh();
+}
-- 
1.7.10.4


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH 20/20] highbank: enable application support
  2013-03-06  9:29 ` [PATCH 01/20] Makefile: x_flags prepare for apps support Jean-Christophe PLAGNIOL-VILLARD
                     ` (17 preceding siblings ...)
  2013-03-06  9:29   ` [PATCH 19/20] app: curses: add form example Jean-Christophe PLAGNIOL-VILLARD
@ 2013-03-06  9:29   ` Jean-Christophe PLAGNIOL-VILLARD
  18 siblings, 0 replies; 31+ messages in thread
From: Jean-Christophe PLAGNIOL-VILLARD @ 2013-03-06  9:29 UTC (permalink / raw)
  To: barebox

Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
---
 arch/arm/configs/highbank_defconfig |   21 +++++++++++++++++++--
 1 file changed, 19 insertions(+), 2 deletions(-)

diff --git a/arch/arm/configs/highbank_defconfig b/arch/arm/configs/highbank_defconfig
index b034ed1..5776c68 100644
--- a/arch/arm/configs/highbank_defconfig
+++ b/arch/arm/configs/highbank_defconfig
@@ -4,15 +4,16 @@ CONFIG_ARM_OPTIMZED_STRING_FUNCTIONS=y
 CONFIG_PBL_IMAGE=y
 CONFIG_MMU=y
 CONFIG_MALLOC_SIZE=0xa00000
+CONFIG_EXPERIMENTAL=y
 CONFIG_MALLOC_TLSF=y
 CONFIG_PROMPT="vexpress: "
 CONFIG_LONGHELP=y
-CONFIG_GLOB=y
 CONFIG_HUSH_FANCY_PROMPT=y
 CONFIG_CMDLINE_EDITING=y
 CONFIG_AUTO_COMPLETE=y
 CONFIG_MENU=y
-CONFIG_DEFAULT_ENVIRONMENT_GENERIC=y
+CONFIG_PARTITION_DISK_EFI=y
+CONFIG_DEFAULT_ENVIRONMENT_GENERIC_NEW=y
 CONFIG_DEFAULT_ENVIRONMENT_PATH="arch/arm/boards/highbank/env"
 CONFIG_CMD_EDIT=y
 CONFIG_CMD_SLEEP=y
@@ -23,10 +24,16 @@ CONFIG_CMD_READLINE=y
 CONFIG_CMD_MENU=y
 CONFIG_CMD_MENU_MANAGEMENT=y
 CONFIG_CMD_PASSWD=y
+CONFIG_CMD_LN=y
+CONFIG_CMD_READLINK=y
 CONFIG_CMD_TFTP=y
+CONFIG_CMD_FILETYPE=y
+CONFIG_CMD_APPINFO=y
 CONFIG_CMD_ECHO_E=y
 CONFIG_CMD_LOADB=y
 CONFIG_CMD_MEMINFO=y
+CONFIG_CMD_CRC=y
+CONFIG_CMD_CRC_CMP=y
 CONFIG_CMD_BOOTM_SHOW_TYPE=y
 CONFIG_CMD_BOOTM_VERBOSE=y
 CONFIG_CMD_BOOTM_INITRD=y
@@ -60,3 +67,13 @@ CONFIG_GPIO_PL061=y
 CONFIG_FS_TFTP=y
 CONFIG_SHA1=y
 CONFIG_SHA256=y
+CONFIG_APPLICATIONS=y
+CONFIG_APP_LIB_PANEL=y
+CONFIG_APP_LIB_MENU=y
+CONFIG_APP_LIB_FORM=y
+CONFIG_APP_TEXT_BASE_OFFSET=0x1000000
+CONFIG_APP_EXAMPLE=y
+CONFIG_APP_TEST_CURSES=y
+CONFIG_APP_TEST_CURSES_PANEL=y
+CONFIG_APP_TEST_CURSES_MENU=y
+CONFIG_APP_TEST_CURSES_FORM=y
-- 
1.7.10.4


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 09/20] arm: add application support
  2013-03-06  9:29   ` [PATCH 09/20] arm: add application support Jean-Christophe PLAGNIOL-VILLARD
@ 2013-03-06  9:59     ` Alexander Shiyan
  2013-03-06 10:13       ` Jean-Christophe PLAGNIOL-VILLARD
  0 siblings, 1 reply; 31+ messages in thread
From: Alexander Shiyan @ 2013-03-06  9:59 UTC (permalink / raw)
  To: Jean-Christophe PLAGNIOL-VILLARD; +Cc: barebox

> Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
> ---
>  arch/arm/Kconfig                       |    1 +
>  arch/arm/Makefile                      |    6 +-
>  arch/arm/apps/Kconfig                  |   11 ++++
>  arch/arm/apps/Makefile                 |    6 ++
>  arch/arm/apps/apps.lds.S               |   64 ++++++++++++++++++
>  arch/arm/apps/binfmt.c                 |  111 ++++++++++++++++++++++++++++++++
>  arch/arm/apps/head.S                   |   59 +++++++++++++++++
>  arch/arm/apps/include/arch/asm/macro.h |   46 +++++++++++++
>  arch/arm/apps/include/arch/setjmp.h    |   26 ++++++++
>  arch/arm/apps/raise.c                  |   27 ++++++++
>  arch/arm/apps/setjmp.S                 |   60 +++++++++++++++++
>  arch/arm/apps/start.c                  |   35 ++++++++++
>  12 files changed, 451 insertions(+), 1 deletion(-)
>  create mode 100644 arch/arm/apps/Kconfig
>  create mode 100644 arch/arm/apps/Makefile
>  create mode 100644 arch/arm/apps/apps.lds.S
>  create mode 100644 arch/arm/apps/binfmt.c
>  create mode 100644 arch/arm/apps/head.S
>  create mode 100644 arch/arm/apps/include/arch/asm/macro.h
>  create mode 100644 arch/arm/apps/include/arch/setjmp.h
>  create mode 100644 arch/arm/apps/raise.c
>  create mode 100644 arch/arm/apps/setjmp.S
>  create mode 100644 arch/arm/apps/start.c
...

Is this feature really needed? If we Include it, is dramatically increases size of BB.
We have a scripting, maybe just inclusion a small "C" interpreter is enough?
Such as "picoc" (http://code.google.com/p/picoc/), for example.

---
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 09/20] arm: add application support
  2013-03-06  9:59     ` Alexander Shiyan
@ 2013-03-06 10:13       ` Jean-Christophe PLAGNIOL-VILLARD
  0 siblings, 0 replies; 31+ messages in thread
From: Jean-Christophe PLAGNIOL-VILLARD @ 2013-03-06 10:13 UTC (permalink / raw)
  To: Alexander Shiyan; +Cc: barebox

On 13:59 Wed 06 Mar     , Alexander Shiyan wrote:
> > Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
> > ---
> >  arch/arm/Kconfig                       |    1 +
> >  arch/arm/Makefile                      |    6 +-
> >  arch/arm/apps/Kconfig                  |   11 ++++
> >  arch/arm/apps/Makefile                 |    6 ++
> >  arch/arm/apps/apps.lds.S               |   64 ++++++++++++++++++
> >  arch/arm/apps/binfmt.c                 |  111 ++++++++++++++++++++++++++++++++
> >  arch/arm/apps/head.S                   |   59 +++++++++++++++++
> >  arch/arm/apps/include/arch/asm/macro.h |   46 +++++++++++++
> >  arch/arm/apps/include/arch/setjmp.h    |   26 ++++++++
> >  arch/arm/apps/raise.c                  |   27 ++++++++
> >  arch/arm/apps/setjmp.S                 |   60 +++++++++++++++++
> >  arch/arm/apps/start.c                  |   35 ++++++++++
> >  12 files changed, 451 insertions(+), 1 deletion(-)
> >  create mode 100644 arch/arm/apps/Kconfig
> >  create mode 100644 arch/arm/apps/Makefile
> >  create mode 100644 arch/arm/apps/apps.lds.S
> >  create mode 100644 arch/arm/apps/binfmt.c
> >  create mode 100644 arch/arm/apps/head.S
> >  create mode 100644 arch/arm/apps/include/arch/asm/macro.h
> >  create mode 100644 arch/arm/apps/include/arch/setjmp.h
> >  create mode 100644 arch/arm/apps/raise.c
> >  create mode 100644 arch/arm/apps/setjmp.S
> >  create mode 100644 arch/arm/apps/start.c
> ...
> 
> Is this feature really needed? If we Include it, is dramatically increases size of BB.
> We have a scripting, maybe just inclusion a small "C" interpreter is enough?
> Such as "picoc" (http://code.google.com/p/picoc/), for example.
increase?? no
 1 to 2 KiB

on barebox side you just have the syscall

it's nothing and this is optionnal

Best Regards,
J.
> 
> ---

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 12/20] app: add tinycurses support
  2013-03-06  9:29   ` [PATCH 12/20] app: add tinycurses support Jean-Christophe PLAGNIOL-VILLARD
@ 2013-03-06 11:31     ` Sascha Hauer
  2013-03-06 13:04       ` Jean-Christophe PLAGNIOL-VILLARD
  0 siblings, 1 reply; 31+ messages in thread
From: Sascha Hauer @ 2013-03-06 11:31 UTC (permalink / raw)
  To: Jean-Christophe PLAGNIOL-VILLARD; +Cc: barebox

On Wed, Mar 06, 2013 at 10:29:41AM +0100, Jean-Christophe PLAGNIOL-VILLARD wrote:
> take from corboot and upated to use ansi
> 
> Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>

Drop the curses stuff from the series. It will take time to get the
application stuff reviewed and merged, so concentrate on the basic stuff
and do not dump this unrelated stuff on the list.

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 12/20] app: add tinycurses support
  2013-03-06 11:31     ` Sascha Hauer
@ 2013-03-06 13:04       ` Jean-Christophe PLAGNIOL-VILLARD
  0 siblings, 0 replies; 31+ messages in thread
From: Jean-Christophe PLAGNIOL-VILLARD @ 2013-03-06 13:04 UTC (permalink / raw)
  To: Sascha Hauer; +Cc: barebox

On 12:31 Wed 06 Mar     , Sascha Hauer wrote:
> On Wed, Mar 06, 2013 at 10:29:41AM +0100, Jean-Christophe PLAGNIOL-VILLARD wrote:
> > take from corboot and upated to use ansi
> > 
> > Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
> 
> Drop the curses stuff from the series. It will take time to get the
> application stuff reviewed and merged, so concentrate on the basic stuff
> and do not dump this unrelated stuff on the list.
this will be presented this friday at CEWG so I choose to send it together and
it's a good example how to use the application implemetation

for the other version of this patch serie I'll not include it

Best Regards,
J.
> 
> Sascha
> 
> -- 
> Pengutronix e.K.                           |                             |
> Industrial Linux Solutions                 | http://www.pengutronix.de/  |
> Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
> Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 06/20] app: add some utils
  2013-03-06  9:29   ` [PATCH 06/20] app: add some utils Jean-Christophe PLAGNIOL-VILLARD
@ 2013-03-06 21:21     ` Sascha Hauer
  2013-03-06 21:34       ` Jean-Christophe PLAGNIOL-VILLARD
  0 siblings, 1 reply; 31+ messages in thread
From: Sascha Hauer @ 2013-03-06 21:21 UTC (permalink / raw)
  To: Jean-Christophe PLAGNIOL-VILLARD; +Cc: barebox

On Wed, Mar 06, 2013 at 10:29:35AM +0100, Jean-Christophe PLAGNIOL-VILLARD wrote:
>  - getchar_timeout
>  - term (try to detect terminal size, position, ansi helper)
>  - list
> 
> Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
> ---
> diff --git a/apps/include/utils/list.h b/apps/include/utils/list.h
> new file mode 100644
> index 0000000..8a18dae
> --- /dev/null
> +++ b/apps/include/utils/list.h
> @@ -0,0 +1,114 @@
> +/*
> + * Copyright (C) 2013 Jean-Christophe PLAGNIOL-VILLARD <plagnio@jcrosoft.com>
> + *
> + * Under GPLv2 only
> + *
> + * As a special exception, if other files instantiate templates or use macros
> + * or inline functions from this file, or you compile this file and link it
> + * with other works to produce a work based on this file, this file does not
> + * by itself cause the resulting work to be covered by the GNU General Public
> + * License. However the source code for this file must still be made available
> + * in accordance with section (3) of the GNU General Public License.
> +
> + * This exception does not invalidate any other reasons why a work based on
> + * this file might be covered by the GNU General Public License.
> + */

This looks suspiciously like the Linux list implementation which I think you
haven't written. Also who gives you the right to add this licence
exception to code you do not own?

Sascha

> +
> +#ifndef __UTILS_LIST_H__
> +#define __UTILS_LIST_H__
> +
> +struct list_entry {
> +	struct list_entry *prev;
> +	struct list_entry *next;
> +};
> +
> +struct list {
> +	struct list_entry head;
> +};
> +
> +#define LIST_HEAD_INIT(name) \
> +	{ \
> +		.head = { \
> +			.prev = &(name).head, \
> +			.next = &(name).head \
> +		} \
> +	}
> +
> +#define LIST_HEAD(name) \
> +	struct list name = LIST_HEAD_INIT(name)
> +
> +#define container_of(ptr, type, member) \
> +	((type *) (((void *)(ptr)) - ((void *) &(((type *)0)->member))))
> +
> +#define list_entry(ptr, type, member) \
> +	container_of(ptr, type, member)
> +
> +#define list_first_entry(ptr, type, member) \
> +	list_entry((ptr)->head.next, type, member)
> +
> +#define list_last_entry(head, type, member) \
> +	list_entry((head)->head.prev, type, member)
> +
> +#define list_for_each(pos, list) \
> +	for (pos = (list).head.next; pos != &(list).head; pos = pos->next)
> +
> +#define list_foreach_safe(pos, n, list) \
> +	for (pos = (list).head.next, *n = pos->next; \
> +		pos != &(list).head; pos = n, n = pos->next)
> +
> +#define list_for_each_entry(pos, list, member)				\
> +	for (pos = list_entry((list)->head.next, typeof(*pos), member);	\
> +	      &pos->member != (&(list)->head);				\
> +	     pos = list_entry(pos->member.next, typeof(*pos), member))
> +
> +
> +#define list_for_each_entry_safe(pos, n, list, member)			\
> +	for (pos = list_entry((list)->head.next, typeof(*pos), member),	\
> +		n = list_entry(pos->member.next, typeof(*pos), member);	\
> +	     &pos->member != (&(list)->head);				\
> +	     pos = n, n = list_entry(n->member.next, typeof(*n), member))
> +
> +
> +static inline bool list_empty(struct list *list)
> +{
> +	struct list_entry *head = &list->head;
> +
> +	return head->next == head;
> +}
> +
> +static inline void __list_add(struct list_entry *new,
> +			      struct list_entry *prev,
> +			      struct list_entry *next)
> +{
> +	next->prev = new;
> +	new->next = next;
> +	new->prev = prev;
> +	prev->next = new;
> +}
> +
> +static inline void list_add(struct list_entry *new, struct list *list)
> +{
> +	struct list_entry *head = &list->head;
> +
> +	__list_add(new, head, head->next);
> +}
> +
> +static inline void list_add_tail(struct list_entry *new, struct list *list)
> +{
> +	struct list_entry *head = &list->head;
> +
> +	__list_add(new, head->prev, head);
> +}
> +
> +static inline void list_del(struct list_entry *entry)
> +{
> +	struct list_entry *prev = entry->prev;
> +	struct list_entry *next = entry->next;
> +
> +	next->prev = prev;
> +	prev->next = next;
> +	entry->next = NULL;
> +	entry->prev = NULL;
> +}
> +	
> +#endif /* __UTILS_LIST_H__ */
-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 06/20] app: add some utils
  2013-03-06 21:21     ` Sascha Hauer
@ 2013-03-06 21:34       ` Jean-Christophe PLAGNIOL-VILLARD
  2013-03-07  7:45         ` Sascha Hauer
  0 siblings, 1 reply; 31+ messages in thread
From: Jean-Christophe PLAGNIOL-VILLARD @ 2013-03-06 21:34 UTC (permalink / raw)
  To: Sascha Hauer; +Cc: barebox

On 22:21 Wed 06 Mar     , Sascha Hauer wrote:
> On Wed, Mar 06, 2013 at 10:29:35AM +0100, Jean-Christophe PLAGNIOL-VILLARD wrote:
> >  - getchar_timeout
> >  - term (try to detect terminal size, position, ansi helper)
> >  - list
> > 
> > Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
> > ---
> > diff --git a/apps/include/utils/list.h b/apps/include/utils/list.h
> > new file mode 100644
> > index 0000000..8a18dae
> > --- /dev/null
> > +++ b/apps/include/utils/list.h
> > @@ -0,0 +1,114 @@
> > +/*
> > + * Copyright (C) 2013 Jean-Christophe PLAGNIOL-VILLARD <plagnio@jcrosoft.com>
> > + *
> > + * Under GPLv2 only
> > + *
> > + * As a special exception, if other files instantiate templates or use macros
> > + * or inline functions from this file, or you compile this file and link it
> > + * with other works to produce a work based on this file, this file does not
> > + * by itself cause the resulting work to be covered by the GNU General Public
> > + * License. However the source code for this file must still be made available
> > + * in accordance with section (3) of the GNU General Public License.
> > +
> > + * This exception does not invalidate any other reasons why a work based on
> > + * this file might be covered by the GNU General Public License.
> > + */
> 
> This looks suspiciously like the Linux list implementation which I think you
> haven't written. Also who gives you the right to add this licence
> exception to code you do not own?
I did wrote this for years about 10 I just update the code to looks like the
linux one so I do own the code

Best Regards,
J.
> 
> Sascha
> 
> > +
> > +#ifndef __UTILS_LIST_H__
> > +#define __UTILS_LIST_H__
> > +
> > +struct list_entry {
> > +	struct list_entry *prev;
> > +	struct list_entry *next;
> > +};
> > +
> > +struct list {
> > +	struct list_entry head;
> > +};
> > +
> > +#define LIST_HEAD_INIT(name) \
> > +	{ \
> > +		.head = { \
> > +			.prev = &(name).head, \
> > +			.next = &(name).head \
> > +		} \
> > +	}
> > +
> > +#define LIST_HEAD(name) \
> > +	struct list name = LIST_HEAD_INIT(name)
> > +
> > +#define container_of(ptr, type, member) \
> > +	((type *) (((void *)(ptr)) - ((void *) &(((type *)0)->member))))
> > +
> > +#define list_entry(ptr, type, member) \
> > +	container_of(ptr, type, member)
> > +
> > +#define list_first_entry(ptr, type, member) \
> > +	list_entry((ptr)->head.next, type, member)
> > +
> > +#define list_last_entry(head, type, member) \
> > +	list_entry((head)->head.prev, type, member)
> > +
> > +#define list_for_each(pos, list) \
> > +	for (pos = (list).head.next; pos != &(list).head; pos = pos->next)
> > +
> > +#define list_foreach_safe(pos, n, list) \
> > +	for (pos = (list).head.next, *n = pos->next; \
> > +		pos != &(list).head; pos = n, n = pos->next)
> > +
> > +#define list_for_each_entry(pos, list, member)				\
> > +	for (pos = list_entry((list)->head.next, typeof(*pos), member);	\
> > +	      &pos->member != (&(list)->head);				\
> > +	     pos = list_entry(pos->member.next, typeof(*pos), member))
> > +
> > +
> > +#define list_for_each_entry_safe(pos, n, list, member)			\
> > +	for (pos = list_entry((list)->head.next, typeof(*pos), member),	\
> > +		n = list_entry(pos->member.next, typeof(*pos), member);	\
> > +	     &pos->member != (&(list)->head);				\
> > +	     pos = n, n = list_entry(n->member.next, typeof(*n), member))
> > +
> > +
> > +static inline bool list_empty(struct list *list)
> > +{
> > +	struct list_entry *head = &list->head;
> > +
> > +	return head->next == head;
> > +}
> > +
> > +static inline void __list_add(struct list_entry *new,
> > +			      struct list_entry *prev,
> > +			      struct list_entry *next)
> > +{
> > +	next->prev = new;
> > +	new->next = next;
> > +	new->prev = prev;
> > +	prev->next = new;
> > +}
> > +
> > +static inline void list_add(struct list_entry *new, struct list *list)
> > +{
> > +	struct list_entry *head = &list->head;
> > +
> > +	__list_add(new, head, head->next);
> > +}
> > +
> > +static inline void list_add_tail(struct list_entry *new, struct list *list)
> > +{
> > +	struct list_entry *head = &list->head;
> > +
> > +	__list_add(new, head->prev, head);
> > +}
> > +
> > +static inline void list_del(struct list_entry *entry)
> > +{
> > +	struct list_entry *prev = entry->prev;
> > +	struct list_entry *next = entry->next;
> > +
> > +	next->prev = prev;
> > +	prev->next = next;
> > +	entry->next = NULL;
> > +	entry->prev = NULL;
> > +}
> > +	
> > +#endif /* __UTILS_LIST_H__ */
> -- 
> Pengutronix e.K.                           |                             |
> Industrial Linux Solutions                 | http://www.pengutronix.de/  |
> Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
> Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [RFC PATCH 00/20] introduce application support
  2013-03-06  9:26 [RFC PATCH 00/20] introduce application support Jean-Christophe PLAGNIOL-VILLARD
  2013-03-06  9:29 ` [PATCH 01/20] Makefile: x_flags prepare for apps support Jean-Christophe PLAGNIOL-VILLARD
@ 2013-03-07  7:36 ` Sascha Hauer
  1 sibling, 0 replies; 31+ messages in thread
From: Sascha Hauer @ 2013-03-07  7:36 UTC (permalink / raw)
  To: Jean-Christophe PLAGNIOL-VILLARD; +Cc: barebox

On Wed, Mar 06, 2013 at 10:26:43AM +0100, Jean-Christophe PLAGNIOL-VILLARD wrote:
> HI,
> 
> 	this patch serie introduce the application support to barebox
> 
> 	This will allow to run application at run time by calling barebox
> 	syscalls and as this will be a stable ABI the application will able
> 	the run against any barebox that support it
> 
> 	As the application are not linked to barebox the GPLv2 licence does
> 	not apply.
> 
> 	This patch serie provide a small libc (partialy implemented) which is
> 	under GPLv2 + exception
> 
> As a special exception, if other files instantiate templates or use macros
> or inline functions from this file, or you compile this file and link it
> with other works to produce a work based on this file, this file does not
> by itself cause the resulting work to be covered by the GNU General Public
> License. However the source code for this file must still be made available
> in accordance with section (3) of the GNU General Public License.
> 
> This exception does not invalidate any other reasons why a work based on
> this file might be covered by the GNU General Public License.
> 
> 	This also provide the curses support proted against the libary with some examples

I'm fine with the app support in general, but I don't want to become the
maintainer of a proprietary software helper framework. So, if you want
curses and whatever stuff, create a separate repository for it. The
barebox repository ends at the syscall interface and an example
application for showing how to use it.

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 02/20] tlsf_malloc: drop duplicate include
  2013-03-06  9:29   ` [PATCH 02/20] tlsf_malloc: drop duplicate include Jean-Christophe PLAGNIOL-VILLARD
@ 2013-03-07  7:37     ` Sascha Hauer
  0 siblings, 0 replies; 31+ messages in thread
From: Sascha Hauer @ 2013-03-07  7:37 UTC (permalink / raw)
  To: Jean-Christophe PLAGNIOL-VILLARD; +Cc: barebox

On Wed, Mar 06, 2013 at 10:29:31AM +0100, Jean-Christophe PLAGNIOL-VILLARD wrote:
> config.h is not need and already inclued by Makefile
> 
> Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>

Applied, thanks

Sascha

> ---
>  common/tlsf_malloc.c |    2 --
>  1 file changed, 2 deletions(-)
> 
> diff --git a/common/tlsf_malloc.c b/common/tlsf_malloc.c
> index 5c5bb61..cd01b56 100644
> --- a/common/tlsf_malloc.c
> +++ b/common/tlsf_malloc.c
> @@ -17,10 +17,8 @@
>   *
>   */
>  
> -#include <config.h>
>  #include <malloc.h>
>  #include <string.h>
> -#include <malloc.h>
>  
>  #include <stdio.h>
>  #include <module.h>
> -- 
> 1.7.10.4
> 
> 
> _______________________________________________
> barebox mailing list
> barebox@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/barebox
> 

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 06/20] app: add some utils
  2013-03-06 21:34       ` Jean-Christophe PLAGNIOL-VILLARD
@ 2013-03-07  7:45         ` Sascha Hauer
  2013-03-07  9:17           ` Alexander Aring
  0 siblings, 1 reply; 31+ messages in thread
From: Sascha Hauer @ 2013-03-07  7:45 UTC (permalink / raw)
  To: Jean-Christophe PLAGNIOL-VILLARD; +Cc: barebox

On Wed, Mar 06, 2013 at 10:34:44PM +0100, Jean-Christophe PLAGNIOL-VILLARD wrote:
> On 22:21 Wed 06 Mar     , Sascha Hauer wrote:
> > On Wed, Mar 06, 2013 at 10:29:35AM +0100, Jean-Christophe PLAGNIOL-VILLARD wrote:
> > >  - getchar_timeout
> > >  - term (try to detect terminal size, position, ansi helper)
> > >  - list
> > > 
> > > Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
> > > ---
> > > diff --git a/apps/include/utils/list.h b/apps/include/utils/list.h
> > > new file mode 100644
> > > index 0000000..8a18dae
> > > --- /dev/null
> > > +++ b/apps/include/utils/list.h
> > > @@ -0,0 +1,114 @@
> > > +/*
> > > + * Copyright (C) 2013 Jean-Christophe PLAGNIOL-VILLARD <plagnio@jcrosoft.com>
> > > + *
> > > + * Under GPLv2 only
> > > + *
> > > + * As a special exception, if other files instantiate templates or use macros
> > > + * or inline functions from this file, or you compile this file and link it
> > > + * with other works to produce a work based on this file, this file does not
> > > + * by itself cause the resulting work to be covered by the GNU General Public
> > > + * License. However the source code for this file must still be made available
> > > + * in accordance with section (3) of the GNU General Public License.
> > > +
> > > + * This exception does not invalidate any other reasons why a work based on
> > > + * this file might be covered by the GNU General Public License.
> > > + */
> > 
> > This looks suspiciously like the Linux list implementation which I think you
> > haven't written. Also who gives you the right to add this licence
> > exception to code you do not own?
> I did wrote this for years about 10 I just update the code to looks like the
> linux one so I do own the code

LOL. I've written my own OS 25 years ago, I just updated the code to look
like Linux.

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 06/20] app: add some utils
  2013-03-07  7:45         ` Sascha Hauer
@ 2013-03-07  9:17           ` Alexander Aring
  0 siblings, 0 replies; 31+ messages in thread
From: Alexander Aring @ 2013-03-07  9:17 UTC (permalink / raw)
  To: Sascha Hauer; +Cc: barebox

On Thu, Mar 07, 2013 at 08:45:03AM +0100, Sascha Hauer wrote:
> On Wed, Mar 06, 2013 at 10:34:44PM +0100, Jean-Christophe PLAGNIOL-VILLARD wrote:
> > On 22:21 Wed 06 Mar     , Sascha Hauer wrote:
> > > On Wed, Mar 06, 2013 at 10:29:35AM +0100, Jean-Christophe PLAGNIOL-VILLARD wrote:
> > > >  - getchar_timeout
> > > >  - term (try to detect terminal size, position, ansi helper)
> > > >  - list
> > > > 
> > > > Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
> > > > ---
> > > > diff --git a/apps/include/utils/list.h b/apps/include/utils/list.h
> > > > new file mode 100644
> > > > index 0000000..8a18dae
> > > > --- /dev/null
> > > > +++ b/apps/include/utils/list.h
> > > > @@ -0,0 +1,114 @@
> > > > +/*
> > > > + * Copyright (C) 2013 Jean-Christophe PLAGNIOL-VILLARD <plagnio@jcrosoft.com>
> > > > + *
> > > > + * Under GPLv2 only
> > > > + *
> > > > + * As a special exception, if other files instantiate templates or use macros
> > > > + * or inline functions from this file, or you compile this file and link it
> > > > + * with other works to produce a work based on this file, this file does not
> > > > + * by itself cause the resulting work to be covered by the GNU General Public
> > > > + * License. However the source code for this file must still be made available
> > > > + * in accordance with section (3) of the GNU General Public License.
> > > > +
> > > > + * This exception does not invalidate any other reasons why a work based on
> > > > + * this file might be covered by the GNU General Public License.
> > > > + */
> > > 
> > > This looks suspiciously like the Linux list implementation which I think you
> > > haven't written. Also who gives you the right to add this licence
> > > exception to code you do not own?
> > I did wrote this for years about 10 I just update the code to looks like the
> > linux one so I do own the code
> 
> LOL. I've written my own OS 25 years ago, I just updated the code to look
> like Linux.
> 
lol... other question: why we need a second list implementation?
In order to not be dependent on linux headers?

Alex

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 31+ messages in thread

end of thread, other threads:[~2013-03-07  9:16 UTC | newest]

Thread overview: 31+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-03-06  9:26 [RFC PATCH 00/20] introduce application support Jean-Christophe PLAGNIOL-VILLARD
2013-03-06  9:29 ` [PATCH 01/20] Makefile: x_flags prepare for apps support Jean-Christophe PLAGNIOL-VILLARD
2013-03-06  9:29   ` [PATCH 02/20] tlsf_malloc: drop duplicate include Jean-Christophe PLAGNIOL-VILLARD
2013-03-07  7:37     ` Sascha Hauer
2013-03-06  9:29   ` [PATCH 03/20] kbuild: add application (app) target Jean-Christophe PLAGNIOL-VILLARD
2013-03-06  9:29   ` [PATCH 04/20] Introduce application (app) support Jean-Christophe PLAGNIOL-VILLARD
2013-03-06  9:29   ` [PATCH 05/20] app: Introduce libc support Jean-Christophe PLAGNIOL-VILLARD
2013-03-06  9:29   ` [PATCH 06/20] app: add some utils Jean-Christophe PLAGNIOL-VILLARD
2013-03-06 21:21     ` Sascha Hauer
2013-03-06 21:34       ` Jean-Christophe PLAGNIOL-VILLARD
2013-03-07  7:45         ` Sascha Hauer
2013-03-07  9:17           ` Alexander Aring
2013-03-06  9:29   ` [PATCH 07/20] app: Introduce example application Jean-Christophe PLAGNIOL-VILLARD
2013-03-06  9:29   ` [PATCH 08/20] filetype: add barebox arm application Jean-Christophe PLAGNIOL-VILLARD
2013-03-06  9:29   ` [PATCH 09/20] arm: add application support Jean-Christophe PLAGNIOL-VILLARD
2013-03-06  9:59     ` Alexander Shiyan
2013-03-06 10:13       ` Jean-Christophe PLAGNIOL-VILLARD
2013-03-06  9:29   ` [PATCH 10/20] app: printf: use HelenOS verison with wide char support Jean-Christophe PLAGNIOL-VILLARD
2013-03-06  9:29   ` [PATCH 11/20] app: printf: add version from contiki Jean-Christophe PLAGNIOL-VILLARD
2013-03-06  9:29   ` [PATCH 12/20] app: add tinycurses support Jean-Christophe PLAGNIOL-VILLARD
2013-03-06 11:31     ` Sascha Hauer
2013-03-06 13:04       ` Jean-Christophe PLAGNIOL-VILLARD
2013-03-06  9:29   ` [PATCH 13/20] app: curses: add pdcurses Jean-Christophe PLAGNIOL-VILLARD
2013-03-06  9:29   ` [PATCH 14/20] app: add test curses Jean-Christophe PLAGNIOL-VILLARD
2013-03-06  9:29   ` [PATCH 15/20] app: pdcurses: add libmenu Jean-Christophe PLAGNIOL-VILLARD
2013-03-06  9:29   ` [PATCH 16/20] app: pdcurses: add libform Jean-Christophe PLAGNIOL-VILLARD
2013-03-06  9:29   ` [PATCH 17/20] app: curses: add menu example Jean-Christophe PLAGNIOL-VILLARD
2013-03-06  9:29   ` [PATCH 18/20] app: curses: add panel example Jean-Christophe PLAGNIOL-VILLARD
2013-03-06  9:29   ` [PATCH 19/20] app: curses: add form example Jean-Christophe PLAGNIOL-VILLARD
2013-03-06  9:29   ` [PATCH 20/20] highbank: enable application support Jean-Christophe PLAGNIOL-VILLARD
2013-03-07  7:36 ` [RFC PATCH 00/20] introduce " Sascha Hauer

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox