summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKhem Raj <raj.khem@gmail.com>2009-02-23 13:19:19 -0800
committerKhem Raj <raj.khem@gmail.com>2009-02-23 13:19:19 -0800
commit8c2955ce84aa2dacfacdfa96b8d2bfaf08f985d2 (patch)
tree01b120afb41cf6fe91c0a093ac38ad7864bb862f
parent0773447006cd2aa0b2c3ac364ce6e1c151215087 (diff)
parent0f5b41fdc74c6b18d482cab683a7fb2d53b6e3a2 (diff)
Merge branch 'org.openembedded.dev' of git@git.openembedded.net:openembedded into org.openembedded.dev
-rw-r--r--classes/image.bbclass30
-rw-r--r--classes/rootfs_ipk.bbclass5
-rw-r--r--conf/checksums.ini4
-rw-r--r--conf/distro/angstrom-2008.1.conf6
-rw-r--r--conf/distro/slugos.conf2
-rw-r--r--packages/bluez/bluez4_4.30.bb2
-rw-r--r--packages/busybox/busybox-static-1.11.3/B921600.patch13
-rw-r--r--packages/dsplink/gstreamer-ti_svn.bb2
-rw-r--r--packages/e2fsprogs/e2fsprogs_1.41.4.bb101
-rw-r--r--packages/gpsd/gpsd.inc2
-rw-r--r--packages/gpsd/gpsd_2.38.bb (renamed from packages/gpsd/gpsd_2.37.bb)2
-rw-r--r--packages/gtk-webcore/midori_git.bb4
-rw-r--r--packages/initrdscripts/files/00-psplash.sh8
-rw-r--r--packages/initrdscripts/files/80-ext3.sh2
-rw-r--r--packages/initrdscripts/files/98-aufs.sh2
-rw-r--r--packages/initrdscripts/files/99-psplash.sh6
-rw-r--r--packages/initrdscripts/files/init.sh7
-rw-r--r--packages/initrdscripts/initramfs-module-psplash_1.0.bb2
-rw-r--r--packages/libnetfilter-queue/libnetfilter-queue.inc22
-rw-r--r--packages/libnetfilter-queue/libnetfilter-queue_0.0.13.bb30
-rw-r--r--packages/libnetfilter-queue/libnetfilter-queue_0.0.16.bb2
-rw-r--r--packages/linux/linux-2.6.27/boc01/012-090115-cy3218-btns.patch406
-rw-r--r--packages/linux/linux-2.6.27/boc01/012-090219-capsense.patch865
-rw-r--r--packages/linux/linux_2.6.27.bb4
-rw-r--r--packages/matchbox-panel/matchbox-panel-0.9.3/mb-applet-system-monitor-crash.patch85
-rw-r--r--packages/matchbox-panel/matchbox-panel_0.9.3.bb5
-rw-r--r--packages/mc/mc-4.6.2/00-70-utf8-common.patch46
-rw-r--r--packages/mc/mc-4.6.2/00-73-utf8-bottom-buttons-width.patch21
-rw-r--r--packages/mc/mc-4.6.2/00-75-utf8-cmdline-help.patch63
-rw-r--r--packages/mc/mc-4.6.2/00-76-utf8-hotlist-highlight.patch23
-rw-r--r--packages/mc/mc-4.6.2/00-77-utf8-filename-search-highlight.patch17
-rw-r--r--packages/mc/mc-4.6.2/mc-utf8-look-and-feel.patch206
-rw-r--r--packages/mc/mc-4.6.2/mc-utf8-nlink.patch11
-rw-r--r--packages/mc/mc-4.6.2/mc-utf8.patch5357
-rw-r--r--packages/mc/mc-4.6.2/mhl-stdbool.patch16
-rw-r--r--packages/mc/mc_4.6.2.bb60
-rwxr-xr-xpackages/meta/run-postinsts/run-postinsts36
-rw-r--r--packages/meta/run-postinsts/run-postinsts.awk30
-rw-r--r--packages/meta/run-postinsts_1.0.bb30
-rw-r--r--packages/motion/motion-3.2.11/ffmpeg-0.4.9.15594svn-20081010.diff14
-rw-r--r--packages/motion/motion_3.2.11.bb7
-rw-r--r--packages/psplash/files/psplash-init12
-rw-r--r--packages/psplash/psplash-openmoko_svn.bb1
-rw-r--r--packages/psplash/psplash.inc1
-rw-r--r--packages/psplash/psplash_svn.bb2
-rw-r--r--packages/tasks/task-gstreamer-ti.bb16
-rw-r--r--packages/tuxtype/tuxtype_1.7.3.bb20
-rw-r--r--packages/u-boot/u-boot-1.3.2/boc01/007-090217-CAPSENSE.patch (renamed from packages/u-boot/u-boot-1.3.2/boc01/007-090112-CAPSENSE.patch)4
-rw-r--r--packages/u-boot/u-boot_1.3.2.bb4
49 files changed, 7131 insertions, 485 deletions
diff --git a/classes/image.bbclass b/classes/image.bbclass
index 2ed0ee1de7..fd0df4df08 100644
--- a/classes/image.bbclass
+++ b/classes/image.bbclass
@@ -2,19 +2,6 @@ inherit rootfs_${IMAGE_PKGTYPE}
LICENSE = "MIT"
PACKAGES = ""
-RDEPENDS += "${IMAGE_INSTALL}"
-
-# "export IMAGE_BASENAME" not supported at this time
-IMAGE_BASENAME[export] = "1"
-export PACKAGE_INSTALL ?= "${IMAGE_INSTALL}"
-
-# We need to recursively follow RDEPENDS and RRECOMMENDS for images
-do_rootfs[recrdeptask] += "do_deploy do_populate_staging"
-
-# Images are generally built explicitly, do not need to be part of world.
-EXCLUDE_FROM_WORLD = "1"
-
-USE_DEVFS ?= "0"
#
# udev, devfsd, busybox-mdev (from busybox) or none
@@ -28,15 +15,26 @@ IMAGE_INITSCRIPTS ?= "initscripts"
#
# tinylogin, getty
#
-IMAGE_LOGIN_MANAGER ?= "tinylogin"
+IMAGE_LOGIN_MANAGER ?= "tinylogin"
IMAGE_VARS = "${IMAGE_INITSCRIPTS} \
${IMAGE_DEV_MANAGER} \
${IMAGE_INIT_MANAGER} \
${IMAGE_LOGIN_MANAGER} "
-RDEPENDS += "${IMAGE_VARS}"
-PACKAGE_INSTALL += "${IMAGE_VARS}"
+RDEPENDS += "${IMAGE_INSTALL} ${IMAGE_VARS}"
+
+# "export IMAGE_BASENAME" not supported at this time
+IMAGE_BASENAME[export] = "1"
+export PACKAGE_INSTALL ?= "${IMAGE_INSTALL} ${IMAGE_VARS}"
+
+# We need to recursively follow RDEPENDS and RRECOMMENDS for images
+do_rootfs[recrdeptask] += "do_deploy do_populate_staging"
+
+# Images are generally built explicitly, do not need to be part of world.
+EXCLUDE_FROM_WORLD = "1"
+
+USE_DEVFS ?= "0"
PID = "${@os.getpid()}"
diff --git a/classes/rootfs_ipk.bbclass b/classes/rootfs_ipk.bbclass
index e752449305..f5714bd1a3 100644
--- a/classes/rootfs_ipk.bbclass
+++ b/classes/rootfs_ipk.bbclass
@@ -21,7 +21,10 @@ ONLINE_PACKAGE_MANAGEMENT ?= "full"
# Which packages to not install on the basis of a recommendation
BAD_RECOMMENDATIONS ?= ""
-DISTRO_EXTRA_RDEPENDS += "${@base_conditional("ONLINE_PACKAGE_MANAGEMENT", "none", "", "opkg opkg-collateral", d)}"
+IPKG_VARIANT ?= "opkg"
+
+RDEPENDS_append = " ${@base_conditional("ONLINE_PACKAGE_MANAGEMENT", "none", "", "${IPKG_VARIANT} opkg-collateral", d)}"
+PACKAGE_INSTALL_append = " ${@base_conditional("ONLINE_PACKAGE_MANAGEMENT", "none", "", "${IPKG_VARIANT} opkg-collateral", d)}"
fakeroot rootfs_ipk_do_rootfs () {
set -x
diff --git a/conf/checksums.ini b/conf/checksums.ini
index 5efcecf298..9492b94809 100644
--- a/conf/checksums.ini
+++ b/conf/checksums.ini
@@ -4618,6 +4618,10 @@ sha256=635d6d07e5a4d615e599c051166af965baa754f9ff7435e746de1a5d2a5c0d56
md5=1c1c5177aea9a23b45b9b3f5b3241819
sha256=635d6d07e5a4d615e599c051166af965baa754f9ff7435e746de1a5d2a5c0d56
+[http://qa.debian.org/watch/sf.php/e2fsprogs/e2fsprogs-1.41.4.tar.gz]
+md5=59033388df36987d2b9c9bbf7e19bd57
+sha256=2cc10fee2b29add737e454eb634513135b34a638f7ca2b18364864fe089020dc
+
[http://downloads.sourceforge.net/e2fsprogs/e2fsprogs-libs-1.33.tar.gz]
md5=c7545bb05e0c2fc59174f0dc455c6519
sha256=a65d064bee3e97c164d07a490692db0e73da8da10019ad9a89866706c93ae703
diff --git a/conf/distro/angstrom-2008.1.conf b/conf/distro/angstrom-2008.1.conf
index 062cba7ac6..27545cebde 100644
--- a/conf/distro/angstrom-2008.1.conf
+++ b/conf/distro/angstrom-2008.1.conf
@@ -181,6 +181,12 @@ PREFERRED_PROVIDER_task-bootstrap = "task-bootstrap"
ARM_ABI ?= "${@['','oabi'][bb.data.getVar('MACHINE',d) in ['collie','h3600', 'h3800', 'simpad', 'htcwallaby']]}"
require conf/distro/include/angstrom${ARM_ABI}.inc
+
+
+# If we're using an .ipk based rootfs, we want to have opkg-nogpg installed so postinst script can run
+# We also take this opportunity to inject angstrom-version and the feed configs into the rootfs
+IPKG_VARIANT = "opkg-nogpg angstrom-version ${ANGSTROM_FEED_CONFIGS}"
+
# do some task-base stuff here
# We want to ship extra debug utils in the rootfs when doing a debug build
diff --git a/conf/distro/slugos.conf b/conf/distro/slugos.conf
index 6182591d6a..3e816f7c58 100644
--- a/conf/distro/slugos.conf
+++ b/conf/distro/slugos.conf
@@ -12,6 +12,8 @@ DISTRO_TYPE = "alpha"
TARGET_ARCH ?= "armeb"
ARM_INSTRUCTION_SET = "arm"
TARGET_OS = "linux-gnueabi"
+IPKG_VARIANT ?= "opkg-nogpg-nocurl"
+IMAGE_INITSCRIPTS ?= "initscripts-slugos"
require conf/distro/include/slugos.inc
diff --git a/packages/bluez/bluez4_4.30.bb b/packages/bluez/bluez4_4.30.bb
index 6499e3ff43..920c2ee05d 100644
--- a/packages/bluez/bluez4_4.30.bb
+++ b/packages/bluez/bluez4_4.30.bb
@@ -4,7 +4,7 @@ PRIORITY = "optional"
DEPENDS = "gst-plugins-base alsa-lib libusb-compat libusb1 dbus-glib"
HOMEPAGE = "http://www.bluez.org"
LICENSE = "GPL"
-PR = "r0"
+PR = "r2"
SRC_URI = "\
http://www.kernel.org/pub/linux/bluetooth/bluez-${PV}.tar.gz \
diff --git a/packages/busybox/busybox-static-1.11.3/B921600.patch b/packages/busybox/busybox-static-1.11.3/B921600.patch
new file mode 100644
index 0000000000..61cc32b0e5
--- /dev/null
+++ b/packages/busybox/busybox-static-1.11.3/B921600.patch
@@ -0,0 +1,13 @@
+diff -upNr busybox-1.7.2/libbb/speed_table.c busybox-1.7.2-921600/libbb/speed_table.c
+--- busybox-1.7.2/libbb/speed_table.c 2007-09-03 13:48:41.000000000 +0200
++++ busybox-1.7.2-921600/libbb/speed_table.c 2008-10-09 16:23:26.269592899 +0200
+@@ -52,6 +52,9 @@ static const struct speed_map speeds[] =
+ #ifdef B460800
+ {B460800, 460800/256 + 0x8000U},
+ #endif
++#ifdef B921600
++ {B921600, 921600/256 + 0x8000U},
++#endif
+ };
+
+ enum { NUM_SPEEDS = ARRAY_SIZE(speeds) };
diff --git a/packages/dsplink/gstreamer-ti_svn.bb b/packages/dsplink/gstreamer-ti_svn.bb
index b7ad411e32..dbf6671f08 100644
--- a/packages/dsplink/gstreamer-ti_svn.bb
+++ b/packages/dsplink/gstreamer-ti_svn.bb
@@ -1,7 +1,7 @@
DEPENDS = "ti-codec-engine ti-dmai gstreamer gst-plugins-base gst-plugins-good gst-plugins-ugly libid3tag liboil libmad"
SRC_URI = "svn://omapzoom.org/svn/gstreamer_ti/trunk;module=gstreamer_ti;proto=https"
-SRCREV = "87"
+SRCREV = "110"
PR = "r1"
diff --git a/packages/e2fsprogs/e2fsprogs_1.41.4.bb b/packages/e2fsprogs/e2fsprogs_1.41.4.bb
new file mode 100644
index 0000000000..dda4b81582
--- /dev/null
+++ b/packages/e2fsprogs/e2fsprogs_1.41.4.bb
@@ -0,0 +1,101 @@
+require e2fsprogs.inc
+
+PR = "r1"
+
+#SRC_URI += "file://no-hardlinks.patch;patch=1 \
+# file://mkinstalldirs.patch;patch=1 \
+# "
+
+do_configure() {
+ # avoid autoreconf
+ oe_runconf $@
+}
+
+do_compile_prepend () {
+ find ./ -print|xargs chmod u=rwX
+ ( cd util; ${BUILD_CC} subst.c -o subst )
+}
+
+ext2fsheaders = "ext2_ext_attr.h bitops.h ext2_err.h \
+ ext2_types.h ext2_fs.h ext2_io.h \
+ ext2fs.h"
+e2pheaders = "e2p.h"
+
+do_stage () {
+ oe_libinstall -a -C lib libe2p ${STAGING_LIBDIR}/
+ oe_libinstall -a -C lib libext2fs ${STAGING_LIBDIR}/
+ install -d ${STAGING_INCDIR}/e2p
+ for h in ${e2pheaders}; do
+ install -m 0644 lib/e2p/$h ${STAGING_INCDIR}/e2p/ || die "failed to install $h"
+ done
+ install -d ${STAGING_INCDIR}/ext2fs
+ for h in ${ext2fsheaders}; do
+ install -m 0644 lib/ext2fs/$h ${STAGING_INCDIR}/ext2fs/ || die "failed to install $h"
+ done
+ autotools_stage_all
+}
+
+# blkid used to be part of e2fsprogs but is useful outside, add it
+# as an RDEPENDS so that anything relying on it being in e2fsprogs
+# still works
+RDEPENDS_e2fsprogs = "e2fsprogs-blkid e2fsprogs-uuidgen e2fsprogs-badblocks"
+
+PACKAGES =+ "e2fsprogs-blkid e2fsprogs-uuidgen e2fsprogs-e2fsck e2fsprogs-mke2fs e2fsprogs-fsck e2fsprogs-tune2fs e2fsprogs-badblocks"
+FILES_e2fsprogs-blkid = "${base_sbindir}/blkid.${PN}"
+FILES_e2fsprogs-uuidgen = "${bindir}/uuidgen"
+FILES_e2fsprogs-fsck = "${base_sbindir}/fsck.${PN}"
+FILES_e2fsprogs-e2fsck = "${base_sbindir}/e2fsck.${PN} ${base_sbindir}/fsck.ext*.${PN}"
+FILES_e2fsprogs-mke2fs = "${base_sbindir}/mke2fs.${PN} ${base_sbindir}/mkfs.ext*.${PN}"
+FILES_e2fsprogs-tune2fs = "${base_sbindir}/tune2fs ${base_sbindir}/e2label ${base_sbindir}/findfs"
+FILES_e2fsprogs-badblocks = "${base_sbindir}/badblocks"
+
+do_install_append () {
+ mv ${D}${base_sbindir}/fsck ${D}${base_sbindir}/fsck.${PN}
+ mv ${D}${base_sbindir}/blkid ${D}${base_sbindir}/blkid.${PN}
+ mv ${D}${base_sbindir}/e2fsck ${D}${base_sbindir}/e2fsck.${PN}
+ mv ${D}${base_sbindir}/fsck.ext2 ${D}${base_sbindir}/fsck.ext2.${PN}
+ mv ${D}${base_sbindir}/fsck.ext3 ${D}${base_sbindir}/fsck.ext3.${PN}
+ mv ${D}${base_sbindir}/mke2fs ${D}${base_sbindir}/mke2fs.${PN}
+ mv ${D}${base_sbindir}/mkfs.ext2 ${D}${base_sbindir}/mkfs.ext2.${PN}
+ mv ${D}${base_sbindir}/mkfs.ext3 ${D}${base_sbindir}/mkfs.ext3.${PN}
+}
+
+pkg_postinst_e2fsprogs-fsck () {
+ update-alternatives --install ${base_sbindir}/fsck fsck fsck.${PN} 100
+}
+
+pkg_prerm_e2fsprogs-fsck () {
+ update-alternatives --remove fsck fsck.${PN}
+}
+
+pkg_postinst_e2fsprogs-blkid () {
+ update-alternatives --install ${base_sbindir}/blkid blkid blkid.${PN} 100
+}
+
+pkg_prerm_e2fsprogs-blkid () {
+ update-alternatives --remove blkid blkid.${PN}
+}
+
+pkg_postinst_e2fsprogs-e2fsck () {
+ update-alternatives --install ${base_sbindir}/e2fsck e2fsck e2fsck.${PN} 100
+ update-alternatives --install ${base_sbindir}/fsck.ext2 fsck.ext2 fsck.ext2.${PN} 100
+ update-alternatives --install ${base_sbindir}/fsck.ext3 fsck.ext3 fsck.ext3.${PN} 100
+}
+
+pkg_prerm_e2fsprogs-e2fsck () {
+ update-alternatives --remove e2fsck e2fsck.${PN}
+ update-alternatives --remove fsck.ext2 fsck.ext2.${PN}
+ update-alternatives --remove fsck.ext3 fsck.ext3.${PN}
+}
+
+pkg_postinst_e2fsprogs-mke2fs () {
+ update-alternatives --install ${base_sbindir}/mke2fs mke2fs mke2fs.${PN} 100
+ update-alternatives --install ${base_sbindir}/mkfs.ext2 mkfs.ext2 mkfs.ext2.${PN} 100
+ update-alternatives --install ${base_sbindir}/mkfs.ext3 mkfs.ext3 mkfs.ext3.${PN} 100
+}
+
+pkg_prerm_e2fsprogs-mke2fs () {
+ update-alternatives --remove mke2fs mke2fs.${PN}
+ update-alternatives --remove mkfs.ext2 mkfs.ext2.${PN}
+ update-alternatives --remove mkfs.ext3 mkfs.ext3.${PN}
+}
diff --git a/packages/gpsd/gpsd.inc b/packages/gpsd/gpsd.inc
index e4f5a9988b..1022091c6c 100644
--- a/packages/gpsd/gpsd.inc
+++ b/packages/gpsd/gpsd.inc
@@ -24,7 +24,7 @@ inherit autotools update-rc.d
INITSCRIPT_NAME = "gpsd"
INITSCRIPT_PARAMS = "defaults 35"
-export LDFLAGS = "-L${STAGING_LIBDIR} -lm"
+LDFLAGS += "-L${STAGING_LIBDIR} -lm"
export STAGING_INCDIR
export STAGING_LIBDIR
diff --git a/packages/gpsd/gpsd_2.37.bb b/packages/gpsd/gpsd_2.38.bb
index 726ba42481..58e9ebeee2 100644
--- a/packages/gpsd/gpsd_2.37.bb
+++ b/packages/gpsd/gpsd_2.38.bb
@@ -1,3 +1,3 @@
require gpsd.inc
-PR = "r2"
+PR = "r0"
diff --git a/packages/gtk-webcore/midori_git.bb b/packages/gtk-webcore/midori_git.bb
index 9354a89a43..f4039a414f 100644
--- a/packages/gtk-webcore/midori_git.bb
+++ b/packages/gtk-webcore/midori_git.bb
@@ -2,7 +2,9 @@ require midori.inc
DEPENDS += "python-native python-docutils-native"
-PV = "0.1.2+gitr${SRCREV}"
+# increment PR every time SRCREV is updated!
+PR = "r0"
+PV = "0.1.2+${PR}+gitr${SRCREV}"
SRC_URI = "http://git.xfce.org/kalikiana/midori/snapshot/midori-${SRCREV}.tar.bz2"
S = "${WORKDIR}/midori-${SRCREV}"
diff --git a/packages/initrdscripts/files/00-psplash.sh b/packages/initrdscripts/files/00-psplash.sh
index 491fe13fc3..db8aabedd7 100644
--- a/packages/initrdscripts/files/00-psplash.sh
+++ b/packages/initrdscripts/files/00-psplash.sh
@@ -1,4 +1,6 @@
-mkdir -p /mnt/.psplash
-mount tmpfs -t tmpfs /mnt/.psplash -o,size=40k
+if ! grep -Eq '\s?psplash=false\s?' /proc/cmdline; then
+ mkdir -p /mnt/.psplash
+ mount tmpfs -t tmpfs /mnt/.psplash -o,size=40k
-psplash &
+ psplash &
+fi
diff --git a/packages/initrdscripts/files/80-ext3.sh b/packages/initrdscripts/files/80-ext3.sh
index ed1909947b..1f52d391fa 100644
--- a/packages/initrdscripts/files/80-ext3.sh
+++ b/packages/initrdscripts/files/80-ext3.sh
@@ -1,7 +1,7 @@
ext3_mount () {
modprobe -q ext3
- mkdir $2
+ mkdir -p $2
mount -t ext3 -onoatime,data=journal,errors=continue $1 $2
}
diff --git a/packages/initrdscripts/files/98-aufs.sh b/packages/initrdscripts/files/98-aufs.sh
index df05418c57..5f7cc11432 100644
--- a/packages/initrdscripts/files/98-aufs.sh
+++ b/packages/initrdscripts/files/98-aufs.sh
@@ -1,7 +1,7 @@
aufs_mount () {
modprobe -q aufs
- mkdir $2 /mnt
+ mkdir -p $2 /mnt
mount -t aufs -o br:$1:$2 none /mnt
}
diff --git a/packages/initrdscripts/files/99-psplash.sh b/packages/initrdscripts/files/99-psplash.sh
index fa488cff8b..3d5f1d60d1 100644
--- a/packages/initrdscripts/files/99-psplash.sh
+++ b/packages/initrdscripts/files/99-psplash.sh
@@ -1,2 +1,4 @@
-mkdir -p /mnt/mnt/.psplash
-mount -n -o move /mnt/.psplash /mnt/mnt/.psplash
+if ! grep -Eq '\s?psplash=false\s?' /proc/cmdline; then
+ mkdir -p /mnt/mnt/.psplash
+ mount -n -o move /mnt/.psplash /mnt/mnt/.psplash
+fi
diff --git a/packages/initrdscripts/files/init.sh b/packages/initrdscripts/files/init.sh
index 5cdbab5e0d..221b8f56b9 100644
--- a/packages/initrdscripts/files/init.sh
+++ b/packages/initrdscripts/files/init.sh
@@ -35,10 +35,16 @@ read_args() {
ROOT_FSTYPE=$optarg ;;
rootdelay=*)
rootdelay=$optarg ;;
+ debug) set -x ;;
+ shell) sh ;;
esac
done
}
+do_depmod() {
+ [ -e "/lib/modules/$(uname -r)/modules.dep" ] || depmod
+}
+
load_module() {
# Cannot redir to $CONSOLE here easily - may not be set yet
echo "initramfs: Loading $module module"
@@ -66,6 +72,7 @@ fatal() {
echo "Starting initramfs boot..."
early_setup
load_modules '0*'
+do_depmod
[ -z "$CONSOLE" ] && CONSOLE="/dev/console"
diff --git a/packages/initrdscripts/initramfs-module-psplash_1.0.bb b/packages/initrdscripts/initramfs-module-psplash_1.0.bb
index a765b36ad3..1cc6f9eabc 100644
--- a/packages/initrdscripts/initramfs-module-psplash_1.0.bb
+++ b/packages/initrdscripts/initramfs-module-psplash_1.0.bb
@@ -1,5 +1,5 @@
SRC_URI = "file://00-psplash.sh file://99-psplash.sh"
-PR = "r1"
+PR = "r2"
RDEPENDS = "initramfs-uniboot psplash"
DESCRIPTION = "An initramfs module to enable psplash."
diff --git a/packages/libnetfilter-queue/libnetfilter-queue.inc b/packages/libnetfilter-queue/libnetfilter-queue.inc
new file mode 100644
index 0000000000..96ec16c330
--- /dev/null
+++ b/packages/libnetfilter-queue/libnetfilter-queue.inc
@@ -0,0 +1,22 @@
+DESCRIPTION = "libnetfilter_queue is a userspace library providing an API to \
+packets that have been queued by the kernel packet filter. It is is part of a \
+system that deprecates the old ip_queue / libipq mechanism."
+
+SECTION = "devel/libs"
+LICENSE = "GPL"
+HOMEPAGE = "http://www.netfilter.org/projects/libnetfilter_queue/index.html"
+PR = "r0"
+
+
+DEPENDS = "libnfnetlink"
+
+SRC_URI = "http://www.netfilter.org/projects/libnetfilter_queue/files/libnetfilter_queue-${PV}.tar.bz2"
+
+S = "${WORKDIR}/libnetfilter_queue-${PV}"
+
+inherit autotools pkgconfig
+
+do_stage() {
+ autotools_stage_all
+}
+
diff --git a/packages/libnetfilter-queue/libnetfilter-queue_0.0.13.bb b/packages/libnetfilter-queue/libnetfilter-queue_0.0.13.bb
index 97af3a7da5..044777c0ce 100644
--- a/packages/libnetfilter-queue/libnetfilter-queue_0.0.13.bb
+++ b/packages/libnetfilter-queue/libnetfilter-queue_0.0.13.bb
@@ -1,30 +1,2 @@
-DESCRIPTION = "libnetfilter_queue is a userspace library providing an API to \
-packets that have been queued by the kernel packet filter. It is is part of a \
-system that deprecates the old ip_queue / libipq mechanism."
-
-SECTION = "devel/libs"
-LICENSE = "GPL"
-HOMEPAGE = "http://www.netfilter.org/projects/libnetfilter_queue/index.html"
-PR = "r0"
-
-
-# This package requires libtool-cross-1.5.24 which is not the default libtool
-# used by OE (25AUG2007)
-DEPENDS = "libnfnetlink libtool-cross (>=1.5.24)"
-
-SRC_URI = "http://www.netfilter.org/projects/libnetfilter_queue/files/libnetfilter_queue-${PV}.tar.bz2"
-
-S = "${WORKDIR}/libnetfilter_queue-${PV}"
-
-inherit autotools pkgconfig
-
-do_configure() {
- gnu-configize
- libtoolize --force
- oe_runconf
-}
-
-do_stage() {
- autotools_stage_all
-}
+include libnetfilter-queue.inc
diff --git a/packages/libnetfilter-queue/libnetfilter-queue_0.0.16.bb b/packages/libnetfilter-queue/libnetfilter-queue_0.0.16.bb
new file mode 100644
index 0000000000..044777c0ce
--- /dev/null
+++ b/packages/libnetfilter-queue/libnetfilter-queue_0.0.16.bb
@@ -0,0 +1,2 @@
+include libnetfilter-queue.inc
+
diff --git a/packages/linux/linux-2.6.27/boc01/012-090115-cy3218-btns.patch b/packages/linux/linux-2.6.27/boc01/012-090115-cy3218-btns.patch
deleted file mode 100644
index 2529be5274..0000000000
--- a/packages/linux/linux-2.6.27/boc01/012-090115-cy3218-btns.patch
+++ /dev/null
@@ -1,406 +0,0 @@
-Index: linux-2.6.27/drivers/input/misc/cy3218-btns.c
-===================================================================
---- /dev/null
-+++ linux-2.6.27/drivers/input/misc/cy3218-btns.c
-@@ -0,0 +1,373 @@
-+/*
-+ * CAPSENSE Interface driver
-+ *
-+ *
-+ * Copyright (C) 2008, CenoSYS (www.cenosys.com).
-+ *
-+ * Guillaume Ligneul <guillaume.ligneul@gmail.com>
-+ * Jeremy Lainé <jeremy.laine@bolloretelecom.eu>
-+ * Sylvain Giroudon <sylvain.giroudon@goobie.fr>
-+ *
-+ * This software program is licensed subject to the GNU General Public License
-+ * (GPL).Version 2,June 1991, available at http://www.fsf.org/copyleft/gpl.html
-+ */
-+
-+#include <linux/init.h>
-+#include <linux/input-polldev.h>
-+#include <linux/ioport.h>
-+#include <linux/module.h>
-+#include <linux/i2c.h>
-+#include <linux/leds.h>
-+
-+static int capsense_attach_adapter(struct i2c_adapter *adapter);
-+static int capsense_detach_client(struct i2c_client *client);
-+#ifdef CONFIG_PM
-+static int capsense_suspend(struct i2c_client *client, pm_message_t mesg);
-+static int capsense_resume(struct i2c_client *client);
-+#endif
-+
-+#define CAPSENSE_NAME "Capsense"
-+
-+/* i2c configuration */
-+#define CAPSENSE_I2C_ADDR 0x25
-+// To debug (may be add in include/linux/i2c-id.h)
-+#define I2C_DRIVERID_CAPSENSE 98
-+
-+#define BUTTONS_POLL_INTERVAL 30 /* msec */
-+
-+#define CAP_OUTPUT_PORT(port) (0x04+(port))
-+#define CAP_OP_SEL(port,bit) (0x1C+(25*(port))+(5*(bit)))
-+#define CAP_READ_STATUS(port) (0x88+(port))
-+
-+#define MASK0 0x10
-+#define MASK1 0x4
-+#define MASK2 0x8
-+#define MASK3 0x1
-+
-+#define CAP_NLEDS 5
-+
-+static int poll_interval = BUTTONS_POLL_INTERVAL;
-+module_param_named(poll, poll_interval, uint, 0);
-+MODULE_PARM_DESC(poll, "poll interval in msec (30=default)");
-+
-+static const unsigned short normal_i2c[] = {
-+ CAPSENSE_I2C_ADDR , I2C_CLIENT_END
-+};
-+I2C_CLIENT_INSMOD;
-+
-+static struct i2c_driver capsense_driver = {
-+ .driver = {
-+ .name = CAPSENSE_NAME,
-+ },
-+ .id = I2C_DRIVERID_CAPSENSE,
-+ .attach_adapter = &capsense_attach_adapter,
-+ .detach_client = &capsense_detach_client,
-+#ifdef CONFIG_PM
-+ .suspend = &capsense_suspend,
-+ .resume = &capsense_resume,
-+#endif
-+};
-+
-+struct cy3218_led {
-+ struct led_classdev cdev;
-+ struct cy3218 *capsense;
-+ int port;
-+ int bit;
-+};
-+
-+struct cy3218 {
-+ struct input_polled_dev *ipdev;
-+ struct i2c_client client;
-+ unsigned char key_state;
-+ struct cy3218_led leds[CAP_NLEDS];
-+ unsigned char led_state[2];
-+ struct mutex mutex;
-+};
-+
-+static unsigned short keymap[] = {
-+ // GP0
-+ KEY_F1,
-+ KEY_ENTER,
-+ KEY_DOWN,
-+ KEY_BACKSPACE,
-+ // GP1
-+ KEY_UP,
-+};
-+
-+struct cy3218_ledmap {
-+ char *name;
-+ int port, bit;
-+};
-+
-+static struct cy3218_ledmap ledmap[CAP_NLEDS] = {
-+ { "capsense:blue:back", 0, 1 },
-+ { "capsense:blue:info", 1, 0 },
-+ { "capsense:blue:down", 1, 1 },
-+ { "capsense:blue:ok", 1, 2 },
-+ { "capsense:blue:up", 1, 3 },
-+};
-+
-+static void handle_buttons(struct input_polled_dev *dev)
-+{
-+ struct cy3218 *capsense = dev->private;
-+ u8 port_value;
-+ u8 new_state = 0;
-+ u8 changed;
-+ int i;
-+
-+ mutex_lock(&capsense->mutex);
-+
-+ // read status
-+ port_value = i2c_smbus_read_byte_data(&capsense->client, CAP_READ_STATUS(0));
-+ if (port_value & MASK0) new_state |= 0x01;
-+ if (port_value & MASK1) new_state |= 0x02;
-+ if (port_value & MASK2) new_state |= 0x04;
-+ if (port_value & MASK3) new_state |= 0x08;
-+
-+ port_value = i2c_smbus_read_byte_data(&capsense->client, CAP_READ_STATUS(1));
-+ if (port_value & MASK0) new_state |= 0x10;
-+
-+ mutex_unlock(&capsense->mutex);
-+
-+ // update keyboard state
-+ changed = capsense->key_state ^ new_state;
-+ for (i = 0; i < ARRAY_SIZE(keymap); i++)
-+ if (changed & (1 << i))
-+ input_report_key(dev->input, keymap[i], (new_state & (1 << i)));
-+ capsense->key_state = new_state;
-+ input_sync(dev->input);
-+}
-+
-+
-+static void
-+capsense_led_set(struct led_classdev *led_cdev,
-+ enum led_brightness value)
-+{
-+ struct cy3218_led *led = (struct cy3218_led *) led_cdev;
-+ struct cy3218 *capsense = led->capsense;
-+ int port = led->port;
-+ unsigned char mask = (1 << led->bit);
-+
-+ if ( value )
-+ capsense->led_state[port] |= mask;
-+ else
-+ capsense->led_state[port] &= ~mask;
-+
-+ mutex_lock(&capsense->mutex);
-+ i2c_smbus_write_byte_data(&capsense->client, CAP_OUTPUT_PORT(port), capsense->led_state[port]);
-+ mutex_unlock(&capsense->mutex);
-+}
-+
-+static void
-+capsense_led_enable(struct cy3218_led *led, int state)
-+{
-+ struct cy3218 *capsense = led->capsense;
-+
-+ mutex_lock(&capsense->mutex);
-+ i2c_smbus_write_byte_data(&capsense->client, CAP_OP_SEL(led->port, led->bit), state ? 0x00 : 0x80);
-+ mutex_unlock(&capsense->mutex);
-+}
-+
-+static int
-+capsense_led_init(struct cy3218 *capsense)
-+{
-+ int i;
-+ int ret;
-+
-+ for (i = 0; i < CAP_NLEDS; i++) {
-+ struct cy3218_led *led = &(capsense->leds[i]);
-+
-+ led->cdev.name = ledmap[i].name;
-+ led->cdev.brightness_set = capsense_led_set;
-+ led->capsense = capsense;
-+ led->port = ledmap[i].port;
-+ led->bit = ledmap[i].bit;
-+
-+ ret = led_classdev_register(&capsense->ipdev->input->dev, &led->cdev);
-+ if ( ret < 0 )
-+ return -1;
-+
-+ capsense_led_enable(led, 1);
-+ }
-+
-+ /* Switch all leds off */
-+ mutex_lock(&capsense->mutex);
-+
-+ capsense->led_state[0] = 0x00;
-+ i2c_smbus_write_byte_data(&capsense->client, CAP_OUTPUT_PORT(0), 0x00);
-+
-+ capsense->led_state[1] = 0x00;
-+ i2c_smbus_write_byte_data(&capsense->client, CAP_OUTPUT_PORT(1), 0x00);
-+
-+ mutex_unlock(&capsense->mutex);
-+
-+ return 0;
-+}
-+
-+
-+static void
-+capsense_led_exit(struct cy3218 *capsense)
-+{
-+ int i;
-+
-+ for (i = 0; i < CAP_NLEDS; i++) {
-+ led_classdev_unregister(&capsense->leds[i].cdev);
-+ }
-+}
-+
-+
-+static inline void
-+capsense_led_suspend(struct cy3218 *capsense)
-+{
-+ int i;
-+
-+ for (i = 0; i < CAP_NLEDS; i++) {
-+ struct cy3218_led *led = &(capsense->leds[i]);
-+
-+ led_classdev_suspend(&led->cdev);
-+ capsense_led_enable(led, 0);
-+ }
-+}
-+
-+
-+static inline void
-+capsense_led_resume(struct cy3218 *capsense)
-+{
-+ int i;
-+
-+ for (i = 0; i < CAP_NLEDS; i++) {
-+ struct cy3218_led *led = &(capsense->leds[i]);
-+
-+ capsense_led_enable(led, 1);
-+ led_classdev_resume(&led->cdev);
-+ }
-+}
-+
-+
-+static int
-+capsense_probe(struct i2c_adapter *adapter, int addr, int kind)
-+{
-+ struct cy3218 *capsense;
-+ struct input_polled_dev *ipdev;
-+ struct input_dev *input;
-+ int rc = 0, err = -ENOMEM, i=0;
-+
-+ capsense = kzalloc(sizeof(*capsense), GFP_KERNEL);
-+ if (!capsense)
-+ goto failout;
-+
-+ mutex_init(&capsense->mutex);
-+
-+ if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) {
-+ goto failout;
-+ }
-+
-+ ipdev = input_allocate_polled_device();
-+ if (!ipdev)
-+ goto failout;
-+
-+ capsense->key_state = 0;
-+ capsense->ipdev = ipdev;
-+ capsense->client.adapter = adapter;
-+ capsense->client.addr = addr;
-+ capsense->client.driver = &capsense_driver;
-+ strlcpy(capsense->client.name, CAPSENSE_NAME, I2C_NAME_SIZE);
-+ i2c_set_clientdata(&capsense->client, capsense);
-+
-+ rc = i2c_attach_client(&capsense->client);
-+ if (rc)
-+ goto out_attach;
-+
-+ ipdev->poll = handle_buttons;
-+ ipdev->private = capsense;
-+ ipdev->poll_interval = poll_interval;
-+
-+ input = ipdev->input;
-+ input->name = "Capsense buttons";
-+ input->phys = "capsense/input0";
-+ input->id.bustype = BUS_I2C;
-+ input->dev.parent = &capsense->client.dev;
-+
-+ input->keycode = keymap;
-+ input->keycodemax = ARRAY_SIZE(keymap);
-+ input->keycodesize = sizeof(unsigned short);
-+
-+ input_set_capability(input, EV_MSC, MSC_SCAN);
-+ set_bit(EV_KEY, ipdev->input->evbit);
-+
-+ for (i = 0; i < ARRAY_SIZE(keymap); i++)
-+ set_bit(keymap[i], ipdev->input->keybit);
-+
-+ rc = input_register_polled_device(ipdev);
-+ if(rc)
-+ goto out_polled;
-+
-+ if ( capsense_led_init(capsense) )
-+ goto out_registered;
-+
-+ return 0;
-+
-+out_registered:
-+ input_unregister_polled_device(ipdev);
-+out_polled:
-+ i2c_detach_client(&capsense->client);
-+out_attach:
-+ input_free_polled_device(ipdev);
-+failout:
-+ return err;
-+}
-+
-+static int
-+capsense_attach_adapter (struct i2c_adapter *adapter)
-+{
-+ return i2c_probe(adapter, &addr_data, capsense_probe);
-+}
-+
-+static int
-+capsense_detach_client(struct i2c_client *client)
-+{
-+ struct cy3218 *capsense = i2c_get_clientdata(client);
-+
-+ capsense_led_exit(capsense);
-+ input_unregister_polled_device(capsense->ipdev);
-+ i2c_detach_client(&capsense->client);
-+ input_free_polled_device(capsense->ipdev);
-+ return 0;
-+}
-+
-+#ifdef CONFIG_PM
-+static int capsense_suspend(struct i2c_client *client, pm_message_t mesg)
-+{
-+ struct cy3218 *capsense = i2c_get_clientdata(client);
-+
-+ capsense_led_suspend(capsense);
-+
-+ return 0;
-+}
-+
-+static int capsense_resume(struct i2c_client *client)
-+{
-+ struct cy3218 *capsense = i2c_get_clientdata(client);
-+
-+ capsense_led_resume(capsense);
-+
-+ return 0;
-+}
-+#endif
-+
-+
-+static int __init capsense_buttons_init(void)
-+{
-+ return i2c_add_driver(&capsense_driver);
-+}
-+
-+static void __exit capsense_buttons_exit(void)
-+{
-+ i2c_del_driver(&capsense_driver);
-+}
-+
-+MODULE_AUTHOR("Guillaume Ligneul <guillaume.ligneul@cenosys.com>");
-+MODULE_DESCRIPTION("Capsense CY3218 Input driver");
-+MODULE_LICENSE("GPL");
-+module_init(capsense_buttons_init);
-+module_exit(capsense_buttons_exit);
-Index: linux-2.6.27/drivers/input/misc/Kconfig
-===================================================================
---- linux-2.6.27.orig/drivers/input/misc/Kconfig
-+++ linux-2.6.27/drivers/input/misc/Kconfig
-@@ -207,4 +207,13 @@ config HP_SDC_RTC
- Say Y here if you want to support the built-in real time clock
- of the HP SDC controller.
-
-+config INPUT_CAPSENSE_BTNS
-+ tristate "CAPSENSE CY3218 button interface"
-+ select INPUT_POLLDEV
-+ select LEDS_CLASS
-+ help
-+ To compile this driver as a module, choose M here: the
-+ module will be called cy3218-btns.
-+ To change poll interval, invoque poll parameter in msecs.
-+
- endif
-Index: linux-2.6.27/drivers/input/misc/Makefile
-===================================================================
---- linux-2.6.27.orig/drivers/input/misc/Makefile
-+++ linux-2.6.27/drivers/input/misc/Makefile
-@@ -20,3 +20,5 @@ obj-$(CONFIG_HP_SDC_RTC) += hp_sdc_rtc.
- obj-$(CONFIG_INPUT_UINPUT) += uinput.o
- obj-$(CONFIG_INPUT_APANEL) += apanel.o
- obj-$(CONFIG_INPUT_SGI_BTNS) += sgi_btns.o
-+obj-$(CONFIG_INPUT_CAPSENSE_BTNS) += cy3218-btns.o
-+
diff --git a/packages/linux/linux-2.6.27/boc01/012-090219-capsense.patch b/packages/linux/linux-2.6.27/boc01/012-090219-capsense.patch
new file mode 100644
index 0000000000..fed8218427
--- /dev/null
+++ b/packages/linux/linux-2.6.27/boc01/012-090219-capsense.patch
@@ -0,0 +1,865 @@
+Index: linux-2.6.27/drivers/input/misc/Kconfig
+===================================================================
+--- linux-2.6.27.orig/drivers/input/misc/Kconfig
++++ linux-2.6.27/drivers/input/misc/Kconfig
+@@ -207,4 +207,13 @@ config HP_SDC_RTC
+ Say Y here if you want to support the built-in real time clock
+ of the HP SDC controller.
+
++config INPUT_CAPSENSE_BTNS
++ tristate "CAPSENSE CY8C201xx buttons interface"
++ select INPUT_POLLDEV
++ select LEDS_CLASS
++ help
++ To compile this driver as a module, choose M here:
++ the module will be called capsense-btns.
++ To change poll interval, invoque poll parameter in msecs.
++
+ endif
+Index: linux-2.6.27/drivers/input/misc/Makefile
+===================================================================
+--- linux-2.6.27.orig/drivers/input/misc/Makefile
++++ linux-2.6.27/drivers/input/misc/Makefile
+@@ -20,3 +20,4 @@ obj-$(CONFIG_HP_SDC_RTC) += hp_sdc_rtc.
+ obj-$(CONFIG_INPUT_UINPUT) += uinput.o
+ obj-$(CONFIG_INPUT_APANEL) += apanel.o
+ obj-$(CONFIG_INPUT_SGI_BTNS) += sgi_btns.o
++obj-$(CONFIG_INPUT_CAPSENSE_BTNS) += capsense-btns.o
+Index: linux-2.6.27/drivers/input/misc/capsense-btns.c
+===================================================================
+--- /dev/null
++++ linux-2.6.27/drivers/input/misc/capsense-btns.c
+@@ -0,0 +1,438 @@
++/*
++ * CAPSENSE Interface driver
++ *
++ *
++ * Copyright (C) 2008, CenoSYS (www.cenosys.com).
++ *
++ * Guillaume Ligneul <guillaume.ligneul@gmail.com>
++ * Jeremy Lainé <jeremy.laine@bolloretelecom.eu>
++ * Sylvain Giroudon <sylvain.giroudon@goobie.fr>
++ *
++ * This software program is licensed subject to the GNU General Public License
++ * (GPL).Version 2,June 1991, available at http://www.fsf.org/copyleft/gpl.html
++ */
++
++#include <linux/init.h>
++#include <linux/input-polldev.h>
++#include <linux/ioport.h>
++#include <linux/module.h>
++#include <linux/i2c.h>
++#include <linux/leds.h>
++
++
++static int capsense_attach_adapter(struct i2c_adapter *adapter);
++static int capsense_detach_client(struct i2c_client *client);
++#ifdef CONFIG_PM
++static int capsense_suspend(struct i2c_client *client, pm_message_t mesg);
++static int capsense_resume(struct i2c_client *client);
++#endif
++
++#define DRIVER_NAME "capsense"
++
++/* i2c configuration */
++#define CAPSENSE_I2C_ADDR 0x25
++// To debug (may be add in include/linux/i2c-id.h)
++#define I2C_DRIVERID_CAPSENSE 98
++
++#define BUTTONS_POLL_INTERVAL 30 /* msec */
++
++#define CAP_OUTPUT_PORT(port) (0x04+(port))
++#define CAP_OP_SEL(port,bit) (0x1C+(25*(port))+(5*(bit)))
++#define CAP_READ_STATUS(port) (0x88+(port))
++
++#define CAP_CS(command,port,bit) ((command)+(5*(port))+(bit))
++#define CAP_CS_FINGER_TH(port,bit) CAP_CS(0x61,port,bit)
++#define CAP_CS_IDAC(port,bit) CAP_CS(0x6B,port,bit)
++
++#define CAP_DEVICE_ID 0x7A
++#define CAP_DEVICE_STATUS 0x7B
++#define CAP_I2C_ADDR_DM 0x7C
++
++#define CAP_COMMAND_REG 0xA0
++#define CAP_COMMAND_STORE_NVM 0x01
++#define CAP_COMMAND_RESTORE_FACTORY 0x02
++#define CAP_COMMAND_RECONFIGURE 0x06
++#define CAP_COMMAND_NORMAL_MODE 0x07
++#define CAP_COMMAND_SETUP_MODE 0x08
++
++#define CAP_NLEDS 5
++
++static int poll_interval = BUTTONS_POLL_INTERVAL;
++module_param_named(poll, poll_interval, uint, 0);
++MODULE_PARM_DESC(poll, "poll interval in msec (30=default)");
++
++static const unsigned short normal_i2c[] = {
++ CAPSENSE_I2C_ADDR , I2C_CLIENT_END
++};
++I2C_CLIENT_INSMOD;
++
++static struct i2c_driver capsense_driver = {
++ .driver = {
++ .name = DRIVER_NAME,
++ },
++ .id = I2C_DRIVERID_CAPSENSE,
++ .attach_adapter = &capsense_attach_adapter,
++ .detach_client = &capsense_detach_client,
++#ifdef CONFIG_PM
++ .suspend = &capsense_suspend,
++ .resume = &capsense_resume,
++#endif
++};
++
++struct capsense_led {
++ struct led_classdev cdev;
++ struct capsense_ctx *capsense;
++ int port;
++ int bit;
++};
++
++struct capsense_ctx {
++ struct input_polled_dev *ipdev;
++ struct i2c_client client;
++ unsigned char key_state;
++ struct capsense_led leds[CAP_NLEDS];
++ unsigned char led_state[2];
++ struct mutex mutex;
++};
++
++static unsigned short input_keymap[] = {
++ // GP0
++ KEY_F1,
++ KEY_ENTER,
++ KEY_DOWN,
++ KEY_BACKSPACE,
++ // GP1
++ KEY_UP,
++};
++
++struct capsense_keymap {
++ char *name;
++ int port, bit;
++};
++
++static struct capsense_keymap phys_keymap[] = {
++ { "info", 0, 4 },
++ { "ok", 0, 2 },
++ { "down", 0, 3 },
++ { "back", 0, 0 },
++ { "up", 1, 4 },
++};
++
++
++struct capsense_ledmap {
++ char *name;
++ int port, bit;
++};
++
++static struct capsense_ledmap ledmap[CAP_NLEDS] = {
++ { "capsense:blue:back", 0, 1 },
++ { "capsense:blue:info", 1, 0 },
++ { "capsense:blue:down", 1, 1 },
++ { "capsense:blue:ok", 1, 2 },
++ { "capsense:blue:up", 1, 3 },
++};
++
++
++/*
++ * Buttons events handling
++ */
++
++static void handle_buttons(struct input_polled_dev *dev)
++{
++ struct capsense_ctx *capsense = dev->private;
++ u8 port_value;
++ u8 new_state = 0;
++ int port;
++ u8 changed;
++ int i;
++
++ mutex_lock(&capsense->mutex);
++
++ // read status
++ port = -1;
++ port_value = 0;
++ for (i = 0; i < ARRAY_SIZE(phys_keymap); i++) {
++ if ( phys_keymap[i].port != port ) {
++ port = phys_keymap[i].port;
++ port_value = i2c_smbus_read_byte_data(&capsense->client, CAP_READ_STATUS(port));
++ }
++
++ if ( port_value & (1 << phys_keymap[i].bit) )
++ new_state |= (1 << i);
++ }
++
++ mutex_unlock(&capsense->mutex);
++
++ // update keyboard state
++ changed = capsense->key_state ^ new_state;
++ for (i = 0; i < ARRAY_SIZE(input_keymap); i++)
++ if (changed & (1 << i))
++ input_report_key(dev->input, input_keymap[i], (new_state & (1 << i)));
++ capsense->key_state = new_state;
++ input_sync(dev->input);
++}
++
++
++/*
++ * LEDs management
++ */
++
++static void
++capsense_led_set(struct led_classdev *led_cdev,
++ enum led_brightness value)
++{
++ struct capsense_led *led = (struct capsense_led *) led_cdev;
++ struct capsense_ctx *capsense = led->capsense;
++ int port = led->port;
++ unsigned char mask = (1 << led->bit);
++
++ if ( value )
++ capsense->led_state[port] |= mask;
++ else
++ capsense->led_state[port] &= ~mask;
++
++ mutex_lock(&capsense->mutex);
++ i2c_smbus_write_byte_data(&capsense->client, CAP_OUTPUT_PORT(port), capsense->led_state[port]);
++ mutex_unlock(&capsense->mutex);
++}
++
++static void
++capsense_led_enable(struct capsense_led *led, int state)
++{
++ struct capsense_ctx *capsense = led->capsense;
++
++ mutex_lock(&capsense->mutex);
++ i2c_smbus_write_byte_data(&capsense->client, CAP_OP_SEL(led->port, led->bit), state ? 0x00 : 0x80);
++ mutex_unlock(&capsense->mutex);
++}
++
++static int
++capsense_led_init(struct capsense_ctx *capsense)
++{
++ int i;
++ int ret;
++
++ for (i = 0; i < CAP_NLEDS; i++) {
++ struct capsense_led *led = &(capsense->leds[i]);
++
++ led->cdev.name = ledmap[i].name;
++ led->cdev.brightness_set = capsense_led_set;
++ led->capsense = capsense;
++ led->port = ledmap[i].port;
++ led->bit = ledmap[i].bit;
++
++ ret = led_classdev_register(&capsense->ipdev->input->dev, &led->cdev);
++ if ( ret < 0 )
++ return -1;
++
++ capsense_led_enable(led, 1);
++ }
++
++ /* Switch all leds off */
++ mutex_lock(&capsense->mutex);
++
++ capsense->led_state[0] = 0x00;
++ i2c_smbus_write_byte_data(&capsense->client, CAP_OUTPUT_PORT(0), 0x00);
++
++ capsense->led_state[1] = 0x00;
++ i2c_smbus_write_byte_data(&capsense->client, CAP_OUTPUT_PORT(1), 0x00);
++
++ mutex_unlock(&capsense->mutex);
++
++ return 0;
++}
++
++
++static void
++capsense_led_exit(struct capsense_ctx *capsense)
++{
++ int i;
++
++ for (i = 0; i < CAP_NLEDS; i++) {
++ led_classdev_unregister(&capsense->leds[i].cdev);
++ }
++}
++
++
++static inline void
++capsense_led_suspend(struct capsense_ctx *capsense)
++{
++ int i;
++
++ for (i = 0; i < CAP_NLEDS; i++) {
++ struct capsense_led *led = &(capsense->leds[i]);
++
++ led_classdev_suspend(&led->cdev);
++ capsense_led_enable(led, 0);
++ }
++}
++
++
++static inline void
++capsense_led_resume(struct capsense_ctx *capsense)
++{
++ int i;
++
++ for (i = 0; i < CAP_NLEDS; i++) {
++ struct capsense_led *led = &(capsense->leds[i]);
++
++ capsense_led_enable(led, 1);
++ led_classdev_resume(&led->cdev);
++ }
++}
++
++
++/*
++ * Device configuration through procfs entries
++ */
++
++#ifdef CONFIG_PROC_FS
++#include "capsense-procfs.c"
++#endif
++
++
++/*
++ * Device initialisation
++ */
++
++static int
++capsense_probe(struct i2c_adapter *adapter, int addr, int kind)
++{
++ struct capsense_ctx *capsense;
++ struct input_polled_dev *ipdev;
++ struct input_dev *input;
++ int rc = 0, err = -ENOMEM, i=0;
++
++ capsense = kzalloc(sizeof(*capsense), GFP_KERNEL);
++ if (!capsense)
++ goto failout;
++
++ mutex_init(&capsense->mutex);
++
++ if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) {
++ goto failout;
++ }
++
++ ipdev = input_allocate_polled_device();
++ if (!ipdev)
++ goto failout;
++
++ capsense->key_state = 0;
++ capsense->ipdev = ipdev;
++ capsense->client.adapter = adapter;
++ capsense->client.addr = addr;
++ capsense->client.driver = &capsense_driver;
++ strlcpy(capsense->client.name, DRIVER_NAME, I2C_NAME_SIZE);
++ i2c_set_clientdata(&capsense->client, capsense);
++
++ rc = i2c_attach_client(&capsense->client);
++ if (rc)
++ goto out_attach;
++
++ ipdev->poll = handle_buttons;
++ ipdev->private = capsense;
++ ipdev->poll_interval = poll_interval;
++
++ input = ipdev->input;
++ input->name = "Capsense buttons";
++ input->phys = "capsense/input0";
++ input->id.bustype = BUS_I2C;
++ input->dev.parent = &capsense->client.dev;
++
++ input->keycode = input_keymap;
++ input->keycodemax = ARRAY_SIZE(input_keymap);
++ input->keycodesize = sizeof(unsigned short);
++
++ input_set_capability(input, EV_MSC, MSC_SCAN);
++ set_bit(EV_KEY, ipdev->input->evbit);
++
++ for (i = 0; i < ARRAY_SIZE(input_keymap); i++)
++ set_bit(input_keymap[i], ipdev->input->keybit);
++
++ rc = input_register_polled_device(ipdev);
++ if(rc)
++ goto out_polled;
++
++ if ( capsense_led_init(capsense) )
++ goto out_registered;
++
++#ifdef CONFIG_PROC_FS
++ /* Create /proc entries for hardware device configuration */
++ capsense_proc_init(capsense);
++#endif
++
++ return 0;
++
++out_registered:
++ input_unregister_polled_device(ipdev);
++out_polled:
++ i2c_detach_client(&capsense->client);
++out_attach:
++ input_free_polled_device(ipdev);
++failout:
++ return err;
++}
++
++static int
++capsense_attach_adapter (struct i2c_adapter *adapter)
++{
++ return i2c_probe(adapter, &addr_data, capsense_probe);
++}
++
++static int
++capsense_detach_client(struct i2c_client *client)
++{
++ struct capsense_ctx *capsense = i2c_get_clientdata(client);
++
++ capsense_led_exit(capsense);
++ input_unregister_polled_device(capsense->ipdev);
++ i2c_detach_client(&capsense->client);
++ input_free_polled_device(capsense->ipdev);
++ return 0;
++}
++
++
++/*
++ * Power management
++ */
++
++#ifdef CONFIG_PM
++static int capsense_suspend(struct i2c_client *client, pm_message_t mesg)
++{
++ struct capsense_ctx *capsense = i2c_get_clientdata(client);
++
++ capsense_led_suspend(capsense);
++
++ return 0;
++}
++
++static int capsense_resume(struct i2c_client *client)
++{
++ struct capsense_ctx *capsense = i2c_get_clientdata(client);
++
++ capsense_led_resume(capsense);
++
++ return 0;
++}
++#endif
++
++
++/*
++ * Driver initialisation
++ */
++
++static int __init capsense_buttons_init(void)
++{
++ return i2c_add_driver(&capsense_driver);
++}
++
++static void __exit capsense_buttons_exit(void)
++{
++ i2c_del_driver(&capsense_driver);
++}
++
++MODULE_AUTHOR("Guillaume Ligneul <guillaume.ligneul@cenosys.com>");
++MODULE_DESCRIPTION("Capsense CY8C201xx Input driver");
++MODULE_LICENSE("GPL");
++module_init(capsense_buttons_init);
++module_exit(capsense_buttons_exit);
+Index: linux-2.6.27/drivers/input/misc/capsense-procfs.c
+===================================================================
+--- /dev/null
++++ linux-2.6.27/drivers/input/misc/capsense-procfs.c
+@@ -0,0 +1,390 @@
++/*
++ * CAPSENSE Interface driver
++ * Device setup using procfs
++ *
++ * Copyright (C) 2008, Goobie (www.goobie.fr).
++ *
++ * Sylvain Giroudon <sylvain.giroudon@goobie.fr>
++ *
++ * This software program is licensed subject to the GNU General Public License
++ * (GPL).Version 2,June 1991, available at http://www.fsf.org/copyleft/gpl.html
++ */
++
++#include <linux/proc_fs.h>
++#include <linux/uaccess.h>
++
++
++struct capsense_proc_data {
++ struct capsense_ctx *capsense;
++ struct capsense_keymap *phys;
++ char *name;
++ unsigned char command;
++ unsigned char hex;
++};
++
++struct capsense_proc_entry {
++ char *name;
++ unsigned char command;
++ struct capsense_proc_data data[ARRAY_SIZE(phys_keymap)];
++};
++
++static struct capsense_proc_entry capsense_proc_key_entries[] = {
++ { "CS_FINGER_TH", CAP_CS_FINGER_TH(0,0) },
++ { "CS_IDAC", CAP_CS_IDAC(0,0) },
++};
++
++static struct capsense_proc_entry capsense_proc_device_entries[] = {
++ { "DEVICE_ID", CAP_DEVICE_ID },
++ { "DEVICE_STATUS", CAP_DEVICE_STATUS },
++};
++
++struct capsense_proc_command {
++ char *name;
++ unsigned char command;
++ struct capsense_ctx *capsense;
++};
++
++static struct capsense_proc_command capsense_proc_commands[] = {
++ { "store", CAP_COMMAND_STORE_NVM },
++ //{ "factory", CAP_COMMAND_RESTORE_FACTORY },
++ //{ "reconfigure", CAP_COMMAND_RECONFIGURE },
++};
++
++
++static int capsense_proc_read(char *page, char **start, off_t off, int count,
++ int *eof, void *_data)
++{
++ struct capsense_proc_data *data = _data;
++ struct capsense_ctx *capsense = data->capsense;
++ u8 value;
++ int len;
++
++ mutex_lock(&capsense->mutex);
++ value = i2c_smbus_read_byte_data(&capsense->client, data->command);
++ mutex_unlock(&capsense->mutex);
++
++ if ( data->hex )
++ len = sprintf(page, "%02X\n", value);
++ else
++ len = sprintf(page, "%u\n", value);
++
++ len -= off;
++ if ( len < count ) {
++ *eof = 1;
++ if ( len <= 0 )
++ return 0;
++ } else {
++ len = count;
++ }
++
++ *start = page + off;
++
++ return len;
++}
++
++
++static int capsense_proc_write(struct file *file, const char *buf,
++ unsigned long count, void *_data)
++{
++ struct capsense_proc_data *data = _data;
++ struct capsense_ctx *capsense = data->capsense;
++ char lbuf[count+1];
++ u8 value;
++
++ /* Only root can do this */
++ if ( !capable(CAP_SYS_ADMIN) )
++ return -EACCES;
++
++ memset(lbuf, 0, sizeof(lbuf));
++
++ if (copy_from_user(lbuf, buf, count))
++ return -EFAULT;
++
++ if ( sscanf(lbuf, "%hhi", &value) == 1 ) {
++ mutex_lock(&capsense->mutex);
++ i2c_smbus_write_byte_data(&capsense->client, CAP_COMMAND_REG, CAP_COMMAND_SETUP_MODE);
++ i2c_smbus_write_byte_data(&capsense->client, data->command, value);
++ i2c_smbus_write_byte_data(&capsense->client, CAP_COMMAND_REG, CAP_COMMAND_NORMAL_MODE);
++ mutex_unlock(&capsense->mutex);
++ }
++ else {
++ printk(KERN_INFO DRIVER_NAME ": [%s/%s] Syntax error in expression\n", data->phys->name, data->name);
++ return -EINVAL;
++ }
++
++ return count;
++}
++
++
++static inline char *str_skip_blanks(char *s)
++{
++ while ( (*s != '\0') && (*s <= ' ') )
++ s++;
++ return s;
++}
++
++
++static inline char *str_skip_chars(char *s)
++{
++ while ( *s > ' ' )
++ s++;
++ return s;
++}
++
++
++static int capsense_proc_write_iic(struct file *file, const char *buf,
++ unsigned long count, void *data)
++{
++ struct capsense_ctx *capsense = data;
++ char lbuf[count+1];
++ int lnum;
++ char *s;
++
++ /* Only root can do this */
++ if ( !capable(CAP_SYS_ADMIN) )
++ return -EACCES;
++
++ printk(KERN_INFO DRIVER_NAME ": Reading configuration script from /proc/" DRIVER_NAME "/iic (%lu bytes)\n", count);
++
++ memset(lbuf, 0, sizeof(lbuf));
++
++ if (copy_from_user(lbuf, buf, count))
++ return -EFAULT;
++
++ s = lbuf;
++ lnum = 0;
++
++ while ( *s != '\0' ) {
++ char *line;
++ char operation;
++ unsigned char data[255];
++ int size;
++ struct i2c_msg msg;
++ int ret;
++
++ lnum++;
++
++ /* Spot the end of the line */
++ line = s;
++ while ( (*s != '\0') && (*s != '\n') )
++ s++;
++ if ( *s != '\0' )
++ *(s++) = '\0';
++
++ //printk(KERN_INFO DRIVER_NAME ": iic:%d: '%s'\n", lnum, line);
++
++ /* Strip leading blank characters */
++ line = str_skip_blanks(line);
++
++ /* Empty or commented line: skip! */
++ if ( (*line == '\0') || (*line == '#') )
++ continue;
++
++ /* Only accept write operations 'w' */
++ operation = *(line++);
++ if ( operation != 'w' ) {
++ printk(KERN_ERR DRIVER_NAME ": iic:%d: Unknown operation '%c ...' -- skipped\n", lnum, operation);
++ continue;
++ }
++
++ /* Extract data values */
++ size = 0;
++ while ( (*line != '\0') && (size < sizeof(data)) ) {
++ line = str_skip_blanks(line);
++ if ( *line != '\0' )
++ sscanf(line, "%hhx", &data[size++]);
++ line = str_skip_chars(line);
++ }
++
++ {
++ int i;
++
++ printk(KERN_DEBUG DRIVER_NAME ": iic:%d: %c", lnum, operation);
++ for (i = 0; i < size; i++)
++ printk(" %02X", data[i]);
++ printk("\n");
++ }
++
++ /* Do nothing if there are less than 2 data bytes (address, command) */
++ if ( size < 3 ) {
++ printk(KERN_ERR DRIVER_NAME ": iic:%d: Too few data for operation '%c ...' -- skipped\n", lnum, operation);
++ continue;
++ }
++
++ /* First data byte is the i2c device address:
++ Warn if it does not match the standard i2c address */
++ if ( data[0] != CAPSENSE_I2C_ADDR ) {
++ printk(KERN_WARNING DRIVER_NAME ": iic:%d: WARNING - Specified i2c address (%02X) differs from standard i2c address (%02X)\n", lnum, data[0], CAPSENSE_I2C_ADDR);
++ }
++
++ /* Second data byte is the capsense register:
++ Warn if changing the device I2C address */
++ if ( data[1] == CAP_I2C_ADDR_DM ) {
++ printk(KERN_WARNING DRIVER_NAME ": iic:%d: WARNING - Changing i2c address to %02X (I2C_ADDR_DM=%02X)\n", lnum, data[2] & 0x7F, data[2]);
++ }
++
++ /* Send command to i2c device */
++ mutex_lock(&capsense->mutex);
++
++ msg.addr = data[0];
++ msg.flags = capsense->client.flags;
++ msg.len = size - 1;
++ msg.buf = data + 1;
++ //printk(KERN_INFO DRIVER_NAME ": iic:%d: i2c transfer: addr=0x%02X flags=0x%04X len=%d\n", lnum, msg.addr, msg.flags, msg.len);
++
++ ret = i2c_transfer(capsense->client.adapter, &msg, 1);
++ if ( ret < 0 )
++ printk(KERN_ERR DRIVER_NAME ": iic:%d: i2c transfer failed (%d), command rejected\n", lnum, ret);
++
++ mutex_unlock(&capsense->mutex);
++ }
++
++ return count;
++}
++
++
++static int capsense_proc_write_command(struct file *file, const char *buf,
++ unsigned long count, void *data)
++{
++ struct capsense_proc_command *command = data;
++ struct capsense_ctx *capsense = command->capsense;
++
++ /* Only root can do this */
++ if ( !capable(CAP_SYS_ADMIN) )
++ return -EACCES;
++
++ printk(KERN_INFO DRIVER_NAME ": %s (%02X)\n", command->name, command->command);
++
++ mutex_lock(&capsense->mutex);
++ i2c_smbus_write_byte_data(&capsense->client, CAP_COMMAND_REG, CAP_COMMAND_SETUP_MODE);
++ i2c_smbus_write_byte_data(&capsense->client, CAP_COMMAND_REG, command->command);
++ i2c_smbus_write_byte_data(&capsense->client, CAP_COMMAND_REG, CAP_COMMAND_NORMAL_MODE);
++ mutex_unlock(&capsense->mutex);
++
++ return count;
++}
++
++
++static int capsense_proc_init(struct capsense_ctx *capsense)
++{
++ struct proc_dir_entry *root;
++ struct proc_dir_entry *dir;
++ struct proc_dir_entry *ent;
++ int i;
++
++ /* Create capsense proc directory */
++ printk(KERN_INFO DRIVER_NAME ": Creating setup entries in /proc/" DRIVER_NAME "/\n");
++
++ root = proc_mkdir(DRIVER_NAME, NULL);
++ if ( root == NULL ) {
++ printk(KERN_WARNING DRIVER_NAME ": Cannot create directory /proc/" DRIVER_NAME "\n");
++ return -1;
++ }
++
++ root->owner = THIS_MODULE;
++
++ /* Create iic config file dump entry */
++ ent = create_proc_entry("iic", S_IFREG|S_IWUSR, root);
++ if ( ent == NULL ) {
++ printk(KERN_WARNING DRIVER_NAME ": Cannot create entry /proc/" DRIVER_NAME "/iic\n");
++ return -1;
++ }
++
++ ent->owner = THIS_MODULE;
++ ent->data = capsense;
++ ent->write_proc = capsense_proc_write_iic;
++
++ /* Create commands directory */
++ dir = proc_mkdir("commands", root);
++ if ( dir == NULL ) {
++ printk(KERN_WARNING DRIVER_NAME ": Cannot create directory /proc/" DRIVER_NAME "/commands\n");
++ return -1;
++ }
++
++ dir->owner = THIS_MODULE;
++
++ /* Create command entries */
++ for (i = 0; i < ARRAY_SIZE(capsense_proc_commands); i++) {
++ struct capsense_proc_command *command = &capsense_proc_commands[i];
++
++ command->capsense = capsense;
++
++ ent = create_proc_entry(command->name, S_IFREG|S_IWUSR, dir);
++ if ( ent == NULL ) {
++ printk(KERN_WARNING DRIVER_NAME ": Cannot create entry /proc/" DRIVER_NAME "/commands/%s\n", command->name);
++ return -1;
++ }
++
++ ent->owner = THIS_MODULE;
++ ent->data = command;
++ ent->write_proc = capsense_proc_write_command;
++ }
++
++ /* Create device status read entries */
++ for (i = 0; i < ARRAY_SIZE(capsense_proc_device_entries); i++) {
++ struct capsense_proc_entry *entry = &(capsense_proc_device_entries[i]);
++ struct capsense_proc_data *data = &(entry->data[i]);
++
++ data->capsense = capsense;
++ data->phys = NULL;
++ data->name = entry->name;
++ data->command = entry->command;
++ data->hex = 1;
++
++ ent = create_proc_entry(entry->name, S_IFREG|S_IRUSR, root);
++ if ( ent == NULL ) {
++ printk(KERN_WARNING DRIVER_NAME ": Cannot create entry /proc/" DRIVER_NAME "/%s\n", entry->name);
++ continue;
++ }
++
++ ent->owner = THIS_MODULE;
++ ent->data = data;
++ ent->read_proc = capsense_proc_read;
++ }
++
++ /* Create keys management directory */
++ dir = proc_mkdir("keys", root);
++ if ( dir == NULL ) {
++ printk(KERN_WARNING DRIVER_NAME ": Cannot create directory /proc/" DRIVER_NAME "/keys\n");
++ return -1;
++ }
++
++ dir->owner = THIS_MODULE;
++
++ /* Create keys sensitivity adjustment entries */
++ for (i = 0; i < ARRAY_SIZE(phys_keymap); i++) {
++ struct capsense_keymap *phys = &phys_keymap[i];
++ struct proc_dir_entry *subdir;
++ int ientry;
++
++ subdir = proc_mkdir(phys->name, dir);
++ if ( subdir == NULL ) {
++ printk(KERN_WARNING DRIVER_NAME ": Cannot create directory /proc/" DRIVER_NAME "/keys/%s\n", phys->name);
++ continue;
++ }
++
++ for (ientry = 0; ientry < ARRAY_SIZE(capsense_proc_key_entries); ientry++) {
++ struct capsense_proc_entry *entry = &(capsense_proc_key_entries[ientry]);
++ struct capsense_proc_data *data = &(entry->data[i]);
++
++ data->capsense = capsense;
++ data->phys = phys;
++ data->name = entry->name;
++ data->command = CAP_CS(entry->command, phys->port, phys->bit);
++ data->hex = 0;
++
++ ent = create_proc_entry(entry->name, S_IFREG|S_IRUSR|S_IWUSR, subdir);
++ if ( ent == NULL ) {
++ printk(KERN_WARNING DRIVER_NAME ": Cannot create entry /proc/" DRIVER_NAME "/keys/%s/%s\n", phys->name, entry->name);
++ continue;
++ }
++
++ ent->owner = THIS_MODULE;
++ ent->data = data;
++ ent->read_proc = capsense_proc_read;
++ ent->write_proc = capsense_proc_write;
++ }
++ }
++
++ return 0;
++}
diff --git a/packages/linux/linux_2.6.27.bb b/packages/linux/linux_2.6.27.bb
index 4b094bf48c..0a2055e58e 100644
--- a/packages/linux/linux_2.6.27.bb
+++ b/packages/linux/linux_2.6.27.bb
@@ -1,6 +1,6 @@
require linux.inc
-PR = "r4"
+PR = "r5"
# Mark archs/machines that this kernel supports
DEFAULT_PREFERENCE = "-1"
@@ -20,7 +20,7 @@ SRC_URI_append_boc01 = "\
file://008-081208-spi.patch;patch=1 \
file://010-090112-mii.patch;patch=1 \
file://011-090115-gpio.patch;patch=1 \
- file://012-090115-cy3218-btns.patch;patch=1 \
+ file://012-090219-capsense.patch;patch=1 \
file://013-090209-lcd.patch;patch=1 \
file://014-090209-pm-wakeup.patch;patch=1 \
"
diff --git a/packages/matchbox-panel/matchbox-panel-0.9.3/mb-applet-system-monitor-crash.patch b/packages/matchbox-panel/matchbox-panel-0.9.3/mb-applet-system-monitor-crash.patch
new file mode 100644
index 0000000000..8773003b34
--- /dev/null
+++ b/packages/matchbox-panel/matchbox-panel-0.9.3/mb-applet-system-monitor-crash.patch
@@ -0,0 +1,85 @@
+Program received signal SIGSEGV, Segmentation fault.
+0x4002dfbc in mb_pixbuf_img_plot_pixel (pb=<value optimized out>, img=0x1ba40, x=22,
+ y=-434, r=255 'Ă¿', g=0 '\0', b=0 '\0') at mbpixbuf.c:2087
+(gdb) bt
+#0 0x4002dfbc in mb_pixbuf_img_plot_pixel (pb=<value optimized out>, img=0x1ba40, x=22,
+ y=-434, r=255 'Ă¿', g=0 '\0', b=0 '\0') at mbpixbuf.c:2087
+#1 0x0000966c in paint_callback (app=<value optimized out>, drw=46137348)
+ at mb-applet-system-monitor.c:272
+#2 0x4002b8f6 in handle_expose (mb=0x1ba40, event=<value optimized out>) at mbtray.c:820
+#3 0x4002b922 in mb_tray_app_repaint (mb=0x1ba40) at mbtray.c:833
+#4 0x00008fd4 in timeout_callback (app=0x1ba40) at mb-applet-system-monitor.c:347
+#5 0x4002c580 in mb_tray_app_main (mb=0x14008) at mbtray.c:302
+#6 0x00009878 in main (argc=1, argv=0xbecf1ca4) at mb-applet-system-monitor.c:410
+(gdb) up
+(gdb) print membox_h
+$1 = 20
+(gdb) print mem_pixels
+$2 = 18798069
+(gdb) print memsize
+$3 = 1597228901
+(gdb) print msd
+$4 = {loadIndex = 15, samples = 16, load = 0x18a90, total = 0x18b18,
+ mem_used = 18446744073706139648, mem_max = 63750144, swap_used = 0, swap_max = 0,
+ swap_percent = 0, mem_percent = 1597228901}
+
+Huh, mem_used doesn't look good!
+
+root@zaurus:~# printf %lx\\n -18446744073706139648
+341000
+
+Well, it's negative. The algorithm is a bit stange.
+
+root@zaurus:~# cat /proc/meminfo
+MemTotal: 62256 kB
+MemFree: 8504 kB
+Buffers: 1508 kB
+Cached: 24692 kB
+SwapCached: 8604 kB
+Active: 22632 kB
+Inactive: 21344 kB
+SwapTotal: 131064 kB
+SwapFree: 72060 kB
+Dirty: 0 kB
+Writeback: 0 kB
+AnonPages: 12636 kB
+Mapped: 5532 kB
+Slab: 4300 kB
+SReclaimable: 1456 kB
+SUnreclaim: 2844 kB
+PageTables: 1116 kB
+NFS_Unstable: 0 kB
+Bounce: 0 kB
+WritebackTmp: 0 kB
+CommitLimit: 162192 kB
+Committed_AS: 81568 kB
+VmallocTotal: 581632 kB
+VmallocUsed: 9112 kB
+VmallocChunk: 565244 kB
+
+Now let's compute what's happening:
+
+cache_used = cache_total - cache_free;
+my_mem_used = cache_used + used - cached - buffers;
+12636 - 5532 + 8604 - 24692 - 1508 = -10492
+ ======
+
+Well, I don't know, how to compute a really used memory, but I could at
+least sanitize the value. Here you are:
+
+Index: matchbox-panel-0.9.3/applets/mb-applet-system-monitor.c
+===================================================================
+--- matchbox-panel-0.9.3/applets/mb-applet-system-monitor.c 2006-02-07 22:19:12.000000000 +0000
++++ matchbox-panel-0.9.3/applets/mb-applet-system-monitor.c 2009-02-21 13:19:41.000000000 +0000
+@@ -195,6 +195,11 @@
+ my_mem_max = total;
+ my_swap_max = cache_total;
+ my_mem_used = cache_used + used - cached - buffers;
++ /* Ugly hack! Fix mem-used algorithm is needed. */
++ if (my_mem_used < 0)
++ my_mem_used = 0;
++ if (my_mem_used > my_mem_max)
++ my_mem_used = my_mem_max;
+ msd.mem_used = my_mem_used;
+ msd.mem_max = my_mem_max;
+ msd.mem_percent = (100 * msd.mem_used) / msd.mem_max;
diff --git a/packages/matchbox-panel/matchbox-panel_0.9.3.bb b/packages/matchbox-panel/matchbox-panel_0.9.3.bb
index b7b12edc63..555912260e 100644
--- a/packages/matchbox-panel/matchbox-panel_0.9.3.bb
+++ b/packages/matchbox-panel/matchbox-panel_0.9.3.bb
@@ -1,4 +1,5 @@
require matchbox-panel.inc
-PR ="r3"
+PR ="r4"
SRC_URI = "http://projects.o-hand.com/matchbox/sources/${PN}/0.9/${PN}-${PV}.tar.gz \
- file://mb-applet-battery-repaint-093.patch;patch=1"
+ file://mb-applet-battery-repaint-093.patch;patch=1 \
+ file://mb-applet-system-monitor-crash.patch;patch=1"
diff --git a/packages/mc/mc-4.6.2/00-70-utf8-common.patch b/packages/mc/mc-4.6.2/00-70-utf8-common.patch
new file mode 100644
index 0000000000..244a01580a
--- /dev/null
+++ b/packages/mc/mc-4.6.2/00-70-utf8-common.patch
@@ -0,0 +1,46 @@
+Some common stuff used by other UTF-8 patches.
+
+================================================================================
+--- mc-4.6.2/src/util.c
++++ mc-4.6.2/src/util.c
+@@ -145,6 +145,30 @@
+ return strlen (str);
+ }
+
++int
++columns_to_bytes (const char *str, int col)
++{
++ int bytes = 0;
++ int columns = 0;
++ int i;
++#ifdef UTF8
++ if (SLsmg_Is_Unicode) {
++ static mbstate_t s;
++ while (columns < col) {
++ memset (&s, 0, sizeof (s));
++ i = mbrlen (str + bytes, -1, &s);
++ if (i <= 0) {
++ return col + bytes - columns;
++ }
++ bytes += i;
++ columns ++;
++ }
++ return col + bytes - columns;
++ } else
++#endif
++ return col;
++}
++
+ #ifdef UTF8
+
+ void
+--- mc-4.6.2/src/util.h
++++ mc-4.6.2/src/util.h
+@@ -104,6 +104,7 @@
+
+ void fix_utf8(char *str);
+ size_t mbstrlen (const char *);
++int columns_to_bytes (const char *, int);
+ wchar_t *mbstr_to_wchar (const char *);
+ char *wchar_to_mbstr (const wchar_t *);
+ char *utf8_to_local(char *str);
diff --git a/packages/mc/mc-4.6.2/00-73-utf8-bottom-buttons-width.patch b/packages/mc/mc-4.6.2/00-73-utf8-bottom-buttons-width.patch
new file mode 100644
index 0000000000..a7bc41c59b
--- /dev/null
+++ b/packages/mc/mc-4.6.2/00-73-utf8-bottom-buttons-width.patch
@@ -0,0 +1,21 @@
+Use six character width cyan rectangles for bottom row's buttons.
+
+================================================================================
+--- mc-4.6.2/src/widget.c
++++ mc-4.6.2/src/widget.c
+@@ -2562,11 +2562,14 @@
+ attrset (DEFAULT_COLOR);
+ tty_printf ("%-*s", bb->widget.cols, "");
+ for (i = 0; i < COLS / 8 && i < 10; i++) {
++ int j;
+ widget_move (&bb->widget, 0, i * 8);
+ attrset (DEFAULT_COLOR);
+ tty_printf ("%d", i + 1);
+ attrset (SELECTED_COLOR);
+- tty_printf ("%-*s", ((i + 1) * 8 == COLS ? 5 : 6),
++ j = columns_to_bytes(bb->labels [i].text ? bb->labels [i].text : "",
++ ((i + 1) * 8 == COLS ? 5 : 6));
++ tty_printf ("%-*s", j,
+ bb->labels[i].text ? bb->labels[i].text : "");
+ attrset (DEFAULT_COLOR);
+ }
diff --git a/packages/mc/mc-4.6.2/00-75-utf8-cmdline-help.patch b/packages/mc/mc-4.6.2/00-75-utf8-cmdline-help.patch
new file mode 100644
index 0000000000..5f1227d30a
--- /dev/null
+++ b/packages/mc/mc-4.6.2/00-75-utf8-cmdline-help.patch
@@ -0,0 +1,63 @@
+Fix formatting the output of "mc --help".
+
+================================================================================
+--- mc-4.6.2/src/main.c
++++ mc-4.6.2/src/main.c
+@@ -1865,7 +1865,7 @@
+
+ /* print help for options */
+ leftColWidth = poptPrintHelp (ctx, stream, 0);
+- fprintf (stream, " %-*s %s\n", leftColWidth, _("+number"),
++ fprintf (stream, " %-*s %s\n", leftColWidth + strlen(_("+number")) - mbstrlen(_("+number")), _("+number"),
+ _("Set initial line number for the internal editor"));
+ fputs (_
+ ("\n"
+--- mc-4.6.2/src/popthelp.c
++++ mc-4.6.2/src/popthelp.c
+@@ -101,7 +101,7 @@
+ goto out;
+ }
+
+- helpLength = strlen(help);
++ helpLength = mbstrlen(help);
+ while (helpLength > lineLength) {
+ ch = help + lineLength - 1;
+ while (ch > help && !isspace((unsigned char) *ch)) ch--;
+@@ -112,7 +112,7 @@
+ fprintf(f, "%.*s\n%*s", (int) (ch - help), help, indentLength, " ");
+ help = ch;
+ while (isspace((unsigned char) *help) && *help) help++;
+- helpLength = strlen(help);
++ helpLength = mbstrlen(help);
+ }
+
+ if (helpLength) fprintf(f, "%s\n", help);
+@@ -233,7 +233,7 @@
+ if (len == 3) return cursor;
+
+ if (argDescrip)
+- len += strlen(argDescrip) + 1;
++ len += mbstrlen(argDescrip) + 1;
+
+ if ((cursor + len) > 79) {
+ fprintf(f, "\n ");
+@@ -304,7 +304,7 @@
+ singleTableUsage(f, cursor, con->options, NULL);
+
+ if (con->otherHelp) {
+- cursor += strlen(con->otherHelp) + 1;
++ cursor += mbstrlen(con->otherHelp) + 1;
+ if (cursor > 79) fprintf(f, "\n ");
+ fprintf(f, " %s", con->otherHelp);
+ }
+--- mc-4.6.2/src/util.c
++++ mc-4.6.2/src/util.c
+@@ -152,7 +152,7 @@
+ int columns = 0;
+ int i;
+ #ifdef UTF8
+- if (SLsmg_Is_Unicode) {
++ if (1) {
+ static mbstate_t s;
+ while (columns < col) {
+ memset (&s, 0, sizeof (s));
diff --git a/packages/mc/mc-4.6.2/00-76-utf8-hotlist-highlight.patch b/packages/mc/mc-4.6.2/00-76-utf8-hotlist-highlight.patch
new file mode 100644
index 0000000000..38e0337ad6
--- /dev/null
+++ b/packages/mc/mc-4.6.2/00-76-utf8-hotlist-highlight.patch
@@ -0,0 +1,23 @@
+Highlight the lines of hotlist in full width.
+
+================================================================================
+--- mc-4.6.2/src/widget.c
++++ mc-4.6.2/src/widget.c
+@@ -1994,6 +1994,7 @@
+ {
+ WLEntry *e;
+ int i;
++ int j;
+ int sel_line;
+ Dlg_head *h = l->widget.parent;
+ int normalc = DLG_NORMALC (h);
+@@ -2024,7 +2025,8 @@
+ text = e->text;
+ e = e->next;
+ }
+- tty_printf (" %-*s ", l->width-2, name_trunc (text, l->width-2));
++ j = columns_to_bytes (name_trunc (text, l->width-2), l->width-2);
++ tty_printf (" %-*s ", j, name_trunc (text, l->width-2));
+ }
+ l->cursor_y = sel_line;
+ if (!l->scrollbar)
diff --git a/packages/mc/mc-4.6.2/00-77-utf8-filename-search-highlight.patch b/packages/mc/mc-4.6.2/00-77-utf8-filename-search-highlight.patch
new file mode 100644
index 0000000000..912d8eb72b
--- /dev/null
+++ b/packages/mc/mc-4.6.2/00-77-utf8-filename-search-highlight.patch
@@ -0,0 +1,17 @@
+Quick filename search (^S) highlights correct width.
+
+================================================================================
+--- mc-4.6.2/src/screen.c
++++ mc-4.6.2/src/screen.c
+@@ -771,8 +771,10 @@
+ widget_move (&panel->widget, llines (panel)+3, 1);
+
+ if (panel->searching){
++ int j;
+ attrset (INPUT_COLOR);
+- tty_printf ("/%-*s", panel->widget.cols-3, panel->search_buffer);
++ j = columns_to_bytes (panel->search_buffer, panel->widget.cols-3);
++ tty_printf ("/%-*s", j, panel->search_buffer);
+ attrset (NORMAL_COLOR);
+ return;
+ }
diff --git a/packages/mc/mc-4.6.2/mc-utf8-look-and-feel.patch b/packages/mc/mc-4.6.2/mc-utf8-look-and-feel.patch
new file mode 100644
index 0000000000..83ad60135d
--- /dev/null
+++ b/packages/mc/mc-4.6.2/mc-utf8-look-and-feel.patch
@@ -0,0 +1,206 @@
+Index: mc-4.6.2~git20080311/src/main.c
+================================================================================
+--- mc-4.6.2/src/main.c
++++ mc-4.6.2/src/main.c
+@@ -276,6 +276,9 @@
+ /* The user's shell */
+ const char *shell = NULL;
+
++/* Is the LANG UTF-8 ? */
++gboolean is_utf8 = FALSE;
++
+ /* mc_home: The home of MC */
+ char *mc_home = NULL;
+
+@@ -2126,6 +2129,16 @@
+ int
+ main (int argc, char *argv[])
+ {
++ /* Check whether we have UTF-8 locale */
++ char *lang = getenv("LANG");
++ size_t len = 0;
++
++ if ( lang )
++ len = strlen(lang);
++
++ if ( len >= 5 && !strcasecmp(&lang[len-5],"UTF-8") )
++ is_utf8 = TRUE;
++
+ /* We had LC_CTYPE before, LC_ALL includs LC_TYPE as well */
+ setlocale (LC_ALL, "");
+ bindtextdomain ("mc", LOCALEDIR);
+--- mc-4.6.2/src/main.h
++++ mc-4.6.2/src/main.h
+@@ -69,6 +69,7 @@
+ extern int only_leading_plus_minus;
+ extern int output_starts_shell;
+ extern int midnight_shutdown;
++extern gboolean is_utf8;
+ extern char cmd_buf [512];
+ extern const char *shell;
+
+--- mc-4.6.2/src/screen.c
++++ mc-4.6.2/src/screen.c
+@@ -892,6 +892,9 @@
+ }
+ #endif /* HAVE_SLANG */
+
++ vscrollbar (panel->widget, panel->widget.lines, panel->widget.cols-1, 2, 2,
++ panel->selected, panel->count, TRUE);
++
+ if (panel->active)
+ attrset (REVERSE_COLOR);
+
+@@ -1493,7 +1496,7 @@
+ panel->dirty = 1;
+
+ /* Status needn't to be split */
+- usable_columns = ((panel->widget.cols-2)/((isstatus)
++ usable_columns = ((panel->widget.cols-3)/((isstatus)
+ ? 1
+ : (panel->split+1))) - (!isstatus && panel->split);
+
+--- mc-4.6.2/src/widget.c
++++ mc-4.6.2/src/widget.c
+@@ -1944,52 +1944,86 @@
+ return in;
+ }
+
+-
+-/* Listbox widget */
++/* Vertical scrollbar widget */
+
+-/* Should draw the scrollbar, but currently draws only
+- * indications that there is more information
+- */
+-static int listbox_cdiff (WLEntry *s, WLEntry *e);
+-
+-static void
+-listbox_drawscroll (WListbox *l)
++void
++vscrollbar (Widget widget, int height, int width, int tpad, int bpad,
++ int selected, int count, gboolean color)
+ {
+ int line;
+- int i, top;
+- int max_line = l->height-1;
+-
++ int i;
++
+ /* Are we at the top? */
+- widget_move (&l->widget, 0, l->width);
+- if (l->list == l->top)
+- one_vline ();
++ widget_move (&widget, tpad, width);
++#ifndef UTF8
++ if (!selected)
++ one_vline ();
+ else
+- addch ('^');
++ addch ('^');
++#else
++ if (color) attrset (MARKED_COLOR);
++ if (is_utf8)
++ SLsmg_write_string("â–´");
++ else
++ addch ('^');
++ if (color) attrset (NORMAL_COLOR);
++#endif
+
+ /* Are we at the bottom? */
+- widget_move (&l->widget, max_line, l->width);
+- top = listbox_cdiff (l->list, l->top);
+- if ((top + l->height == l->count) || l->height >= l->count)
+- one_vline ();
++ widget_move (&widget, height-1-bpad, width);
++#ifndef UTF8
++ if (selected == count-1)
++ one_vline ();
++ else
++ addch ('v');
++#else
++ if (color) attrset (MARKED_COLOR);
++ if (is_utf8)
++ SLsmg_write_string("â–¾");
+ else
+- addch ('v');
++ addch('v');
++ if (color) attrset (NORMAL_COLOR);
++#endif
+
+ /* Now draw the nice relative pointer */
+- if (l->count)
+- line = 1+ ((l->pos * (l->height-2)) / l->count);
++ if (count > 1)
++ line = tpad + 1 + ((selected * (height-3-tpad-bpad)) / (count-1));
+ else
+- line = 0;
+-
+- for (i = 1; i < max_line; i++){
+- widget_move (&l->widget, i, l->width);
+- if (i != line)
+- one_vline ();
+- else
+- addch ('*');
++ line = 0;
++
++ for (i = tpad + 1; i < height-1-bpad; i++){
++ widget_move (&widget, i, width);
++ if (i != line)
++#ifndef UTF8
++ one_vline ();
++ else
++ addch ('*');
++#else
++ if (is_utf8)
++ SLsmg_write_string("â–’");
++ else
++ one_vline();
++ else {
++ if (color) attrset (MARKED_COLOR);
++ if (is_utf8)
++ SLsmg_write_string("â—ˆ");
++ else
++ addch('*');
++ if (color) attrset (NORMAL_COLOR);
++ }
++#endif
+ }
+ }
+-
+-static void
++
++
++/* Listbox widget */
++
++/* Should draw the scrollbar, but currently draws only
++ * indications that there is more information
++ */
++static int listbox_cdiff (WLEntry *s, WLEntry *e);
++
++void
+ listbox_draw (WListbox *l, int focused)
+ {
+ WLEntry *e;
+@@ -2032,7 +2066,7 @@
+ if (!l->scrollbar)
+ return;
+ attrset (normalc);
+- listbox_drawscroll (l);
++ vscrollbar (l->widget, l->height, l->width, 0, 0, l->pos, l->count, FALSE);
+ }
+
+ /* Returns the number of items between s and e,
+--- mc-4.6.2/src/widget.h
++++ mc-4.6.2/src/widget.h
+@@ -187,6 +187,10 @@
+ /* Listbox manager */
+ WLEntry *listbox_get_data (WListbox *l, int pos);
+
++/* Vertical scrollbar */
++void vscrollbar (Widget widget, int height, int width, int tpad, int bpad,
++ int selected, int count, gboolean color);
++
+ /* search text int listbox entries */
+ WLEntry *listbox_search_text (WListbox *l, const char *text);
+ void listbox_select_entry (WListbox *l, WLEntry *dest);
diff --git a/packages/mc/mc-4.6.2/mc-utf8-nlink.patch b/packages/mc/mc-4.6.2/mc-utf8-nlink.patch
new file mode 100644
index 0000000000..9e361630c4
--- /dev/null
+++ b/packages/mc/mc-4.6.2/mc-utf8-nlink.patch
@@ -0,0 +1,11 @@
+--- mc-4.6.2/src/screen.c
++++ mc-4.6.2/src/screen.c
+@@ -671,7 +671,7 @@
+ SLsmg_write_nwchars (((wchar_t *) buffer)
+ + txtlen - n2, n2);
+ } else
+- SLsmg_write_nwchars ((wchar_t *) buffer, len);
++ SLsmg_write_nwchars ((wchar_t *) buffer + still, len);
+ } else {
+ printw ("%*s", still, "");
+ SLsmg_write_nwchars ((wchar_t *) buffer, txtlen);
diff --git a/packages/mc/mc-4.6.2/mc-utf8.patch b/packages/mc/mc-4.6.2/mc-utf8.patch
new file mode 100644
index 0000000000..5778604350
--- /dev/null
+++ b/packages/mc/mc-4.6.2/mc-utf8.patch
@@ -0,0 +1,5357 @@
+--- mc-4.6.2/acinclude.m4
++++ mc-4.6.2/acinclude.m4
+@@ -399,14 +399,14 @@
+ fi
+
+ dnl Unless external S-Lang was requested, reject S-Lang with UTF-8 hacks
+- if test x$with_screen = xslang; then
+- :
+- m4_if([$1], strict, ,
+- [AC_CHECK_LIB([slang], [SLsmg_write_nwchars],
+- [AC_MSG_WARN([Rejecting S-Lang with UTF-8 support, \
+-it's not fully supported yet])
+- with_screen=mcslang])])
+- fi
++dnl if test x$with_screen = xslang; then
++dnl :
++dnl m4_if([$1], strict, ,
++dnl [AC_CHECK_LIB([slang], [SLsmg_write_nwchars],
++dnl [AC_MSG_WARN([Rejecting S-Lang with UTF-8 support, \
++dnl it's not fully supported yet])
++dnl with_screen=mcslang])])
++dnl fi
+
+ if test x$with_screen = xslang; then
+ AC_DEFINE(HAVE_SYSTEM_SLANG, 1,
+--- mc-4.6.2/edit/edit-widget.h
++++ mc-4.6.2/edit/edit-widget.h
+@@ -30,6 +30,11 @@
+ long command;
+ } edit_key_map_type;
+
++struct action {
++ mc_wchar_t ch;
++ long flags;
++};
++
+ struct WEdit {
+ Widget widget;
+
+@@ -42,8 +47,17 @@
+ /* dynamic buffers and cursor position for editor: */
+ long curs1; /* position of the cursor from the beginning of the file. */
+ long curs2; /* position from the end of the file */
++#ifndef UTF8
+ unsigned char *buffers1[MAXBUFF + 1]; /* all data up to curs1 */
+ unsigned char *buffers2[MAXBUFF + 1]; /* all data from end of file down to curs2 */
++#else /* UTF8 */
++ mc_wchar_t *buffers1[MAXBUFF + 1]; /* all data up to curs1 */
++ mc_wchar_t *buffers2[MAXBUFF + 1]; /* all data from end of file down to curs2 */
++
++ unsigned char charbuf[MB_LEN_MAX];
++ int charpoint;
++#endif /* UTF8 */
++
+
+ /* search variables */
+ long search_start; /* First character to start searching from */
+@@ -87,7 +101,7 @@
+
+ /* undo stack and pointers */
+ unsigned long stack_pointer;
+- long *undo_stack;
++ struct action *undo_stack;
+ unsigned long stack_size;
+ unsigned long stack_size_mask;
+ unsigned long stack_bottom;
+--- mc-4.6.2/edit/edit.c
++++ mc-4.6.2/edit/edit.c
+@@ -105,7 +105,11 @@
+
+ static void user_menu (WEdit *edit);
+
++#ifndef UTF8
+ int edit_get_byte (WEdit * edit, long byte_index)
++#else
++mc_wchar_t edit_get_byte (WEdit * edit, long byte_index)
++#endif
+ {
+ unsigned long p;
+ if (byte_index >= (edit->curs1 + edit->curs2) || byte_index < 0)
+@@ -134,7 +138,7 @@
+
+ edit->curs1 = 0;
+ edit->curs2 = 0;
+- edit->buffers2[0] = g_malloc (EDIT_BUF_SIZE);
++ edit->buffers2[0] = g_malloc (EDIT_BUF_SIZE * sizeof(mc_wchar_t));
+ }
+
+ /*
+@@ -159,7 +163,7 @@
+ }
+
+ if (!edit->buffers2[buf2])
+- edit->buffers2[buf2] = g_malloc (EDIT_BUF_SIZE);
++ edit->buffers2[buf2] = g_malloc (EDIT_BUF_SIZE * sizeof(mc_wchar_t));
+
+ mc_read (file,
+ (char *) edit->buffers2[buf2] + EDIT_BUF_SIZE -
+@@ -169,7 +173,7 @@
+ for (buf = buf2 - 1; buf >= 0; buf--) {
+ /* edit->buffers2[0] is already allocated */
+ if (!edit->buffers2[buf])
+- edit->buffers2[buf] = g_malloc (EDIT_BUF_SIZE);
++ edit->buffers2[buf] = g_malloc (EDIT_BUF_SIZE * sizeof(mc_wchar_t));
+ mc_read (file, (char *) edit->buffers2[buf], EDIT_BUF_SIZE);
+ }
+
+@@ -242,9 +246,44 @@
+ {
+ int c;
+ long i = 0;
+- while ((c = fgetc (f)) >= 0) {
++#ifndef UTF8
++ while ((c = fgetc (f)) != EOF) {
+ edit_insert (edit, c);
+ i++;
++#else /* UTF8 */
++ unsigned char buf[MB_LEN_MAX];
++ int charpos = 0;
++ mbstate_t mbs;
++
++ while ((c = fgetc (f)) != EOF) {
++ mc_wchar_t wc;
++ int size;
++ int j;
++
++ buf[charpos++] = c;
++
++ memset (&mbs, 0, sizeof (mbs));
++ size = mbrtowc(&wc, (char *)buf, charpos, &mbs);
++
++ if (size == -2)
++ continue; /* incomplete */
++
++ else if (size >= 0) {
++ edit_insert (edit, wc);
++ i++;
++ charpos = 0;
++ continue;
++ }
++ else {
++
++ /* invalid */
++#ifdef __STDC_ISO_10646__
++ for (j=0; j<charpos; j++)
++ edit_insert (edit, BINARY_CHAR_OFFSET + (mc_wchar_t)buf[j]);
++#endif
++ charpos = 0;
++ }
++#endif /* UTF8 */
+ }
+ return i;
+ }
+@@ -252,9 +291,32 @@
+ long edit_write_stream (WEdit * edit, FILE * f)
+ {
+ long i;
++#ifndef UTF8
+ for (i = 0; i < edit->last_byte; i++)
+ if (fputc (edit_get_byte (edit, i), f) < 0)
+ break;
++#else /* UTF8 */
++ for (i = 0; i < edit->last_byte; i++) {
++ mc_wchar_t wc = edit_get_byte (edit, i);
++ int res;
++ char tmpbuf[MB_LEN_MAX];
++ mbstate_t mbs;
++
++ memset (&mbs, 0, sizeof (mbs));
++
++#ifdef __STDC_ISO_10646__
++ if (wc >= BINARY_CHAR_OFFSET && wc < (BINARY_CHAR_OFFSET + 256)) {
++ res = 1;
++ tmpbuf[0] = (char) (wc - BINARY_CHAR_OFFSET);
++ } else
++#endif
++ res = wcrtomb(tmpbuf, wc, &mbs);
++ if (res > 0) {
++ if (fwrite(tmpbuf, res, 1, f) != 1)
++ break;
++ }
++ }
++#endif /* UTF8 */
+ return i;
+ }
+
+@@ -293,12 +355,46 @@
+ int i, file, blocklen;
+ long current = edit->curs1;
+ unsigned char *buf;
++#ifdef UTF8
++ mbstate_t mbs;
++ int bufstart = 0;
++
++ memset (&mbs, 0, sizeof (mbs));
++#endif /* UTF8 */
+ if ((file = mc_open (filename, O_RDONLY | O_BINARY)) == -1)
+ return 0;
+ buf = g_malloc (TEMP_BUF_LEN);
++#ifndef UTF8
+ while ((blocklen = mc_read (file, (char *) buf, TEMP_BUF_LEN)) > 0) {
+ for (i = 0; i < blocklen; i++)
+ edit_insert (edit, buf[i]);
++#else /* UTF8 */
++ while ((blocklen = mc_read (file, (char *) buf + bufstart, TEMP_BUF_LEN - bufstart)) > 0) {
++ blocklen += bufstart;
++ bufstart = 0;
++ for (i = 0; i < blocklen; ) {
++ mc_wchar_t wc;
++ int j;
++ int size = mbrtowc(&wc, (char *)buf + i, blocklen - i, &mbs);
++ if (size == -2) { /*incomplete char*/
++ bufstart = blocklen - i;
++ memcpy(buf, buf+i, bufstart);
++ i = blocklen;
++ memset (&mbs, 0, sizeof (mbs));
++ }
++ else if (size <= 0) {
++#ifdef __STDC_ISO_10646__
++ edit_insert (edit, BINARY_CHAR_OFFSET + (mc_wchar_t)buf[i]);
++#endif
++ memset (&mbs, 0, sizeof (mbs));
++ i++; /* skip broken char */
++ }
++ else {
++ edit_insert (edit, wc);
++ i+=size;
++ }
++ }
++#endif /* UTF8 */
+ }
+ edit_cursor_move (edit, current - edit->curs1);
+ g_free (buf);
+@@ -388,7 +484,11 @@
+ static int
+ edit_load_file (WEdit *edit)
+ {
++#ifndef UTF8
+ int fast_load = 1;
++#else /* UTF8 */
++ int fast_load = 0; /* can't be used with multibyte characters */
++#endif /* UTF8 */
+
+ /* Cannot do fast load if a filter is used */
+ if (edit_find_filter (edit->filename) >= 0)
+@@ -454,6 +554,7 @@
+ edit->prev_col = column;
+ edit_move_to_prev_col (edit, edit_bol (edit, edit->curs1));
+ edit_move_display (edit, line - (edit->num_widget_lines / 2));
++ edit->charpoint = 0;
+ }
+
+ /* Save cursor position in the file */
+@@ -537,7 +638,7 @@
+ edit_set_filename (edit, filename);
+ edit->stack_size = START_STACK_SIZE;
+ edit->stack_size_mask = START_STACK_SIZE - 1;
+- edit->undo_stack = g_malloc ((edit->stack_size + 10) * sizeof (long));
++ edit->undo_stack = g_malloc ((edit->stack_size + 10) * sizeof (struct action));
+ if (edit_load_file (edit)) {
+ /* edit_load_file already gives an error message */
+ if (to_free)
+@@ -692,14 +793,23 @@
+ {
+ unsigned long sp = edit->stack_pointer;
+ unsigned long spm1;
+- long *t;
++
++ struct action *t;
++ mc_wchar_t ch = 0;
++
++ if (c == CHAR_INSERT || c == CHAR_INSERT_AHEAD) {
++ va_list ap;
++ va_start (ap, c);
++ ch = va_arg (ap, mc_wint_t);
++ va_end (ap);
++ }
+
+ /* first enlarge the stack if necessary */
+ if (sp > edit->stack_size - 10) { /* say */
+ if (option_max_undo < 256)
+ option_max_undo = 256;
+ if (edit->stack_size < (unsigned long) option_max_undo) {
+- t = g_realloc (edit->undo_stack, (edit->stack_size * 2 + 10) * sizeof (long));
++ t = g_realloc (edit->undo_stack, (edit->stack_size * 2 + 10) * sizeof (struct action));
+ if (t) {
+ edit->undo_stack = t;
+ edit->stack_size <<= 1;
+@@ -714,7 +824,7 @@
+ #ifdef FAST_MOVE_CURSOR
+ if (c == CURS_LEFT_LOTS || c == CURS_RIGHT_LOTS) {
+ va_list ap;
+- edit->undo_stack[sp] = c == CURS_LEFT_LOTS ? CURS_LEFT : CURS_RIGHT;
++ edit->undo_stack[sp].flags = c == CURS_LEFT_LOTS ? CURS_LEFT : CURS_RIGHT;
+ edit->stack_pointer = (edit->stack_pointer + 1) & edit->stack_size_mask;
+ va_start (ap, c);
+ c = -(va_arg (ap, int));
+@@ -725,12 +835,14 @@
+ && spm1 != edit->stack_bottom
+ && ((sp - 2) & edit->stack_size_mask) != edit->stack_bottom) {
+ int d;
+- if (edit->undo_stack[spm1] < 0) {
+- d = edit->undo_stack[(sp - 2) & edit->stack_size_mask];
+- if (d == c) {
+- if (edit->undo_stack[spm1] > -1000000000) {
++ mc_wchar_t d_ch;
++ if (edit->undo_stack[spm1].flags < 0) {
++ d = edit->undo_stack[(sp - 2) & edit->stack_size_mask].flags;
++ d_ch = edit->undo_stack[(sp - 2) & edit->stack_size_mask].ch;
++ if (d == c && d_ch == ch) {
++ if (edit->undo_stack[spm1].flags > -1000000000) {
+ if (c < KEY_PRESS) /* --> no need to push multiple do-nothings */
+- edit->undo_stack[spm1]--;
++ edit->undo_stack[spm1].flags--;
+ return;
+ }
+ }
+@@ -738,19 +850,20 @@
+ #ifndef NO_STACK_CURSMOVE_ANIHILATION
+ else if ((c == CURS_LEFT && d == CURS_RIGHT)
+ || (c == CURS_RIGHT && d == CURS_LEFT)) { /* a left then a right anihilate each other */
+- if (edit->undo_stack[spm1] == -2)
++ if (edit->undo_stack[spm1].flags == -2)
+ edit->stack_pointer = spm1;
+ else
+- edit->undo_stack[spm1]++;
++ edit->undo_stack[spm1].flags++;
+ return;
+ }
+ #endif
+ } else {
+- d = edit->undo_stack[spm1];
+- if (d == c) {
++ d = edit->undo_stack[spm1].flags;
++ d_ch = edit->undo_stack[spm1].ch;
++ if (d == c && d_ch == ch) {
+ if (c >= KEY_PRESS)
+ return; /* --> no need to push multiple do-nothings */
+- edit->undo_stack[sp] = -2;
++ edit->undo_stack[sp].flags = -2;
+ goto check_bottom;
+ }
+ #ifndef NO_STACK_CURSMOVE_ANIHILATION
+@@ -762,7 +875,9 @@
+ #endif
+ }
+ }
+- edit->undo_stack[sp] = c;
++ edit->undo_stack[sp].flags = c;
++ edit->undo_stack[sp].ch = ch;
++
+ check_bottom:
+
+ edit->stack_pointer = (edit->stack_pointer + 1) & edit->stack_size_mask;
+@@ -775,10 +890,10 @@
+ (((unsigned long) c + 1) & edit->stack_size_mask) == edit->stack_bottom)
+ do {
+ edit->stack_bottom = (edit->stack_bottom + 1) & edit->stack_size_mask;
+- } while (edit->undo_stack[edit->stack_bottom] < KEY_PRESS && edit->stack_bottom != edit->stack_pointer);
++ } while (edit->undo_stack[edit->stack_bottom].flags < KEY_PRESS && edit->stack_bottom != edit->stack_pointer);
+
+ /*If a single key produced enough pushes to wrap all the way round then we would notice that the [stack_bottom] does not contain KEY_PRESS. The stack is then initialised: */
+- if (edit->stack_pointer != edit->stack_bottom && edit->undo_stack[edit->stack_bottom] < KEY_PRESS)
++ if (edit->stack_pointer != edit->stack_bottom && edit->undo_stack[edit->stack_bottom].flags < KEY_PRESS)
+ edit->stack_bottom = edit->stack_pointer = 0;
+ }
+
+@@ -787,30 +902,30 @@
+ then the file should be as it was when he loaded up. Then set edit->modified to 0.
+ */
+ static long
+-pop_action (WEdit * edit)
++pop_action (WEdit * edit, struct action *c)
+ {
+- long c;
+ unsigned long sp = edit->stack_pointer;
+ if (sp == edit->stack_bottom) {
+- return STACK_BOTTOM;
++ c->flags = STACK_BOTTOM;
++ return c->flags;
+ }
+ sp = (sp - 1) & edit->stack_size_mask;
+- if ((c = edit->undo_stack[sp]) >= 0) {
+-/* edit->undo_stack[sp] = '@'; */
++ *c = edit->undo_stack[sp];
++ if (edit->undo_stack[sp].flags >= 0) {
+ edit->stack_pointer = (edit->stack_pointer - 1) & edit->stack_size_mask;
+- return c;
++ return c->flags;
+ }
+ if (sp == edit->stack_bottom) {
+ return STACK_BOTTOM;
+ }
+- c = edit->undo_stack[(sp - 1) & edit->stack_size_mask];
+- if (edit->undo_stack[sp] == -2) {
+-/* edit->undo_stack[sp] = '@'; */
++ *c = edit->undo_stack[(sp - 1) & edit->stack_size_mask];
++
++ if (edit->undo_stack[sp].flags == -2) {
+ edit->stack_pointer = sp;
+ } else
+- edit->undo_stack[sp]++;
++ edit->undo_stack[sp].flags++;
+
+- return c;
++ return c->flags;
+ }
+
+ /* is called whenever a modification is made by one of the four routines below */
+@@ -831,7 +946,7 @@
+ */
+
+ void
+-edit_insert (WEdit *edit, int c)
++edit_insert (WEdit *edit, mc_wchar_t c)
+ {
+ /* check if file has grown to large */
+ if (edit->last_byte >= SIZE_LIMIT)
+@@ -869,12 +984,11 @@
+ /* add a new buffer if we've reached the end of the last one */
+ if (!(edit->curs1 & M_EDIT_BUF_SIZE))
+ edit->buffers1[edit->curs1 >> S_EDIT_BUF_SIZE] =
+- g_malloc (EDIT_BUF_SIZE);
++ g_malloc (EDIT_BUF_SIZE * sizeof(mc_wchar_t));
+
+ /* perform the insertion */
+- edit->buffers1[edit->curs1 >> S_EDIT_BUF_SIZE][edit->
+- curs1 & M_EDIT_BUF_SIZE]
+- = (unsigned char) c;
++ edit->buffers1[edit->curs1 >> S_EDIT_BUF_SIZE]
++ [edit->curs1 & M_EDIT_BUF_SIZE] = c;
+
+ /* update file length */
+ edit->last_byte++;
+@@ -885,7 +999,7 @@
+
+
+ /* same as edit_insert and move left */
+-void edit_insert_ahead (WEdit * edit, int c)
++void edit_insert_ahead (WEdit * edit, mc_wchar_t c)
+ {
+ if (edit->last_byte >= SIZE_LIMIT)
+ return;
+@@ -908,7 +1022,7 @@
+ edit->last_get_rule += (edit->last_get_rule >= edit->curs1);
+
+ if (!((edit->curs2 + 1) & M_EDIT_BUF_SIZE))
+- edit->buffers2[(edit->curs2 + 1) >> S_EDIT_BUF_SIZE] = g_malloc (EDIT_BUF_SIZE);
++ edit->buffers2[(edit->curs2 + 1) >> S_EDIT_BUF_SIZE] = g_malloc (EDIT_BUF_SIZE * sizeof(mc_wchar_t));
+ edit->buffers2[edit->curs2 >> S_EDIT_BUF_SIZE][EDIT_BUF_SIZE - (edit->curs2 & M_EDIT_BUF_SIZE) - 1] = c;
+
+ edit->last_byte++;
+@@ -918,7 +1032,7 @@
+
+ int edit_delete (WEdit * edit)
+ {
+- int p;
++ mc_wint_t p;
+ if (!edit->curs2)
+ return 0;
+
+@@ -942,7 +1056,7 @@
+ edit->total_lines--;
+ edit->force |= REDRAW_AFTER_CURSOR;
+ }
+- edit_push_action (edit, p + 256);
++ edit_push_action (edit, CHAR_INSERT_AHEAD, p);
+ if (edit->curs1 < edit->start_display) {
+ edit->start_display--;
+ if (p == '\n')
+@@ -956,7 +1070,7 @@
+ static int
+ edit_backspace (WEdit * edit)
+ {
+- int p;
++ mc_wint_t p;
+ if (!edit->curs1)
+ return 0;
+
+@@ -980,7 +1094,7 @@
+ edit->total_lines--;
+ edit->force |= REDRAW_AFTER_CURSOR;
+ }
+- edit_push_action (edit, p);
++ edit_push_action (edit, CHAR_INSERT, p);
+
+ if (edit->curs1 < edit->start_display) {
+ edit->start_display--;
+@@ -993,10 +1107,18 @@
+
+ #ifdef FAST_MOVE_CURSOR
+
+-static void memqcpy (WEdit * edit, unsigned char *dest, unsigned char *src, int n)
++static void memqcpy (WEdit * edit, mc_wchar_t *dest, mc_wchar_t *src, int n)
+ {
+ unsigned long next;
++#ifndef UTF8
+ while ((next = (unsigned long) memccpy (dest, src, '\n', n))) {
++#else /* UTF8 */
++ while (n) {
++ next = 0;
++ while (next < n && src[next]!='\n') next++;
++ if (next < n) next++;
++ wmemcpy (dest, src, next)
++#endif /* UTF8 */
+ edit->curs_line--;
+ next -= (unsigned long) dest;
+ n -= next;
+@@ -1009,7 +1131,7 @@
+ edit_move_backward_lots (WEdit *edit, long increment)
+ {
+ int r, s, t;
+- unsigned char *p;
++ mc_wchar_t *p;
+
+ if (increment > edit->curs1)
+ increment = edit->curs1;
+@@ -1049,7 +1171,7 @@
+ edit->buffers2[edit->curs2 >> S_EDIT_BUF_SIZE] = p;
+ else
+ edit->buffers2[edit->curs2 >> S_EDIT_BUF_SIZE] =
+- g_malloc (EDIT_BUF_SIZE);
++ g_malloc (EDIT_BUF_SIZE * sizeof(mc_wchar_t));
+ } else {
+ g_free (p);
+ }
+@@ -1087,7 +1209,7 @@
+ edit->buffers2[edit->curs2 >> S_EDIT_BUF_SIZE] = p;
+ else
+ edit->buffers2[edit->curs2 >> S_EDIT_BUF_SIZE] =
+- g_malloc (EDIT_BUF_SIZE);
++ g_malloc (EDIT_BUF_SIZE * sizeof(mc_wchar_t));
+ } else {
+ g_free (p);
+ }
+@@ -1120,7 +1242,7 @@
+
+ c = edit_get_byte (edit, edit->curs1 - 1);
+ if (!((edit->curs2 + 1) & M_EDIT_BUF_SIZE))
+- edit->buffers2[(edit->curs2 + 1) >> S_EDIT_BUF_SIZE] = g_malloc (EDIT_BUF_SIZE);
++ edit->buffers2[(edit->curs2 + 1) >> S_EDIT_BUF_SIZE] = g_malloc (EDIT_BUF_SIZE * sizeof(mc_wchar_t));
+ edit->buffers2[edit->curs2 >> S_EDIT_BUF_SIZE][EDIT_BUF_SIZE - (edit->curs2 & M_EDIT_BUF_SIZE) - 1] = c;
+ edit->curs2++;
+ c = edit->buffers1[(edit->curs1 - 1) >> S_EDIT_BUF_SIZE][(edit->curs1 - 1) & M_EDIT_BUF_SIZE];
+@@ -1144,7 +1266,7 @@
+
+ c = edit_get_byte (edit, edit->curs1);
+ if (!(edit->curs1 & M_EDIT_BUF_SIZE))
+- edit->buffers1[edit->curs1 >> S_EDIT_BUF_SIZE] = g_malloc (EDIT_BUF_SIZE);
++ edit->buffers1[edit->curs1 >> S_EDIT_BUF_SIZE] = g_malloc (EDIT_BUF_SIZE * sizeof(mc_wchar_t));
+ edit->buffers1[edit->curs1 >> S_EDIT_BUF_SIZE][edit->curs1 & M_EDIT_BUF_SIZE] = c;
+ edit->curs1++;
+ c = edit->buffers2[(edit->curs2 - 1) >> S_EDIT_BUF_SIZE][EDIT_BUF_SIZE - ((edit->curs2 - 1) & M_EDIT_BUF_SIZE) - 1];
+@@ -1249,7 +1371,7 @@
+ q = edit->last_byte + 2;
+
+ for (col = 0, p = current; p < q; p++) {
+- int c;
++ mc_wchar_t c;
+ if (cols != -10) {
+ if (col == cols)
+ return p;
+@@ -1267,7 +1389,7 @@
+ } else if (c < 32 || c == 127)
+ col += 2; /* Caret notation for control characters */
+ else
+- col++;
++ col += wcwidth(c);
+ }
+ return col;
+ }
+@@ -1400,12 +1522,16 @@
+ is_blank (WEdit *edit, long offset)
+ {
+ long s, f;
+- int c;
++ mc_wchar_t c;
+ s = edit_bol (edit, offset);
+ f = edit_eol (edit, offset) - 1;
+ while (s <= f) {
+ c = edit_get_byte (edit, s++);
++#ifndef UTF8
+ if (!isspace (c))
++#else
++ if (!iswspace (c))
++#endif /* UTF8 */
+ return 0;
+ }
+ return 1;
+@@ -1660,6 +1786,7 @@
+ return 2;
+ return 0x80000000UL;
+ }
++#ifndef UTF8
+ if (isupper (c))
+ c = 'A';
+ else if (islower (c))
+@@ -1670,6 +1797,18 @@
+ c = '0';
+ else if (isspace (c))
+ c = ' ';
++#else
++ if (iswupper (c))
++ c = 'A';
++ else if (iswlower (c))
++ c = 'a';
++ else if (iswalpha (c))
++ c = 'a';
++ else if (iswdigit (c))
++ c = '0';
++ else if (iswspace (c))
++ c = ' ';
++#endif /* UTF8 */
+ q = strchr (option_chars_move_whole_word, c);
+ if (!q)
+ return 0xFFFFFFFFUL;
+@@ -1694,10 +1833,18 @@
+ c2 = edit_get_byte (edit, edit->curs1);
+ if (!(my_type_of (c1) & my_type_of (c2)))
+ break;
++#ifndef UTF8
+ if (isspace (c1) && !isspace (c2))
++#else
++ if (iswspace (c1) && !iswspace (c2))
++#endif /* UTF8 */
+ break;
+ if (s)
++#ifndef UTF8
+ if (!isspace (c1) && isspace (c2))
++#else
++ if (!iswspace (c1) && iswspace (c2))
++#endif /* UTF8 */
+ break;
+ }
+ }
+@@ -1720,10 +1867,18 @@
+ c2 = edit_get_byte (edit, edit->curs1);
+ if (!(my_type_of (c1) & my_type_of (c2)))
+ break;
++#ifndef UTF8
+ if (isspace (c1) && !isspace (c2))
++#else
++ if (iswspace (c1) && !iswspace (c2))
++#endif /* UTF8 */
+ break;
+ if (s)
++#ifndef UTF8
+ if (!isspace (c1) && isspace (c2))
++#else
++ if (!iswspace (c1) && iswspace (c2))
++#endif /* UTF8 */
+ break;
+ }
+ }
+@@ -1743,7 +1898,11 @@
+ break;
+ c1 = edit_delete (edit);
+ c2 = edit_get_byte (edit, edit->curs1);
++#ifndef UTF8
+ if ((isspace (c1) == 0) != (isspace (c2) == 0))
++#else
++ if ((iswspace (c1) == 0) != (iswspace (c2) == 0))
++#endif /* UTF8 */
+ break;
+ if (!(my_type_of (c1) & my_type_of (c2)))
+ break;
+@@ -1758,7 +1917,11 @@
+ break;
+ c1 = edit_backspace (edit);
+ c2 = edit_get_byte (edit, edit->curs1 - 1);
++#ifndef UTF8
+ if ((isspace (c1) == 0) != (isspace (c2) == 0))
++#else
++ if ((iswspace (c1) == 0) != (iswspace (c2) == 0))
++#endif /* UTF8 */
+ break;
+ if (!(my_type_of (c1) & my_type_of (c2)))
+ break;
+@@ -1772,13 +1935,13 @@
+ static void
+ edit_do_undo (WEdit * edit)
+ {
+- long ac;
++ struct action ac;
+ long count = 0;
+
+ edit->stack_disable = 1; /* don't record undo's onto undo stack! */
+
+- while ((ac = pop_action (edit)) < KEY_PRESS) {
+- switch ((int) ac) {
++ while (pop_action (edit, &ac) < KEY_PRESS) {
++ switch ((int) ac.flags) {
+ case STACK_BOTTOM:
+ goto done_undo;
+ case CURS_RIGHT:
+@@ -1799,31 +1962,33 @@
+ case COLUMN_OFF:
+ column_highlighting = 0;
+ break;
++ case CHAR_INSERT:
++ edit_insert (edit, ac.ch);
++ break;
++ case CHAR_INSERT_AHEAD:
++ edit_insert_ahead (edit, ac.ch);
++ break;
+ }
+- if (ac >= 256 && ac < 512)
+- edit_insert_ahead (edit, ac - 256);
+- if (ac >= 0 && ac < 256)
+- edit_insert (edit, ac);
+
+- if (ac >= MARK_1 - 2 && ac < MARK_2 - 2) {
+- edit->mark1 = ac - MARK_1;
++ if (ac.flags >= MARK_1 - 2 && ac.flags < MARK_2 - 2) {
++ edit->mark1 = ac.flags - MARK_1;
+ edit->column1 = edit_move_forward3 (edit, edit_bol (edit, edit->mark1), 0, edit->mark1);
+- } else if (ac >= MARK_2 - 2 && ac < KEY_PRESS) {
+- edit->mark2 = ac - MARK_2;
++ } else if (ac.flags >= MARK_2 - 2 && ac.flags < KEY_PRESS) {
++ edit->mark2 = ac.flags - MARK_2;
+ edit->column2 = edit_move_forward3 (edit, edit_bol (edit, edit->mark2), 0, edit->mark2);
+ }
+ if (count++)
+ edit->force |= REDRAW_PAGE; /* more than one pop usually means something big */
+ }
+
+- if (edit->start_display > ac - KEY_PRESS) {
+- edit->start_line -= edit_count_lines (edit, ac - KEY_PRESS, edit->start_display);
++ if (edit->start_display > ac.flags - KEY_PRESS) {
++ edit->start_line -= edit_count_lines (edit, ac.flags - KEY_PRESS, edit->start_display);
+ edit->force |= REDRAW_PAGE;
+- } else if (edit->start_display < ac - KEY_PRESS) {
+- edit->start_line += edit_count_lines (edit, edit->start_display, ac - KEY_PRESS);
++ } else if (edit->start_display < ac.flags - KEY_PRESS) {
++ edit->start_line += edit_count_lines (edit, edit->start_display, ac.flags - KEY_PRESS);
+ edit->force |= REDRAW_PAGE;
+ }
+- edit->start_display = ac - KEY_PRESS; /* see push and pop above */
++ edit->start_display = ac.flags - KEY_PRESS; /* see push and pop above */
+ edit_update_curs_row (edit);
+
+ done_undo:;
+@@ -2103,7 +2268,7 @@
+ * passed as -1. Commands are executed, and char_for_insertion is
+ * inserted at the cursor.
+ */
+-void edit_execute_key_command (WEdit *edit, int command, int char_for_insertion)
++void edit_execute_key_command (WEdit *edit, int command, mc_wint_t char_for_insertion)
+ {
+ if (command == CK_Begin_Record_Macro) {
+ edit->macro_i = 0;
+@@ -2138,7 +2303,7 @@
+ all of them. It also does not check for the Undo command.
+ */
+ void
+-edit_execute_cmd (WEdit *edit, int command, int char_for_insertion)
++edit_execute_cmd (WEdit *edit, int command, mc_wint_t char_for_insertion)
+ {
+ edit->force |= REDRAW_LINE;
+
+@@ -2171,7 +2336,7 @@
+ }
+
+ /* An ordinary key press */
+- if (char_for_insertion >= 0) {
++ if (char_for_insertion != (mc_wint_t) -1) {
+ if (edit->overwrite) {
+ if (edit_get_byte (edit, edit->curs1) != '\n')
+ edit_delete (edit);
+--- mc-4.6.2/edit/edit.h
++++ mc-4.6.2/edit/edit.h
+@@ -25,6 +25,27 @@
+
+ #include <stdio.h>
+
++#include "src/tty.h"
++
++#ifdef UTF8
++#include <wchar.h>
++#include <wctype.h>
++
++#define mc_wchar_t wchar_t
++#define mc_wint_t wint_t
++
++#else
++
++#define mc_wchar_t unsigned char
++#define mc_wint_t int
++
++#endif
++
++
++/* unicode private use area */
++#define BINARY_CHAR_OFFSET 0xFFE00
++
++
+ #define N_menus 5
+
+ #define SEARCH_DIALOG_OPTION_NO_SCANF (1 << 0)
+@@ -86,6 +107,8 @@
+ #define START_STACK_SIZE 32
+
+ /* Some codes that may be pushed onto or returned from the undo stack */
++#define CHAR_INSERT 65
++#define CHAR_INSERT_AHEAD 66
+ #define CURS_LEFT 601
+ #define CURS_RIGHT 602
+ #define DELCHAR 603
+@@ -105,7 +128,7 @@
+
+ struct macro {
+ short command;
+- short ch;
++ mc_wchar_t ch;
+ };
+
+ struct WEdit;
+@@ -120,8 +143,12 @@
+ void menu_save_mode_cmd (void);
+ int edit_raw_key_query (const char *heading, const char *query, int cancel);
+ int edit_file (const char *_file, int line);
+-int edit_translate_key (WEdit *edit, long x_key, int *cmd, int *ch);
++int edit_translate_key (WEdit *edit, long x_key, int *cmd, mc_wint_t *ch);
++#ifndef UTF8
+ int edit_get_byte (WEdit * edit, long byte_index);
++#else /* UTF8 */
++mc_wchar_t edit_get_byte (WEdit * edit, long byte_index);
++#endif /* UTF8 */
+ int edit_count_lines (WEdit * edit, long current, int upto);
+ long edit_move_forward (WEdit * edit, long current, int lines, long upto);
+ long edit_move_forward3 (WEdit * edit, long current, int cols, long upto);
+@@ -148,11 +175,11 @@
+ void edit_delete_line (WEdit * edit);
+
+ int edit_delete (WEdit * edit);
+-void edit_insert (WEdit * edit, int c);
++void edit_insert (WEdit * edit, mc_wchar_t c);
+ void edit_cursor_move (WEdit * edit, long increment);
+ void edit_push_action (WEdit * edit, long c, ...);
+ void edit_push_key_press (WEdit * edit);
+-void edit_insert_ahead (WEdit * edit, int c);
++void edit_insert_ahead (WEdit * edit, mc_wchar_t c);
+ long edit_write_stream (WEdit * edit, FILE * f);
+ char *edit_get_write_filter (const char *writename, const char *filename);
+ int edit_save_confirm_cmd (WEdit * edit);
+@@ -183,7 +210,7 @@
+ int eval_marks (WEdit * edit, long *start_mark, long *end_mark);
+ void edit_status (WEdit * edit);
+ void edit_execute_key_command (WEdit *edit, int command,
+- int char_for_insertion);
++ mc_wint_t char_for_insertion);
+ void edit_update_screen (WEdit * edit);
+ int edit_print_string (WEdit * e, const char *s);
+ void edit_move_to_line (WEdit * e, long line);
+@@ -233,7 +260,7 @@
+ void format_paragraph (WEdit *edit, int force);
+
+ /* either command or char_for_insertion must be passed as -1 */
+-void edit_execute_cmd (WEdit *edit, int command, int char_for_insertion);
++void edit_execute_cmd (WEdit *edit, int command, mc_wint_t char_for_insertion);
+
+ #define get_sys_error(s) (s)
+
+--- mc-4.6.2/edit/editcmd.c
++++ mc-4.6.2/edit/editcmd.c
+@@ -60,7 +60,7 @@
+ #include "../src/selcodepage.h"
+
+ struct selection {
+- unsigned char * text;
++ mc_wchar_t *text;
+ int len;
+ };
+
+@@ -83,12 +83,16 @@
+ #define MAX_REPL_LEN 1024
+
+ static int edit_save_cmd (WEdit *edit);
+-static unsigned char *edit_get_block (WEdit *edit, long start,
++static mc_wchar_t *edit_get_block (WEdit *edit, long start,
+ long finish, int *l);
+
+-static inline int my_lower_case (int c)
++static inline mc_wchar_t my_lower_case (mc_wchar_t c)
+ {
++#ifndef UTF8
+ return tolower(c & 0xFF);
++#else
++ return towlower(c);
++#endif
+ }
+
+ static const char *
+@@ -123,11 +127,11 @@
+ #endif /* !HAVE_MEMMOVE */
+
+ /* #define itoa MY_itoa <---- this line is now in edit.h */
+-static char *
++static mc_wchar_t *
+ MY_itoa (int i)
+ {
+- static char t[14];
+- char *s = t + 13;
++ static mc_wchar_t t[14];
++ mc_wchar_t *s = t + 13;
+ int j = i;
+ *s-- = 0;
+ do {
+@@ -212,6 +216,48 @@
+ doupdate();
+ }
+
++#ifdef UTF8
++
++static size_t
++wchar_write(int fd, mc_wchar_t *buf, size_t len)
++{
++ char *tmpbuf = g_malloc(len + MB_LEN_MAX);
++ mbstate_t mbs;
++ size_t i;
++ size_t outlen = 0;
++ size_t res;
++
++ for (i = 0; i < len; i++) {
++ if (outlen >= len) {
++ if ((res = mc_write(fd, tmpbuf, outlen)) != outlen) {
++ g_free(tmpbuf);
++ return -1;
++ }
++ outlen = 0;
++ }
++ memset (&mbs, 0, sizeof (mbs));
++#ifdef __STDC_ISO_10646__
++ if (buf[i] >= BINARY_CHAR_OFFSET && buf[i] < (BINARY_CHAR_OFFSET + 256)) {
++ res = 1;
++ tmpbuf[outlen] = (char) (buf[i] - BINARY_CHAR_OFFSET);
++
++ } else
++#endif
++ res = wcrtomb(tmpbuf + outlen, buf[i], &mbs);
++ if (res > 0) {
++ outlen += res;
++ }
++ }
++ if ((res = mc_write(fd, tmpbuf, outlen)) != outlen) {
++ g_free(tmpbuf);
++ return -1;
++ }
++ g_free(tmpbuf);
++ return len;
++}
++
++#endif /* UTF8 */
++
+ /* If 0 (quick save) then a) create/truncate <filename> file,
+ b) save to <filename>;
+ if 1 (safe save) then a) save to <tempnam>,
+@@ -359,32 +405,48 @@
+ buf = 0;
+ filelen = edit->last_byte;
+ while (buf <= (edit->curs1 >> S_EDIT_BUF_SIZE) - 1) {
++#ifndef UTF8
+ if (mc_write (fd, (char *) edit->buffers1[buf], EDIT_BUF_SIZE)
++#else /* UTF8 */
++ if (wchar_write (fd, edit->buffers1[buf], EDIT_BUF_SIZE)
++#endif /* UTF8 */
+ != EDIT_BUF_SIZE) {
+ mc_close (fd);
+ goto error_save;
+ }
+ buf++;
+ }
++#ifndef UTF8
+ if (mc_write
+ (fd, (char *) edit->buffers1[buf],
++#else /* UTF8 */
++ if (wchar_write
++ (fd, edit->buffers1[buf],
++#endif /* UTF8 */
+ edit->curs1 & M_EDIT_BUF_SIZE) !=
+ (edit->curs1 & M_EDIT_BUF_SIZE)) {
+ filelen = -1;
+ } else if (edit->curs2) {
+ edit->curs2--;
+ buf = (edit->curs2 >> S_EDIT_BUF_SIZE);
+- if (mc_write
+- (fd,
+- (char *) edit->buffers2[buf] + EDIT_BUF_SIZE -
++#ifndef UTF8
++ if (mc_write(fd, (char *) edit->buffers2[buf] + EDIT_BUF_SIZE -
++#else /* UTF8 */
++ if (wchar_write(fd, edit->buffers2[buf] + EDIT_BUF_SIZE -
++#endif /* UTF8 */
+ (edit->curs2 & M_EDIT_BUF_SIZE) - 1,
+ 1 + (edit->curs2 & M_EDIT_BUF_SIZE)) !=
+ 1 + (edit->curs2 & M_EDIT_BUF_SIZE)) {
+ filelen = -1;
+ } else {
+ while (--buf >= 0) {
++#ifndef UTF8
+ if (mc_write
+ (fd, (char *) edit->buffers2[buf],
++#else /* UTF8 */
++ if (wchar_write
++ (fd, edit->buffers2[buf],
++#endif /* UTF8 */
+ EDIT_BUF_SIZE) != EDIT_BUF_SIZE) {
+ filelen = -1;
+ break;
+@@ -705,13 +767,21 @@
+ if (!n || n == EOF)
+ break;
+ n = 0;
++#ifndef UTF8
+ while (fscanf (f, "%hd %hd, ", &macro[n].command, &macro[n].ch))
++#else /* UTF8 */
++ while (fscanf (f, "%hd %lu, ", &macro[n].command, &macro[n].ch))
++#endif /* UTF8 */
+ n++;
+ fscanf (f, ";\n");
+ if (s != k) {
+ fprintf (g, ("key '%d 0': "), s);
+ for (i = 0; i < n; i++)
++#ifndef UTF8
+ fprintf (g, "%hd %hd, ", macro[i].command, macro[i].ch);
++#else /* UTF8 */
++ fprintf (g, "%hd %lu, ", macro[i].command, macro[i].ch);
++#endif /* UTF8 */
+ fprintf (g, ";\n");
+ }
+ }
+@@ -744,7 +814,11 @@
+ if (f) {
+ fprintf (f, ("key '%d 0': "), s);
+ for (i = 0; i < n; i++)
++#ifndef UTF8
+ fprintf (f, "%hd %hd, ", macro[i].command, macro[i].ch);
++#else /* UTF8 */
++ fprintf (f, "%hd %lu, ", macro[i].command, macro[i].ch);
++#endif /* UTF8 */
+ fprintf (f, ";\n");
+ fclose (f);
+ if (saved_macros_loaded) {
+@@ -794,10 +868,18 @@
+ saved_macro[i++] = s;
+ if (!found) {
+ *n = 0;
++#ifndef UTF8
+ while (*n < MAX_MACRO_LENGTH && 2 == fscanf (f, "%hd %hd, ", &macro[*n].command, &macro[*n].ch))
++#else /* UTF8 */
++ while (*n < MAX_MACRO_LENGTH && 2 == fscanf (f, "%hd %lu, ", &macro[*n].command, &macro[*n].ch))
++#endif /* UTF8 */
+ (*n)++;
+ } else {
++#ifndef UTF8
+ while (2 == fscanf (f, "%hd %hd, ", &dummy.command, &dummy.ch));
++#else /* UTF8 */
++ while (2 == fscanf (f, "%hd %lu, ", &dummy.command, &dummy.ch));
++#endif /* UTF8 */
+ }
+ fscanf (f, ";\n");
+ if (s == k)
+@@ -945,7 +1027,7 @@
+ #define space_width 1
+
+ static void
+-edit_insert_column_of_text (WEdit * edit, unsigned char *data, int size, int width)
++edit_insert_column_of_text (WEdit * edit, mc_wchar_t *data, int size, int width)
+ {
+ long cursor;
+ int i, col;
+@@ -993,7 +1075,7 @@
+ {
+ long start_mark, end_mark, current = edit->curs1;
+ int size;
+- unsigned char *copy_buf;
++ mc_wchar_t *copy_buf;
+
+ edit_update_curs_col (edit);
+ if (eval_marks (edit, &start_mark, &end_mark))
+@@ -1033,7 +1115,7 @@
+ {
+ long count;
+ long current;
+- unsigned char *copy_buf;
++ mc_wchar_t *copy_buf;
+ long start_mark, end_mark;
+ int deleted = 0;
+ int x = 0;
+@@ -1094,7 +1176,7 @@
+ edit_push_action (edit, COLUMN_ON);
+ column_highlighting = 0;
+ } else {
+- copy_buf = g_malloc (end_mark - start_mark);
++ copy_buf = g_malloc ((end_mark - start_mark) * sizeof(mc_wchar_t));
+ edit_cursor_move (edit, start_mark - edit->curs1);
+ edit_scroll_screen_over_cursor (edit);
+ count = start_mark;
+@@ -1433,7 +1515,11 @@
+ /* This function is a modification of mc-3.2.10/src/view.c:regexp_view_search() */
+ /* returns -3 on error in pattern, -1 on not found, found_len = 0 if either */
+ static int
++#ifndef UTF8
+ string_regexp_search (char *pattern, char *string, int match_type,
++#else /* UTF8 */
++string_regexp_search (char *pattern, mc_wchar_t *wstring, int match_type,
++#endif /* UTF8 */
+ int match_bol, int icase, int *found_len, void *d)
+ {
+ static regex_t r;
+@@ -1442,6 +1528,11 @@
+ regmatch_t *pmatch;
+ static regmatch_t s[1];
+
++#ifdef UTF8
++ char *string;
++ int i;
++#endif /* UTF8 */
++
+ pmatch = (regmatch_t *) d;
+ if (!pmatch)
+ pmatch = s;
+@@ -1462,13 +1553,51 @@
+ old_type = match_type;
+ old_icase = icase;
+ }
++
++#ifdef UTF8
++ string = wchar_to_mbstr(wstring);
++ if (string == NULL)
++ return -1;
++#endif /* UTF8 */
++
+ if (regexec
+ (&r, string, d ? NUM_REPL_ARGS : 1, pmatch,
+ ((match_bol
+ || match_type != match_normal) ? 0 : REG_NOTBOL)) != 0) {
+ *found_len = 0;
++
++#ifdef UTF8
++ g_free(string);
++#endif /* UTF8 */
++
+ return -1;
+ }
++
++#ifdef UTF8
++ for (i = 0; i < (d ? NUM_REPL_ARGS : 1); i++) {
++ char tmp;
++ int new_o;
++
++ if (pmatch[i].rm_so < 0)
++ continue;
++ tmp = string[pmatch[i].rm_so];
++ string[pmatch[i].rm_so] = 0;
++ new_o = mbstrlen(string);
++ string[pmatch[i].rm_so] = tmp;
++ pmatch[i].rm_so = new_o;
++
++ if (pmatch[i].rm_eo < 0)
++ continue;
++ tmp = string[pmatch[i].rm_eo];
++ string[pmatch[i].rm_eo] = 0;
++ new_o = mbstrlen(string);
++ string[pmatch[i].rm_eo] = tmp;
++ pmatch[i].rm_eo = new_o;
++ }
++
++ g_free(string);
++#endif /* UTF8 */
++
+ *found_len = pmatch[0].rm_eo - pmatch[0].rm_so;
+ return (pmatch[0].rm_so);
+ }
+@@ -1476,13 +1605,29 @@
+ /* thanks to Liviu Daia <daia@stoilow.imar.ro> for getting this
+ (and the above) routines to work properly - paul */
+
++#ifndef UTF8
+ typedef int (*edit_getbyte_fn) (WEdit *, long);
++#else /* UTF8 */
++typedef mc_wchar_t (*edit_getbyte_fn) (WEdit *, long);
++#endif /* UTF8 */
+
+ static long
++#ifndef UTF8
+ edit_find_string (long start, unsigned char *exp, int *len, long last_byte, edit_getbyte_fn get_byte, void *data, int once_only, void *d)
++#else /* UTF8 */
++edit_find_string (long start, unsigned char *exp_mb, int *len, long last_byte, edit_getbyte_fn get_byte, void *data, int once_only, void *d)
++#endif /* UTF8 */
+ {
+ long p, q = 0;
+- long l = strlen ((char *) exp), f = 0;
++ long f = 0;
++
++#ifndef UTF8
++ long l = strlen ((char *) exp);
++#else /* UTF8 */
++ mc_wchar_t *exp = mbstr_to_wchar((char *)exp_mb);
++ mc_wchar_t *exp_backup = exp;
++ long l = wcslen(exp);
++#endif /* UTF8 */
+ int n = 0;
+
+ for (p = 0; p < l; p++) /* count conversions... */
+@@ -1491,19 +1636,22 @@
+ n++;
+
+ if (replace_scanf || replace_regexp) {
+- int c;
+- unsigned char *buf;
+- unsigned char mbuf[MAX_REPL_LEN * 2 + 3];
++ mc_wint_t c;
++ mc_wchar_t *buf;
++ mc_wchar_t mbuf[MAX_REPL_LEN * 2 + 3];
+
+ replace_scanf = (!replace_regexp); /* can't have both */
+
+ buf = mbuf;
+
+ if (replace_scanf) {
+- unsigned char e[MAX_REPL_LEN];
+- if (n >= NUM_REPL_ARGS)
+- return -3;
+-
++ mc_wchar_t e[MAX_REPL_LEN];
++ if (n >= NUM_REPL_ARGS) {
++#ifdef UTF8
++ g_free(exp_backup);
++#endif /* UTF8 */
++ return -3;
++ }
+ if (replace_case) {
+ for (p = start; p < last_byte && p < start + MAX_REPL_LEN; p++)
+ buf[p - start] = (*get_byte) (data, p);
+@@ -1517,20 +1665,36 @@
+ }
+
+ buf[(q = p - start)] = 0;
++#ifndef UTF8
+ strcpy ((char *) e, (char *) exp);
+ strcat ((char *) e, "%n");
++#else /* UTF8 */
++ wcscpy (e, exp);
++ wcscat (e, L"%n");
++#endif /* UTF8 */
+ exp = e;
+
+ while (q) {
+ *((int *) sargs[n]) = 0; /* --> here was the problem - now fixed: good */
++#ifndef UTF8
+ if (n == sscanf ((char *) buf, (char *) exp, SCANF_ARGS)) {
++#else /* UTF8 */
++ if (n == swscanf (buf, exp, SCANF_ARGS)) {
++#endif /* UTF8 */
+ if (*((int *) sargs[n])) {
+ *len = *((int *) sargs[n]);
++#ifdef UTF8
++ g_free(exp_backup);
++#endif /* UTF8 */
+ return start;
+ }
+ }
+- if (once_only)
++ if (once_only) {
++#ifdef UTF8
++ g_free(exp_backup);
++#endif /* UTF8 */
+ return -2;
++ }
+ if (q + start < last_byte) {
+ if (replace_case) {
+ buf[q] = (*get_byte) (data, q + start);
+@@ -1544,7 +1708,11 @@
+ start++;
+ buf++; /* move the window along */
+ if (buf == mbuf + MAX_REPL_LEN) { /* the window is about to go past the end of array, so... */
++#ifndef UTF8
+ memmove (mbuf, buf, strlen ((char *) buf) + 1); /* reset it */
++#else /* UTF8 */
++ wmemmove (mbuf, buf, (wcslen (buf) + 1)); /* reset it */
++#endif /* UTF8 */
+ buf = mbuf;
+ }
+ q--;
+@@ -1571,10 +1739,16 @@
+
+ buf = mbuf;
+ while (q) {
++#ifndef UTF8
+ found_start = string_regexp_search ((char *) exp, (char *) buf, match_normal, match_bol, !replace_case, len, d);
+-
++#else /* UTF8 */
++ found_start = string_regexp_search ((char *) exp_mb, buf, match_normal, match_bol, !replace_case, len, d);
++#endif /* UTF8 */
+ if (found_start <= -2) { /* regcomp/regexec error */
+ *len = 0;
++#ifdef UTF8
++ g_free (exp_backup);
++#endif /* UTF8 */
+ return -3;
+ }
+ else if (found_start == -1) /* not found: try next line */
+@@ -1585,15 +1759,27 @@
+ match_bol = 0;
+ continue;
+ }
+- else /* found */
++ else { /* found */
++#ifdef UTF8
++ g_free(exp_backup);
++#endif /* UTF8 */
+ return (start + offset - q + found_start);
++ }
+ }
+- if (once_only)
++ if (once_only) {
++#ifdef UTF8
++ g_free(exp_backup);
++#endif /* UTF8 */
+ return -2;
++ }
+
+ if (buf[q - 1] != '\n') { /* incomplete line: try to recover */
+ buf = mbuf + MAX_REPL_LEN / 2;
++#ifndef UTF8
+ q = strlen ((const char *) buf);
++#else /* UTF8 */
++ q = wcslen (buf);
++#endif /* UTF8 */
+ memmove (mbuf, buf, q);
+ p = start + q;
+ move_win = 1;
+@@ -1603,36 +1789,59 @@
+ }
+ }
+ } else {
++#ifndef UTF8
+ *len = strlen ((const char *) exp);
++#else /* UTF8 */
++ *len = wcslen (exp);
++#endif /* UTF8 */
+ if (replace_case) {
+ for (p = start; p <= last_byte - l; p++) {
+- if ((*get_byte) (data, p) == (unsigned char)exp[0]) { /* check if first char matches */
++ if ((*get_byte) (data, p) == exp[0]) { /* check if first char matches */
+ for (f = 0, q = 0; q < l && f < 1; q++)
+- if ((*get_byte) (data, q + p) != (unsigned char)exp[q])
++ if ((*get_byte) (data, q + p) != exp[q])
+ f = 1;
+- if (f == 0)
++ if (f == 0) {
++#ifdef UTF8
++ g_free (exp_backup);
++#endif /* UTF8 */
+ return p;
++ }
+ }
+- if (once_only)
++ if (once_only) {
++#ifdef UTF8
++ g_free(exp_backup);
++#endif /* UTF8 */
+ return -2;
++ }
+ }
+ } else {
+ for (p = 0; exp[p] != 0; p++)
+ exp[p] = my_lower_case (exp[p]);
+
+ for (p = start; p <= last_byte - l; p++) {
+- if (my_lower_case ((*get_byte) (data, p)) == (unsigned char)exp[0]) {
++ if (my_lower_case ((*get_byte) (data, p)) == exp[0]) {
+ for (f = 0, q = 0; q < l && f < 1; q++)
+- if (my_lower_case ((*get_byte) (data, q + p)) != (unsigned char)exp[q])
++ if (my_lower_case ((*get_byte) (data, q + p)) != exp[q])
+ f = 1;
+- if (f == 0)
++ if (f == 0) {
++#ifdef UTF8
++ g_free (exp_backup);
++#endif /* UTF8 */
+ return p;
++ }
+ }
+- if (once_only)
++ if (once_only) {
++#ifdef UTF8
++ g_free (exp_backup);
++#endif /* UTF8 */
+ return -2;
++ }
+ }
+ }
+ }
++#ifdef UTF8
++ g_free (exp_backup);
++#endif /* UTF8 */
+ return -2;
+ }
+
+@@ -1646,9 +1855,14 @@
+
+ while ((p = edit_find_string (p, exp, len, last_byte, get_byte, data, once_only, d)) >= 0) {
+ if (replace_whole) {
++#ifndef UTF8
+ /*If the bordering chars are not in option_whole_chars_search then word is whole */
+ if (!strcasechr (option_whole_chars_search, (*get_byte) (data, p - 1))
+ && !strcasechr (option_whole_chars_search, (*get_byte) (data, p + *len)))
++#else /* UTF8 */
++ if (!iswalnum((*get_byte) (data, p - 1))
++ && !iswalnum((*get_byte) (data, p + *len)))
++#endif /* UTF8 */
+ return p;
+ if (once_only)
+ return -2;
+@@ -1680,6 +1894,7 @@
+
+ #define is_digit(x) ((x) >= '0' && (x) <= '9')
+
++#ifndef UTF8
+ #define snprint(v) { \
+ *p1++ = *p++; \
+ *p1 = '\0'; \
+@@ -1687,33 +1902,48 @@
+ if (n >= (size_t) (e - s)) goto nospc; \
+ s += n; \
+ }
++#else /* UTF8 */
++#define snprint(v) { \
++ *p1++ = *p++; \
++ *p1 = '\0'; \
++ n = swprintf(s, e-s, q1,v); \
++ if (n >= (size_t) (e - s)) goto nospc; \
++ s += n; \
++ }
++#endif /* UTF8 */
+
+ /* this function uses the sprintf command to do a vprintf */
+ /* it takes pointers to arguments instead of the arguments themselves */
+ /* The return value is the number of bytes written excluding '\0'
+ if successfull, -1 if the resulting string would be too long and
+ -2 if the format string is errorneous. */
+-static int snprintf_p (char *str, size_t size, const char *fmt,...)
+- __attribute__ ((format (printf, 3, 4)));
+-
+-static int snprintf_p (char *str, size_t size, const char *fmt,...)
++static int snprintf_p (mc_wchar_t *str, size_t size, const mc_wchar_t *fmt,...)
+ {
+ va_list ap;
+ size_t n;
+- const char *q, *p;
+- char *s = str, *e = str + size;
+- char q1[40];
+- char *p1;
++ const mc_wchar_t *q, *p;
++ mc_wchar_t *s = str, *e = str + size;
++ mc_wchar_t q1[40];
++
++ mc_wchar_t *p1;
+ int nargs = 0;
+
+ va_start (ap, fmt);
+ p = q = fmt;
+
++#ifndef UTF8
+ while ((p = strchr (p, '%'))) {
++#else /* UTF8 */
++ while ((p = wcschr (p, L'%'))) {
++#endif /* UTF8 */
+ n = p - q;
+ if (n >= (size_t) (e - s))
+ goto nospc;
++#ifndef UTF8
+ memcpy (s, q, n); /* copy stuff between format specifiers */
++#else /* UTF8 */
++ wmemcpy (s, q, n); /* copy stuff between format specifiers */
++#endif /* UTF8 */
+ s += n;
+ q = p;
+ p1 = q1;
+@@ -1741,45 +1971,78 @@
+ *p1++ = *p++;
+ if (*p == '*') {
+ p++;
++#ifndef UTF8
+ strcpy (p1, MY_itoa (*va_arg (ap, int *))); /* replace field width with a number */
+ p1 += strlen (p1);
++#else /* UTF8 */
++ wcscpy (p1, MY_itoa (*va_arg (ap, int *))); /* replace field width with a number */
++ p1 += wcslen (p1);
++#endif /* UTF8 */
+ } else {
+- while (is_digit (*p) && p1 < q1 + 20)
++#ifndef UTF8
++ while (is_digit (*p)
++#else /* UTF8 */
++ while (iswdigit (*p)
++#endif /* UTF8 */
++ && p1 < q1 + 20)
+ *p1++ = *p++;
+- if (is_digit (*p))
++#ifndef UTF8
++ if (is_digit (*p))
++#else /* UTF8 */
++ if (iswdigit (*p))
++#endif /* UTF8 */
+ goto err;
+ }
+ if (*p == '.')
+ *p1++ = *p++;
+ if (*p == '*') {
+ p++;
++#ifndef UTF8
+ strcpy (p1, MY_itoa (*va_arg (ap, int *))); /* replace precision with a number */
+ p1 += strlen (p1);
++#else /* UTF8 */
++ wcscpy (p1, MY_itoa (*va_arg (ap, int *))); /* replace precision with a number */
++ p1 += wcslen (p1);
++#endif /* UTF8 */
+ } else {
+- while (is_digit (*p) && p1 < q1 + 32)
++#ifndef UTF8
++ while (is_digit (*p)
++#else /* UTF8 */
++ while (iswdigit (*p)
++#endif /* UTF8 */
++ && p1 < q1 + 32)
+ *p1++ = *p++;
+- if (is_digit (*p))
++#ifndef UTF8
++ if (is_digit (*p))
++#else /* UTF8 */
++ if (iswdigit (*p))
++#endif /* UTF8 */
+ goto err;
+ }
+ /* flags done, now get argument */
+ if (*p == 's') {
++#ifndef UTF8
+ snprint (va_arg (ap, char *));
++#else /* UTF8 */
++ *p1++ = 'l';
++ snprint (va_arg (ap, mc_wchar_t *));
++#endif /* UTF8 */
+ } else if (*p == 'h') {
+- if (strchr ("diouxX", *p))
++ if (*p < 128 && strchr ("diouxX", *p))
+ snprint (*va_arg (ap, short *));
+ } else if (*p == 'l') {
+ *p1++ = *p++;
+- if (strchr ("diouxX", *p))
++ if (*p < 128 && strchr ("diouxX", *p))
+ snprint (*va_arg (ap, long *));
+- } else if (strchr ("cdiouxX", *p)) {
++ } else if (*p < 128 && strchr ("cdiouxX", *p)) {
+ snprint (*va_arg (ap, int *));
+ } else if (*p == 'L') {
+ *p1++ = *p++;
+- if (strchr ("EefgG", *p))
++ if (*p < 128 && strchr ("EefgG", *p))
+ snprint (*va_arg (ap, double *)); /* should be long double */
+- } else if (strchr ("EefgG", *p)) {
++ } else if (*p < 128 && strchr ("EefgG", *p)) {
+ snprint (*va_arg (ap, double *));
+- } else if (strchr ("DOU", *p)) {
++ } else if (*p < 128 && strchr ("DOU", *p)) {
+ snprint (*va_arg (ap, long *));
+ } else if (*p == 'p') {
+ snprint (*va_arg (ap, void **));
+@@ -1788,10 +2051,17 @@
+ q = p;
+ }
+ va_end (ap);
++#ifndef UTF8
+ n = strlen (q);
+ if (n >= (size_t) (e - s))
+ return -1;
+ memcpy (s, q, n + 1);
++#else /* UTF8 */
++ n = wcslen (q);
++ if (n >= (size_t) (e - s))
++ return -1;
++ wmemcpy (s, q, n + 1);
++#endif /* UTF8 */
+ return s + n - str;
+ nospc:
+ va_end (ap);
+@@ -1970,8 +2240,11 @@
+ }
+ }
+ if (replace_yes) { /* delete then insert new */
++#ifdef UTF8
++ mc_wchar_t *winput2 = mbstr_to_wchar(input2);
++#endif /* UTF8 */
+ if (replace_scanf) {
+- char repl_str[MAX_REPL_LEN + 2];
++ mc_wchar_t repl_str[MAX_REPL_LEN + 2];
+ int ret = 0;
+
+ /* we need to fill in sargs just like with scanf */
+@@ -1980,17 +2253,25 @@
+ for (k = 1;
+ k < NUM_REPL_ARGS && pmatch[k].rm_eo >= 0;
+ k++) {
++#ifndef UTF8
+ unsigned char *t;
++#else /* UTF8 */
++ mc_wchar_t *t;
++#endif
+
+ if (pmatch[k].rm_eo - pmatch[k].rm_so > 255) {
+ ret = -1;
+ break;
+ }
++#ifndef UTF8
+ t = (unsigned char *) &sargs[k - 1][0];
++#else /* UTF8 */
++ t = (mc_wchar_t *) &sargs[k - 1][0];
++#endif /* UTF8 */
+ for (j = 0;
+ j < pmatch[k].rm_eo - pmatch[k].rm_so
+ && j < 255; j++, t++)
+- *t = (unsigned char) edit_get_byte (edit,
++ *t = edit_get_byte (edit,
+ edit->
+ search_start
+ -
+@@ -2008,14 +2289,23 @@
+ }
+ if (!ret)
+ ret =
++#ifndef UTF8
+ snprintf_p (repl_str, MAX_REPL_LEN + 2, input2,
++#else /* UTF8 */
++ snprintf_p (repl_str, MAX_REPL_LEN + 2, winput2,
++#endif /* UTF8 */
+ PRINTF_ARGS);
+ if (ret >= 0) {
+ times_replaced++;
+ while (i--)
+ edit_delete (edit);
++#ifndef UTF8
+ while (repl_str[++i])
+ edit_insert (edit, repl_str[i]);
++#else /* UTF8 */
++ while (winput2[++i])
++ edit_insert (edit, winput2[i]);
++#endif /* UTF8 */
+ } else {
+ edit_error_dialog (_(" Replace "),
+ ret ==
+@@ -2029,10 +2319,18 @@
+ times_replaced++;
+ while (i--)
+ edit_delete (edit);
++#ifndef UTF8
+ while (input2[++i])
+ edit_insert (edit, input2[i]);
++#else /* UTF8 */
++ while (winput2[++i])
++ edit_insert (edit, winput2[i]);
++#endif /* UTF8 */
+ }
+ edit->found_len = i;
++#ifdef UTF8
++ g_free (winput2);
++#endif /* UTF8 */
+ }
+ /* so that we don't find the same string again */
+ if (replace_backwards) {
+@@ -2205,16 +2503,17 @@
+ #define TEMP_BUF_LEN 1024
+
+ /* Return a null terminated length of text. Result must be g_free'd */
+-static unsigned char *
++static mc_wchar_t *
+ edit_get_block (WEdit *edit, long start, long finish, int *l)
+ {
+- unsigned char *s, *r;
+- r = s = g_malloc (finish - start + 1);
++ mc_wchar_t *s, *r;
++ r = s = g_malloc ((finish - start + 1) * sizeof(mc_wchar_t));
+ if (column_highlighting) {
+ *l = 0;
+ /* copy from buffer, excluding chars that are out of the column 'margins' */
+ while (start < finish) {
+- int c, x;
++ mc_wchar_t c;
++ int x;
+ x = edit_move_forward3 (edit, edit_bol (edit, start), 0,
+ start);
+ c = edit_get_byte (edit, start);
+@@ -2247,11 +2546,15 @@
+ return 0;
+
+ if (column_highlighting) {
+- unsigned char *block, *p;
++ mc_wchar_t *block, *p;
+ int r;
+ p = block = edit_get_block (edit, start, finish, &len);
+ while (len) {
++#ifndef UTF8
+ r = mc_write (file, p, len);
++#else /* UTF8 */
++ r = wchar_write (file, p, len);
++#endif /* UTF8 */
+ if (r < 0)
+ break;
+ p += r;
+@@ -2259,15 +2562,19 @@
+ }
+ g_free (block);
+ } else {
+- unsigned char *buf;
++ mc_wchar_t *buf;
+ int i = start, end;
+ len = finish - start;
+- buf = g_malloc (TEMP_BUF_LEN);
++ buf = g_malloc (TEMP_BUF_LEN * sizeof(mc_wchar_t));
+ while (start != finish) {
+ end = min (finish, start + TEMP_BUF_LEN);
+ for (; i < end; i++)
+ buf[i - start] = edit_get_byte (edit, i);
++#ifndef UTF8
+ len -= mc_write (file, (char *) buf, end - start);
++#else /* UTF8 */
++ len -= wchar_write (file, buf, end - start);
++#endif /* UTF8 */
+ start = end;
+ }
+ g_free (buf);
+@@ -2609,17 +2916,20 @@
+
+ /* prints at the cursor */
+ /* returns the number of chars printed */
++#ifndef UTF8
+ int edit_print_string (WEdit * e, const char *s)
++#else /* UTF8 */
++int edit_print_wstring (WEdit * e, mc_wchar_t *s)
++#endif /* UTF8 */
+ {
+ int i = 0;
+ while (s[i])
+- edit_execute_cmd (e, -1, (unsigned char) s[i++]);
++ edit_execute_cmd (e, -1, s[i++]);
+ e->force |= REDRAW_COMPLETELY;
+ edit_update_screen (e);
+ return i;
+ }
+
+-
+ static void pipe_mail (WEdit *edit, char *to, char *subject, char *cc)
+ {
+ FILE *p = 0;
+@@ -2713,15 +3023,20 @@
+ /* find first character of current word */
+ static int edit_find_word_start (WEdit *edit, long *word_start, int *word_len)
+ {
+- int i, c, last;
++ int i;
++ mc_wint_t c, last;
+
+ /* return if at begin of file */
+ if (edit->curs1 <= 0)
+ return 0;
+
+- c = (unsigned char) edit_get_byte (edit, edit->curs1 - 1);
++ c = edit_get_byte (edit, edit->curs1 - 1);
+ /* return if not at end or in word */
++#ifndef UTF8
+ if (isspace (c) || !(isalnum (c) || c == '_'))
++#else /* UTF8 */
++ if (iswspace (c) || !(iswalnum (c) || c == '_'))
++#endif /* UTF8 */
+ return 0;
+
+ /* search start of word to be completed */
+@@ -2731,11 +3046,19 @@
+ return 0;
+
+ last = c;
+- c = (unsigned char) edit_get_byte (edit, edit->curs1 - i);
++ c = edit_get_byte (edit, edit->curs1 - i);
+
++#ifndef UTF8
+ if (!(isalnum (c) || c == '_')) {
++#else /* UTF8 */
++ if (!(iswalnum (c) || c == '_')) {
++#endif /* UTF8 */
+ /* return if word starts with digit */
++#ifndef UTF8
+ if (isdigit (last))
++#else /* UTF8 */
++ if (iswdigit (last))
++#endif /* UTF8 */
+ return 0;
+
+ *word_start = edit->curs1 - (i - 1); /* start found */
+@@ -2768,7 +3091,7 @@
+ int *num)
+ {
+ int len, max_len = 0, i, skip;
+- unsigned char *bufpos;
++ mc_wchar_t *bufpos;
+
+ /* collect max MAX_WORD_COMPLETIONS completions */
+ while (*num < MAX_WORD_COMPLETIONS) {
+@@ -2787,11 +3110,16 @@
+ buffers1[start >> S_EDIT_BUF_SIZE][start & M_EDIT_BUF_SIZE];
+ skip = 0;
+ for (i = 0; i < *num; i++) {
++#ifndef UTF8
+ if (strncmp
+ ((char *) &compl[i].text[word_len],
+- (char *) &bufpos[word_len], max (len,
+- compl[i].len) -
+- word_len) == 0) {
++ (char *) &bufpos[word_len],
++#else /* UTF8 */
++ if (wcsncmp
++ ((wchar_t *) &compl[i].text[word_len],
++ (wchar_t *) &bufpos[word_len],
++#endif /* UTF8 */
++ max (len, compl[i].len) - word_len) == 0) {
+ skip = 1;
+ break; /* skip it, already added */
+ }
+@@ -2799,7 +3127,7 @@
+ if (skip)
+ continue;
+
+- compl[*num].text = g_malloc (len + 1);
++ compl[*num].text = g_malloc ((len + 1) * sizeof(mc_wchar_t));
+ compl[*num].len = len;
+ for (i = 0; i < len; i++)
+ compl[*num].text[i] = *(bufpos + i);
+@@ -2813,6 +3141,18 @@
+ return max_len;
+ }
+
++#ifdef UTF8
++int edit_print_string (WEdit * e, const char *s)
++{
++ int i;
++ mc_wchar_t *ws = mbstr_to_wchar(s);
++ i = edit_print_wstring (e, ws);
++ g_free(ws);
++ return i;
++}
++
++#endif /* UTF8 */
++
+
+ /* let the user select its preferred completion */
+ static void
+@@ -2825,6 +3165,9 @@
+ WListbox *compl_list;
+ int compl_dlg_h; /* completion dialog height */
+ int compl_dlg_w; /* completion dialog width */
++#ifdef UTF8
++ char *mbtext;
++#endif /* UTF8 */
+
+ /* calculate the dialog metrics */
+ compl_dlg_h = num_compl + 2;
+@@ -2860,9 +3203,18 @@
+ add_widget (compl_dlg, compl_list);
+
+ /* fill the listbox with the completions */
++#ifndef UTF8
+ for (i = 0; i < num_compl; i++)
+ listbox_add_item (compl_list, LISTBOX_APPEND_AT_END, 0,
+ (char *) compl[i].text, NULL);
++#else /* UTF8 */
++ for (i = 0; i < num_compl; i++) {
++ mbtext = wchar_to_mbstr(compl[i].text);
++ listbox_add_item (compl_list, LISTBOX_APPEND_AT_END, 0,
++ mbtext, NULL);
++ g_free(mbtext);
++ }
++#endif /* UTF8 */
+
+ /* pop up the dialog */
+ run_dlg (compl_dlg);
+@@ -2870,9 +3222,17 @@
+ /* apply the choosen completion */
+ if (compl_dlg->ret_value == B_ENTER) {
+ listbox_get_current (compl_list, &curr, NULL);
+- if (curr)
++ if (curr){
++#ifndef UTF8
+ for (curr += word_len; *curr; curr++)
+ edit_insert (edit, *curr);
++#else /* UTF8 */
++ mc_wchar_t *wc, *wccurr = mbstr_to_wchar(curr);
++ for (wc = wccurr + word_len; *wc; wc++)
++ edit_insert (edit, *wc);
++ g_free(wccurr);
++#endif /* UTF8 */
++ }
+ }
+
+ /* destroy dialog before return */
+@@ -2889,8 +3249,9 @@
+ {
+ int word_len = 0, i, num_compl = 0, max_len;
+ long word_start = 0;
+- unsigned char *bufpos;
+- char *match_expr;
++ mc_wchar_t *bufpos;
++ mc_wchar_t *match_expr;
++ char *mbmatch_expr;
+ struct selection compl[MAX_WORD_COMPLETIONS]; /* completions */
+
+ /* don't want to disturb another search */
+@@ -2907,16 +3268,32 @@
+ /* prepare match expression */
+ bufpos = &edit->buffers1[word_start >> S_EDIT_BUF_SIZE]
+ [word_start & M_EDIT_BUF_SIZE];
++
++ match_expr = g_malloc((word_len + 14) * sizeof(mc_wchar_t));
++#ifndef UTF8
+ match_expr = g_strdup_printf ("%.*s[a-zA-Z_0-9]+", word_len, bufpos);
++#else /* UTF8 */
++ wcsncpy (match_expr, bufpos, word_len);
++ match_expr[word_len] = '\0';
++ wcscat (match_expr, L"[a-zA-Z_0-9]+");
++#endif /* UTF8 */
+
+ /* init search: backward, regexp, whole word, case sensitive */
+ edit_set_search_parameters (0, 1, 1, 1, 1);
+
+ /* collect the possible completions */
+ /* start search from curs1 down to begin of file */
++#ifndef UTF8
+ max_len =
+ edit_collect_completions (edit, word_start, word_len, match_expr,
+ (struct selection *) &compl, &num_compl);
++#else /* UTF8 */
++ mbmatch_expr = wchar_to_mbstr(match_expr);
++ max_len =
++ edit_collect_completions (edit, word_start, word_len, mbmatch_expr,
++ (struct selection *) &compl, &num_compl);
++ g_free(mbmatch_expr);
++#endif /* UTF8 */
+
+ if (num_compl > 0) {
+ /* insert completed word if there is only one match */
+--- mc-4.6.2/edit/editdraw.c
++++ mc-4.6.2/edit/editdraw.c
+@@ -71,11 +71,16 @@
+ * as decimal and as hex.
+ */
+ if (edit->curs1 < edit->last_byte) {
+- unsigned char cur_byte = edit_get_byte (edit, edit->curs1);
++ mc_wchar_t cur_byte = edit_get_byte (edit, edit->curs1);
++#ifndef UTF8
+ g_snprintf (byte_str, sizeof (byte_str), "%c %3d 0x%02X",
+ is_printable (cur_byte) ? cur_byte : '.',
+- (int) cur_byte,
+- (unsigned) cur_byte);
++#else /* UTF8 */
++ g_snprintf (byte_str, sizeof(byte_str), "%lc %3d 0x%02X",
++ iswprint(cur_byte) ? cur_byte : '.',
++#endif /* UTF8 */
++ (int) cur_byte,
++ (unsigned) cur_byte);
+ } else {
+ strcpy (byte_str, "<EOF>");
+ }
+@@ -207,11 +212,16 @@
+ #define lowlevel_set_color(x) attrset(MY_COLOR_PAIR(color))
+ #endif
+
++struct line_s {
++ mc_wchar_t ch;
++ unsigned int style;
++};
++
+ static void
+ print_to_widget (WEdit *edit, long row, int start_col, int start_col_real,
+- long end_col, unsigned int line[])
++ long end_col, struct line_s line[])
+ {
+- unsigned int *p;
++ struct line_s *p;
+
+ int x = start_col_real + EDIT_TEXT_HORIZONTAL_OFFSET;
+ int x1 = start_col + EDIT_TEXT_HORIZONTAL_OFFSET;
+@@ -225,9 +235,9 @@
+ edit_move (x1 + FONT_OFFSET_X, y + FONT_OFFSET_Y);
+ p = line;
+
+- while (*p) {
++ while (p->ch) {
+ int style;
+- int textchar;
++ mc_wchar_t textchar;
+ int color;
+
+ if (cols_to_skip) {
+@@ -236,9 +246,9 @@
+ continue;
+ }
+
+- style = *p & 0xFF00;
+- textchar = *p & 0xFF;
+- color = *p >> 16;
++ style = p->style & 0xFF00;
++ textchar = p->ch;
++ color = p->style >> 16;
+
+ if (style & MOD_ABNORMAL) {
+ /* Non-printable - use black background */
+@@ -267,8 +277,11 @@
+ lowlevel_set_color (color);
+ }
+ }
+-
++#ifdef UTF8
++ SLsmg_write_nwchars(&textchar, 1);
++#else
+ addch (textchar);
++#endif
+ p++;
+ }
+ }
+@@ -280,11 +293,11 @@
+ edit_draw_this_line (WEdit *edit, long b, long row, long start_col,
+ long end_col)
+ {
+- static unsigned int line[MAX_LINE_LEN];
+- unsigned int *p = line;
++ struct line_s line[MAX_LINE_LEN];
++ struct line_s *p = line;
+ long m1 = 0, m2 = 0, q, c1, c2;
+ int col, start_col_real;
+- unsigned int c;
++ mc_wint_t c;
+ int color;
+ int i;
+
+@@ -309,62 +322,89 @@
+ }
+
+ while (col <= end_col - edit->start_col) {
+- *p = 0;
++ p->ch = 0;
++ p->style = 0;
+ if (q == edit->curs1)
+- *p |= MOD_CURSOR;
++ p->style |= MOD_CURSOR;
+ if (q >= m1 && q < m2) {
+ if (column_highlighting) {
+ int x;
+ x = edit_move_forward3 (edit, b, 0, q);
+ if (x >= c1 && x < c2)
+- *p |= MOD_MARKED;
++ p->style |= MOD_MARKED;
+ } else
+- *p |= MOD_MARKED;
++ p->style |= MOD_MARKED;
+ }
+ if (q == edit->bracket)
+- *p |= MOD_BOLD;
++ p->style |= MOD_BOLD;
+ if (q >= edit->found_start
+ && q < edit->found_start + edit->found_len)
+- *p |= MOD_BOLD;
++ p->style |= MOD_BOLD;
+ c = edit_get_byte (edit, q);
+ /* we don't use bg for mc - fg contains both */
+ edit_get_syntax_color (edit, q, &color);
+- *p |= color << 16;
++ p->style |= color << 16;
+ switch (c) {
+ case '\n':
+ col = end_col - edit->start_col + 1; /* quit */
+- *(p++) |= ' ';
++ p->ch = ' ';
++ p++;
+ break;
+ case '\t':
+ i = TAB_SIZE - ((int) col % TAB_SIZE);
+ col += i;
+ if (use_colors && visible_tabs) {
+- c = (*p & ~MOD_CURSOR) | MOD_WHITESPACE;
++ c = (p->style & ~MOD_CURSOR) | MOD_WHITESPACE;
+ if (i > 2) {
+- *(p++) |= '<' | MOD_WHITESPACE;
+- while (--i > 1)
+- *(p++) = c | '-';
+- *(p++) = c | '>';
++ p->ch = '<';
++ p->style |= MOD_WHITESPACE;
++ p++;
++ while (--i > 1) {
++ p->style = c;
++ p->ch = '-';
++ p++;
++ }
++ p->style = c;
++ p->ch = '>';
++ p++;
+ } else if (i > 1) {
+- *(p++) |= '<' | MOD_WHITESPACE;
+- *(p++) = c | '>';
+- } else
+- *(p++) |= '>' | MOD_WHITESPACE;
++ p->style |= MOD_WHITESPACE;
++ p->ch = '<';
++ p++;
++ p->style = c;
++ p->ch = '>';
++ p++;
++ } else {
++ p->style |= MOD_WHITESPACE;
++ p->ch = '>';
++ p++;
++ }
+ } else if (use_colors && visible_tws && q >= tws) {
+- *p |= '.' | MOD_WHITESPACE;
+- c = *(p++) & ~MOD_CURSOR;
+- while (--i)
+- *(p++) = c;
++ p->style |= MOD_WHITESPACE;
++ p->ch = '.';
++ p++;
++ c = p->style & ~MOD_CURSOR;
++ while (--i) {
++ p->style = c;
++ p->ch = ' ';
++ p++;
++ }
+ } else {
+- *p |= ' ';
+- c = *(p++) & ~MOD_CURSOR;
+- while (--i)
+- *(p++) = c;
++ p->ch |= ' ';
++ c = p->style & ~MOD_CURSOR;
++ p++;
++ while (--i) {
++ p->style = c;
++ p->ch = ' ';
++ p++;
++ }
+ }
+ break;
+ case ' ':
+ if (use_colors && visible_tws && q >= tws) {
+- *(p++) |= '.' | MOD_WHITESPACE;
++ p->ch = '.';
++ p->style |= MOD_WHITESPACE;
++ p++;
+ col++;
+ break;
+ }
+@@ -374,22 +414,47 @@
+
+ /* Caret notation for control characters */
+ if (c < 32) {
+- *(p++) = '^' | MOD_ABNORMAL;
+- *(p++) = (c + 0x40) | MOD_ABNORMAL;
++ p->ch = '^';
++ p->style = MOD_ABNORMAL;
++ p++;
++ p->ch = c + 0x40;
++ p->style = MOD_ABNORMAL;
+ col += 2;
+ break;
+ }
+ if (c == 127) {
+- *(p++) = '^' | MOD_ABNORMAL;
+- *(p++) = '?' | MOD_ABNORMAL;
++ p->ch = '^';
++ p->style = MOD_ABNORMAL;
++ p++;
++ p->ch = '?';
++ p->style = MOD_ABNORMAL;
++ p++;
+ col += 2;
+ break;
+ }
+
+- if (is_printable (c)) {
+- *(p++) |= c;
++#ifndef UTF8
++ if (is_printable (c)
++#else /* UTF8 */
++ if (iswprint (c)
++#ifdef __STDC_ISO_10646__
++ && (c < BINARY_CHAR_OFFSET || c >= (BINARY_CHAR_OFFSET + 256))
++#endif
++#endif /* UTF8 */
++ ) {
++ p->ch = c;
++ p++;
++
++#ifdef UTF8
++ i = wcwidth(c);
++ if (i > 1) {
++ col += i - 1;
++ }
++#endif /* UTF8 */
+ } else {
+- *(p++) = '.' | MOD_ABNORMAL;
++ p->ch = '.';
++ p->style = MOD_ABNORMAL;
++ p++;
+ }
+ col++;
+ break;
+@@ -400,7 +465,7 @@
+ } else {
+ start_col_real = start_col = 0;
+ }
+- *p = 0;
++ p->ch = 0;
+
+ print_to_widget (edit, row, start_col, start_col_real, end_col, line);
+ }
+--- mc-4.6.2/edit/editkeys.c
++++ mc-4.6.2/edit/editkeys.c
+@@ -183,10 +183,10 @@
+ * 'command' is one of the editor commands from editcmddef.h.
+ */
+ int
+-edit_translate_key (WEdit *edit, long x_key, int *cmd, int *ch)
++edit_translate_key (WEdit *edit, long x_key, int *cmd, mc_wint_t *ch)
+ {
+ int command = CK_Insert_Char;
+- int char_for_insertion = -1;
++ mc_wint_t char_for_insertion = -1;
+ int i = 0;
+ int extmod = 0;
+ const edit_key_map_type *key_map = NULL;
+@@ -243,9 +243,30 @@
+ /* an ordinary insertable character */
+ if (x_key < 256 && !extmod) {
+ int c = convert_from_input_c (x_key);
+-
++#ifdef UTF8
++ mbstate_t mbs;
++ int res;
++ mc_wchar_t wc;
++
++ memset (&mbs, 0, sizeof (mbs));
++
++ if (edit->charpoint >= MB_CUR_MAX) edit->charpoint = 0;
++
++ edit->charbuf[edit->charpoint++] = c;
++
++ res = mbrtowc(&wc, (char *)edit->charbuf, edit->charpoint, &mbs);
++ if (res < 0) {
++ if (res != -2) edit->charpoint = 0; /* broken multibyte char, skip */
++ return 0;
++ }
++ edit->charpoint = 0;
++
++ if (iswprint (wc)) {
++ char_for_insertion = wc;
++#else
+ if (is_printable (c)) {
+ char_for_insertion = c;
++#endif /* UTF8 */
+ goto fin;
+ }
+ }
+@@ -284,7 +305,7 @@
+ *cmd = command;
+ *ch = char_for_insertion;
+
+- if (command == CK_Insert_Char && char_for_insertion == -1) {
++ if (command == CK_Insert_Char && char_for_insertion == (mc_wint_t)-1) {
+ /* unchanged, key has no function here */
+ return 0;
+ }
+--- mc-4.6.2/edit/editwidget.c
++++ mc-4.6.2/edit/editwidget.c
+@@ -333,7 +333,8 @@
+
+ case WIDGET_KEY:
+ {
+- int cmd, ch;
++ int cmd;
++ mc_wint_t ch;
+
+ /* The user may override the access-keys for the menu bar. */
+ if (edit_translate_key (e, parm, &cmd, &ch)) {
+--- mc-4.6.2/edit/wordproc.c
++++ mc-4.6.2/edit/wordproc.c
+@@ -40,7 +40,12 @@
+
+ #define tab_width option_tab_spacing
+
++#ifndef UTF8
+ #define NO_FORMAT_CHARS_START "-+*\\,.;:&>"
++#else /* UTF8 */
++#define NO_FORMAT_CHARS_START L"-+*\\,.;:&>"
++#endif /* UTF8 */
++
+ #define FONT_MEAN_WIDTH 1
+
+ static long
+@@ -57,14 +62,21 @@
+ p = edit_move_forward (edit, p, line - l, 0);
+
+ p = edit_bol (edit, p);
++
++#ifndef UTF8
+ while (strchr ("\t ", edit_get_byte (edit, p)))
++#else /* UTF8 */
++ while (wcschr (L"\t ", edit_get_byte (edit, p)))
++#endif /* UTF8 */
++
+ p++;
+ return p;
+ }
+
+ static int bad_line_start (WEdit * edit, long p)
+ {
+- int c;
++ mc_wint_t c;
++
+ c = edit_get_byte (edit, p);
+ if (c == '.') { /* `...' is acceptable */
+ if (edit_get_byte (edit, p + 1) == '.')
+@@ -78,7 +90,13 @@
+ return 0; /* `---' is acceptable */
+ return 1;
+ }
++
++#ifndef UTF8
+ if (strchr (NO_FORMAT_CHARS_START, c))
++#else /* UTF8 */
++ if (wcschr (NO_FORMAT_CHARS_START, c))
++#endif /* UTF8 */
++
+ return 1;
+ return 0;
+ }
+@@ -131,33 +149,37 @@
+ i - edit->curs_line, 0));
+ }
+
+-static unsigned char *
++static mc_wchar_t *
+ get_paragraph (WEdit *edit, long p, long q, int indent, int *size)
+ {
+- unsigned char *s, *t;
++ mc_wchar_t *s, *t;
+ #if 0
+- t = g_malloc ((q - p) + 2 * (q - p) / option_word_wrap_line_length +
+- 10);
++ t = g_malloc (((q - p) + 2 * (q - p) / option_word_wrap_line_length +
++ 10) * sizeof(mc_wchar_t));
+ #else
+- t = g_malloc (2 * (q - p) + 100);
++ t = g_malloc ((2 * (q - p) + 100) * sizeof(mc_wchar_t));
+ #endif
+ if (!t)
+ return 0;
+ for (s = t; p < q; p++, s++) {
+ if (indent)
+ if (edit_get_byte (edit, p - 1) == '\n')
++#ifndef UTF8
+ while (strchr ("\t ", edit_get_byte (edit, p)))
++#else /* UTF8 */
++ while (wcschr (L"\t ", edit_get_byte (edit, p)))
++#endif /* UTF8 */
+ p++;
+ *s = edit_get_byte (edit, p);
+ }
+- *size = (unsigned long) s - (unsigned long) t;
++ *size = s - t;
+ t[*size] = '\n';
+ return t;
+ }
+
+-static void strip_newlines (unsigned char *t, int size)
++static void strip_newlines (mc_wchar_t *t, int size)
+ {
+- unsigned char *p = t;
++ mc_wchar_t *p = t;
+ while (size--) {
+ *p = *p == '\n' ? ' ' : *p;
+ p++;
+@@ -174,7 +196,7 @@
+ {
+ return x += tab_width - x % tab_width;
+ }
+-static int line_pixel_length (unsigned char *t, long b, int l)
++static int line_pixel_length (mc_wchar_t *t, long b, int l)
+ {
+ int x = 0, c, xn = 0;
+ for (;;) {
+@@ -198,7 +220,7 @@
+ }
+
+ static int
+-next_word_start (unsigned char *t, int q, int size)
++next_word_start (mc_wchar_t *t, int q, int size)
+ {
+ int i;
+ int saw_ws = 0;
+@@ -222,7 +244,7 @@
+
+ /* find the start of a word */
+ static int
+-word_start (unsigned char *t, int q, int size)
++word_start (mc_wchar_t *t, int q, int size)
+ {
+ int i = q;
+ if (t[q] == ' ' || t[q] == '\t')
+@@ -241,7 +263,7 @@
+ }
+
+ /* replaces ' ' with '\n' to properly format a paragraph */
+-static void format_this (unsigned char *t, int size, int indent)
++static void format_this (mc_wchar_t *t, int size, int indent)
+ {
+ int q = 0, ww;
+ strip_newlines (t, size);
+@@ -269,7 +291,7 @@
+ }
+ }
+
+-static void replace_at (WEdit * edit, long q, int c)
++static void replace_at (WEdit * edit, long q, mc_wint_t c)
+ {
+ edit_cursor_move (edit, q - edit->curs1);
+ edit_delete (edit);
+@@ -278,18 +300,27 @@
+
+ /* replaces a block of text */
+ static void
+-put_paragraph (WEdit * edit, unsigned char *t, long p, int indent, int size)
++put_paragraph (WEdit * edit, mc_wchar_t *t, long p, int indent, int size)
+ {
+ long cursor;
+- int i, c = 0;
++ int i;
++ mc_wchar_t c = 0;
+ cursor = edit->curs1;
+ if (indent)
++#ifndef UTF8
+ while (strchr ("\t ", edit_get_byte (edit, p)))
++#else /* UTF8 */
++ while (wcschr (L"\t ", edit_get_byte (edit, p)))
++#endif /* UTF8 */
+ p++;
+ for (i = 0; i < size; i++, p++) {
+ if (i && indent) {
+ if (t[i - 1] == '\n' && c == '\n') {
++#ifndef UTF8
+ while (strchr ("\t ", edit_get_byte (edit, p)))
++#else /* UTF8 */
++ while (wcschr (L"\t ", edit_get_byte (edit, p)))
++#endif /* UTF8 */
+ p++;
+ } else if (t[i - 1] == '\n') {
+ long curs;
+@@ -301,7 +332,11 @@
+ p = edit->curs1;
+ } else if (c == '\n') {
+ edit_cursor_move (edit, p - edit->curs1);
++#ifndef UTF8
+ while (strchr ("\t ", edit_get_byte (edit, p))) {
++#else /* UTF8 */
++ while (wcschr (L"\t ", edit_get_byte (edit, p))) {
++#endif /* UTF8 */
+ edit_delete (edit);
+ if (cursor > edit->curs1)
+ cursor--;
+@@ -334,7 +369,7 @@
+ {
+ long p, q;
+ int size;
+- unsigned char *t;
++ mc_wchar_t *t;
+ int indent = 0;
+ if (option_word_wrap_line_length < 2)
+ return;
+@@ -344,17 +379,25 @@
+ q = end_paragraph (edit, force);
+ indent = test_indent (edit, p, q);
+ t = get_paragraph (edit, p, q, indent, &size);
+- if (!t)
++ if (!t)
+ return;
+ if (!force) {
+ int i;
++#ifndef UTF8
+ if (strchr (NO_FORMAT_CHARS_START, *t)) {
++#else /* UTF8 */
++ if (wcschr (NO_FORMAT_CHARS_START, *t)) {
++#endif /* UTF8 */
+ g_free (t);
+ return;
+ }
+ for (i = 0; i < size - 1; i++) {
+ if (t[i] == '\n') {
++#ifndef UTF8
+ if (strchr (NO_FORMAT_CHARS_START "\t ", t[i + 1])) {
++#else /* UTF8 */
++ if (wcschr (NO_FORMAT_CHARS_START "\t", t[i + 1])) {
++#endif /* UTF8 */
+ g_free (t);
+ return;
+ }
+--- mc-4.6.2/src/achown.c
++++ mc-4.6.2/src/achown.c
+@@ -585,6 +585,12 @@
+ b_att[2] = button_new (XTRACT (6));
+ b_user = button_new (XTRACT (5));
+ b_group = button_new (XTRACT (4));
++#ifdef UTF8
++ if (SLsmg_Is_Unicode) {
++ b_user->text = g_realloc (b_user->text, MB_CUR_MAX * 15 + 1);
++ b_group->text = g_realloc (b_group->text, MB_CUR_MAX * 15 + 1);
++ }
++#endif
+
+ add_widget (ch_dlg, b_group);
+ add_widget (ch_dlg, b_user);
+--- mc-4.6.2/src/boxes.c
++++ mc-4.6.2/src/boxes.c
+@@ -154,23 +154,23 @@
+ display_title = _(display_title);
+ for (i = 0; i < LIST_TYPES; i++) {
+ displays[i] = _(displays[i]);
+- if ((l = strlen (displays[i])) > maxlen)
++ if ((l = mbstrlen (displays[i])) > maxlen)
+ maxlen = l;
+ }
+
+- i = strlen (ok_button) + 5;
+- l = strlen (cancel_button) + 3;
++ i = mbstrlen (ok_button) + 5;
++ l = mbstrlen (cancel_button) + 3;
+ l = max (i, l);
+
+ i = maxlen + l + 16;
+ if (i > DISPLAY_X)
+ DISPLAY_X = i;
+
+- i = strlen (user_mini_status) + 13;
++ i = mbstrlen (user_mini_status) + 13;
+ if (i > DISPLAY_X)
+ DISPLAY_X = i;
+
+- i = strlen (display_title) + 10;
++ i = mbstrlen (display_title) + 10;
+ if (i > DISPLAY_X)
+ DISPLAY_X = i;
+
+@@ -290,20 +290,20 @@
+ int maxlen = 0;
+ for (i = SORT_TYPES - 1; i >= 0; i--) {
+ sort_orders_names[i] = _(sort_orders[i].sort_name);
+- r = strlen (sort_orders_names[i]);
++ r = mbstrlen (sort_orders_names[i]);
+ if (r > maxlen)
+ maxlen = r;
+ }
+
+ check_pos = maxlen + 9;
+
+- r = strlen (reverse_label) + 4;
+- i = strlen (case_label) + 4;
++ r = mbstrlen (reverse_label) + 4;
++ i = mbstrlen (case_label) + 4;
+ if (i > r)
+ r = i;
+
+- l = strlen (ok_button) + 6;
+- i = strlen (cancel_button) + 4;
++ l = mbstrlen (ok_button) + 6;
++ i = mbstrlen (cancel_button) + 4;
+ if (i > l)
+ l = i;
+
+@@ -312,7 +312,7 @@
+ if (i > SORT_X)
+ SORT_X = i;
+
+- i = strlen (sort_title) + 6;
++ i = mbstrlen (sort_title) + 6;
+ if (i > SORT_X)
+ SORT_X = i;
+
+@@ -413,7 +413,7 @@
+ while (i--)
+ {
+ conf_widgets [i].text = _(conf_widgets [i].text);
+- l1 = strlen (conf_widgets [i].text) + 3;
++ l1 = mbstrlen (conf_widgets [i].text) + 3;
+ if (l1 > maxlen)
+ maxlen = l1;
+ }
+@@ -428,8 +428,8 @@
+ * And this for the case when buttons with some space to the right
+ * do not fit within 2/6
+ */
+- l1 = strlen (conf_widgets [0].text) + 3;
+- i = strlen (conf_widgets [1].text) + 5;
++ l1 = mbstrlen (conf_widgets [0].text) + 3;
++ i = mbstrlen (conf_widgets [1].text) + 5;
+ if (i > l1)
+ l1 = i;
+
+@@ -502,11 +502,11 @@
+ {
+ display_widgets [i].text = _(display_widgets[i].text);
+ display_bits_str [i] = _(display_bits_str [i]);
+- l1 = strlen (display_bits_str [i]);
++ l1 = mbstrlen (display_bits_str [i]);
+ if (l1 > maxlen)
+ maxlen = l1;
+ }
+- l1 = strlen (display_widgets [2].text);
++ l1 = mbstrlen (display_widgets [2].text);
+ if (l1 > maxlen)
+ maxlen = l1;
+
+@@ -514,8 +514,8 @@
+ display_bits.xlen = (maxlen + 5) * 6 / 4;
+
+ /* See above confirm_box */
+- l1 = strlen (display_widgets [0].text) + 3;
+- i = strlen (display_widgets [1].text) + 5;
++ l1 = mbstrlen (display_widgets [0].text) + 3;
++ i = mbstrlen (display_widgets [1].text) + 5;
+ if (i > l1)
+ l1 = i;
+
+@@ -610,7 +610,7 @@
+
+ cpname = _("&Select");
+ add_widget (dbits_dlg,
+- button_new (4, DISPX - 8 - strlen (cpname), B_USER,
++ button_new (4, DISPX - 8 - mbstrlen (cpname), B_USER,
+ NORMAL_BUTTON, cpname, sel_charset_button));
+
+ return dbits_dlg;
+@@ -821,7 +821,7 @@
+ quick_widgets [1].y_divisions =
+ quick_widgets [0].y_divisions = Quick_input.ylen = 5;
+
+- len = strlen (quick_widgets [1].text);
++ len = mbstrlen (quick_widgets [1].text);
+
+ quick_widgets [0].relative_x =
+ quick_widgets [1].relative_x + len + 1;
+@@ -980,7 +980,7 @@
+ {
+ job_buttons [i].name = _(job_buttons [i].name);
+
+- len = strlen (job_buttons [i].name) + 4;
++ len = mbstrlen (job_buttons [i].name) + 4;
+ JOBS_X = max (JOBS_X, startx + len + 3);
+
+ job_buttons [i].xpos = startx;
+@@ -989,7 +989,7 @@
+
+ /* Last button - Ok a.k.a. Cancel :) */
+ job_buttons [n_buttons - 1].xpos =
+- JOBS_X - strlen (job_buttons [n_buttons - 1].name) - 7;
++ JOBS_X - mbstrlen (job_buttons [n_buttons - 1].name) - 7;
+
+ i18n_flag = 1;
+ }
+@@ -1047,7 +1047,7 @@
+
+ while (i--)
+ {
+- l1 = strlen (labs [i] = _(labs [i]));
++ l1 = mbstrlen (labs [i] = _(labs [i]));
+ if (l1 > maxlen)
+ maxlen = l1;
+ }
+@@ -1057,7 +1057,7 @@
+
+ for (i = sizeof(buts)/sizeof(buts[0]), l1 = 0; i--; )
+ {
+- l1 += strlen (buts [i] = _(buts [i]));
++ l1 += mbstrlen (buts [i] = _(buts [i]));
+ }
+ l1 += 15;
+ if (l1 > dialog_x)
+@@ -1066,7 +1066,7 @@
+ ilen = dialog_x - 7 - maxlen; /* for the case of very long buttons :) */
+ istart = dialog_x - 3 - ilen;
+
+- b2 = dialog_x - (strlen(buts[1]) + 6);
++ b2 = dialog_x - (mbstrlen(buts[1]) + 6);
+
+ i18n_flag = 1;
+ }
+--- mc-4.6.2/src/dialog.c
++++ mc-4.6.2/src/dialog.c
+@@ -167,7 +167,7 @@
+
+ if (h->title) {
+ attrset (DLG_HOT_NORMALC (h));
+- dlg_move (h, space, (h->cols - strlen (h->title)) / 2);
++ dlg_move (h, space, (h->cols - mbstrlen (h->title)) / 2);
+ addstr (h->title);
+ }
+ }
+--- mc-4.6.2/src/file.c
++++ mc-4.6.2/src/file.c
+@@ -167,15 +167,20 @@
+ do_transform_source (FileOpContext *ctx, const char *source)
+ {
+ size_t j, k, l, len;
+- const char *fnsource = x_basename (source);
++ char *fnsource = g_strdup (x_basename (source));
+ int next_reg;
+ enum CaseConvs case_conv = NO_CONV;
+ static char fntarget[MC_MAXPATHLEN];
+
++#ifdef UTF8
++ fix_utf8(fnsource);
++#endif
++
+ len = strlen (fnsource);
+ j = re_match (&ctx->rx, fnsource, len, 0, &ctx->regs);
+ if (j != len) {
+ transform_error = FILE_SKIP;
++ g_free (fnsource);
+ return NULL;
+ }
+ for (next_reg = 1, j = 0, k = 0; j < strlen (ctx->dest_mask); j++) {
+@@ -225,6 +230,7 @@
+ || ctx->regs.start[next_reg] < 0) {
+ message (1, MSG_ERROR, _(" Invalid target mask "));
+ transform_error = FILE_ABORT;
++ g_free(fnsource);
+ return NULL;
+ }
+ for (l = (size_t) ctx->regs.start[next_reg];
+@@ -239,6 +245,7 @@
+ }
+ }
+ fntarget[k] = 0;
++ g_free(fnsource);
+ return fntarget;
+ }
+
+@@ -1700,13 +1707,13 @@
+ *dp = '\0';
+
+ if (single_source) {
+- i = fmd_xlen - strlen (format_string) - 4;
++ i = fmd_xlen - mbstrlen (format_string) - 4;
+ g_snprintf (cmd_buf, sizeof (cmd_buf), format_string,
+ name_trunc (single_source, i));
+ } else {
+ g_snprintf (cmd_buf, sizeof (cmd_buf), format_string,
+ panel->marked);
+- i = strlen (cmd_buf) + 6 - fmd_xlen;
++ i = mbstrlen (cmd_buf) + 6 - fmd_xlen;
+ if (i > 0) {
+ fmd_xlen += i;
+ fmd_init_i18n (TRUE); /* to recalculate positions of child widgets */
+--- mc-4.6.2/src/filegui.c
++++ mc-4.6.2/src/filegui.c
+@@ -66,6 +66,7 @@
+ #include "filegui.h"
+ #include "key.h" /* get_event */
+ #include "util.h" /* strip_password() */
++#include "tty.h"
+
+ /* }}} */
+
+@@ -564,8 +565,8 @@
+ * longest of "Overwrite..." labels
+ * (assume "Target date..." are short enough)
+ */
+- l1 = max (strlen (rd_widgets[6].text),
+- strlen (rd_widgets[11].text));
++ l1 = max (mbstrlen (rd_widgets[6].text),
++ mbstrlen (rd_widgets[11].text));
+
+ /* longest of button rows */
+ i = sizeof (rd_widgets) / sizeof (rd_widgets[0]);
+@@ -576,7 +577,7 @@
+ l2 = max (l2, l);
+ l = 0;
+ }
+- l += strlen (rd_widgets[i].text) + 4;
++ l += mbstrlen (rd_widgets[i].text) + 4;
+ }
+ }
+ l2 = max (l2, l); /* last row */
+@@ -594,12 +595,12 @@
+ l = l1;
+ }
+ rd_widgets[i].xpos = l;
+- l += strlen (rd_widgets[i].text) + 4;
++ l += mbstrlen (rd_widgets[i].text) + 4;
+ }
+ }
+ /* Abort button is centered */
+ rd_widgets[1].xpos =
+- (rd_xlen - strlen (rd_widgets[1].text) - 3) / 2;
++ (rd_xlen - mbstrlen (rd_widgets[1].text) - 3) / 2;
+ }
+ #endif /* ENABLE_NLS */
+
+@@ -618,7 +619,7 @@
+
+ ADD_RD_LABEL (ui, 0,
+ name_trunc (ui->replace_filename,
+- rd_trunc - strlen (rd_widgets[0].text)), 0);
++ rd_trunc - mbstrlen (rd_widgets[0].text)), 0);
+ ADD_RD_BUTTON (1);
+
+ ADD_RD_BUTTON (2);
+@@ -805,36 +806,36 @@
+ if (fmd_widgets[i].text[0] != '\0')
+ fmd_widgets[i].text = _(fmd_widgets[i].text);
+
+- len = strlen (fmd_widgets[FMCB11].text)
+- + strlen (fmd_widgets[FMCB21].text) + 15;
++ len = mbstrlen (fmd_widgets[FMCB11].text)
++ + mbstrlen (fmd_widgets[FMCB21].text) + 15;
+ fmd_xlen = max (fmd_xlen, len);
+
+- len = strlen (fmd_widgets[FMCB12].text)
+- + strlen (fmd_widgets[FMCB22].text) + 15;
++ len = mbstrlen (fmd_widgets[FMCB12].text)
++ + mbstrlen (fmd_widgets[FMCB22].text) + 15;
+ fmd_xlen = max (fmd_xlen, len);
+
+- len = strlen (fmd_widgets[FMBRGT].text)
+- + strlen (fmd_widgets[FMBLFT].text) + 11;
++ len = mbstrlen (fmd_widgets[FMBRGT].text)
++ + mbstrlen (fmd_widgets[FMBLFT].text) + 11;
+
+ #ifdef FMBMID
+- len += strlen (fmd_widgets[FMBMID].text) + 6;
++ len += mbstrlen (fmd_widgets[FMBMID].text) + 6;
+ #endif
+
+ fmd_xlen = max (fmd_xlen, len + 4);
+
+ len = (fmd_xlen - (len + 6)) / 2;
+ i = fmd_widgets[FMBLFT].relative_x = len + 3;
+- i += strlen (fmd_widgets[FMBLFT].text) + 8;
++ i += mbstrlen (fmd_widgets[FMBLFT].text) + 8;
+
+ #ifdef FMBMID
+ fmd_widgets[FMBMID].relative_x = i;
+- i += strlen (fmd_widgets[FMBMID].text) + 6;
++ i += mbstrlen (fmd_widgets[FMBMID].text) + 6;
+ #endif
+
+ fmd_widgets[FMBRGT].relative_x = i;
+
+ #define chkbox_xpos(i) \
+- fmd_widgets [i].relative_x = fmd_xlen - strlen (fmd_widgets [i].text) - 6
++ fmd_widgets [i].relative_x = fmd_xlen - mbstrlen (fmd_widgets [i].text) - 6
+
+ chkbox_xpos (FMCB0);
+ chkbox_xpos (FMCB21);
+@@ -856,7 +857,7 @@
+
+ char *
+ file_mask_dialog (FileOpContext *ctx, FileOperation operation, const char *text,
+- const char *def_text, int only_one, int *do_background)
++ const char *def_text_orig, int only_one, int *do_background)
+ {
+ int source_easy_patterns = easy_patterns;
+ char *source_mask, *orig_mask, *dest_dir, *tmpdest;
+@@ -865,12 +866,20 @@
+ struct stat buf;
+ int val;
+ QuickDialog Quick_input;
+-
++ char *def_text;
+ g_return_val_if_fail (ctx != NULL, NULL);
++
++ def_text = g_strdup(def_text_orig);
++
+ #if 0
+ message (1, __FUNCTION__, "text = `%s' \n def_text = `%s'", text,
+ def_text);
+ #endif
++
++#ifdef UTF8
++ fix_utf8(def_text);
++#endif
++
+ fmd_init_i18n (FALSE);
+
+ /* Set up the result pointers */
+@@ -929,6 +938,7 @@
+ orig_mask = source_mask;
+ if (!dest_dir || !*dest_dir) {
+ g_free (source_mask);
++ g_free(def_text);
+ return dest_dir;
+ }
+ if (source_easy_patterns) {
+@@ -982,5 +992,6 @@
+ }
+ if (val == B_USER)
+ *do_background = 1;
++ g_free(def_text);
+ return dest_dir;
+ }
+--- mc-4.6.2/src/find.c
++++ mc-4.6.2/src/find.c
+@@ -219,7 +219,7 @@
+ int l1, maxlen = 0;
+
+ while (i--) {
+- l1 = strlen (labs[i] = _(labs[i]));
++ l1 = mbstrlen (labs[i] = _(labs[i]));
+ if (l1 > maxlen)
+ maxlen = l1;
+ }
+@@ -228,7 +228,7 @@
+ FIND_X = i;
+
+ for (i = sizeof (buts) / sizeof (buts[0]), l1 = 0; i--;) {
+- l1 += strlen (buts[i] = _(buts[i]));
++ l1 += mbstrlen (buts[i] = _(buts[i]));
+ }
+ l1 += 21;
+ if (l1 > FIND_X)
+@@ -237,8 +237,8 @@
+ ilen = FIND_X - 7 - maxlen; /* for the case of very long buttons :) */
+ istart = FIND_X - 3 - ilen;
+
+- b1 = b0 + strlen (buts[0]) + 7;
+- b2 = FIND_X - (strlen (buts[2]) + 6);
++ b1 = b0 + mbstrlen (buts[0]) + 7;
++ b2 = FIND_X - (mbstrlen (buts[2]) + 6);
+
+ i18n_flag = 1;
+ case_label = _(case_label);
+@@ -865,7 +865,7 @@
+ if (!i18n_flag) {
+ register int i = sizeof (fbuts) / sizeof (fbuts[0]);
+ while (i--)
+- fbuts[i].len = strlen (fbuts[i].text = _(fbuts[i].text)) + 3;
++ fbuts[i].len = mbstrlen (fbuts[i].text = _(fbuts[i].text)) + 3;
+ fbuts[2].len += 2; /* DEFPUSH_BUTTON */
+ i18n_flag = 1;
+ }
+@@ -1030,7 +1030,7 @@
+
+ if (!next_free) /* first turn i.e clean old list */
+ panel_clean_dir (current_panel);
+- list->list[next_free].fnamelen = strlen (name);
++ list->list[next_free].fnamelen = mbstrlen (name);
+ list->list[next_free].fname = name;
+ list->list[next_free].f.marked = 0;
+ list->list[next_free].f.link_to_dir = link_to_dir;
+--- mc-4.6.2/src/help.c
++++ mc-4.6.2/src/help.c
+@@ -416,10 +416,28 @@
+ #ifndef HAVE_SLANG
+ addch (acs_map [c]);
+ #else
++#if defined(UTF8) && SLANG_VERSION < 20000
++ SLsmg_draw_object (h->y + line + 2, h->x + col + 2, acs_map [c]);
++#else
+ SLsmg_draw_object (h->y + line + 2, h->x + col + 2, c);
++#endif /* UTF8 */
+ #endif
++ } else {
++#ifdef UTF8
++ if (SLsmg_Is_Unicode) {
++ int len;
++ mbstate_t mbs;
++ wchar_t wc;
++ memset (&mbs, 0, sizeof (mbs));
++ len = mbrtowc(&wc, p, MB_CUR_MAX, &mbs);
++ if (len <= 0) len = 1; /* skip broken multibyte chars */
++
++ SLsmg_write_nwchars(&wc, 1);
++ p += len - 1;
+ } else
++#endif
+ addch (c);
++ }
+ col++;
+ break;
+ }
+@@ -772,6 +790,12 @@
+ message (1, MSG_ERROR, _(" Cannot open file %s \n %s "), filename ? filename : hlpfile,
+ unix_error_string (errno));
+ }
++ else
++ {
++ char *conv = utf8_to_local(data);
++ g_free(data);
++ data = conv;
++ }
+
+ if (!filename)
+ g_free (hlpfile);
+--- mc-4.6.2/src/hotlist.c
++++ mc-4.6.2/src/hotlist.c
+@@ -566,7 +566,7 @@
+
+ row = hotlist_but [i].y;
+ ++count [row];
+- len [row] += strlen (hotlist_but [i].text) + 5;
++ len [row] += mbstrlen (hotlist_but [i].text) + 5;
+ if (hotlist_but [i].flags == DEFPUSH_BUTTON)
+ len [row] += 2;
+ }
+@@ -591,12 +591,12 @@
+ /* not first int the row */
+ if (!strcmp (hotlist_but [i].text, cancel_but))
+ hotlist_but [i].x =
+- cols - strlen (hotlist_but [i].text) - 13;
++ cols - mbstrlen (hotlist_but [i].text) - 13;
+ else
+ hotlist_but [i].x = cur_x [row];
+ }
+
+- cur_x [row] += strlen (hotlist_but [i].text) + 2
++ cur_x [row] += mbstrlen (hotlist_but [i].text) + 2
+ + (hotlist_but [i].flags == DEFPUSH_BUTTON ? 5 : 3);
+ }
+ }
+@@ -837,7 +837,7 @@
+ for (i = 0; i < 3; i++)
+ {
+ qw [i].text = _(qw [i].text);
+- l[i] = strlen (qw [i].text) + 3;
++ l[i] = mbstrlen (qw [i].text) + 3;
+ }
+ space = (len - 4 - l[0] - l[1] - l[2]) / 4;
+
+@@ -886,7 +886,7 @@
+
+ msglen(text1, &lines1, &cols1);
+ msglen(text2, &lines2, &cols2);
+- len = max ((int) strlen (header), cols1);
++ len = max ((int) mbstrlen (header), cols1);
+ len = max (len, cols2) + 4;
+ len = max (len, 64);
+
+@@ -982,7 +982,7 @@
+ #endif /* ENABLE_NLS */
+
+ msglen (label, &lines, &cols);
+- len = max ((int) strlen (header), cols) + 4;
++ len = max ((int) mbstrlen (header), cols) + 4;
+ len = max (len, 64);
+
+ #ifdef ENABLE_NLS
+@@ -1038,7 +1038,7 @@
+ {
+ char *prompt, *label;
+ const char *cp = _("Label for \"%s\":");
+- int l = strlen (cp);
++ int l = mbstrlen (cp);
+ char *label_string = g_strdup (current_panel->cwd);
+
+ strip_password (label_string, 1);
+--- mc-4.6.2/src/layout.c
++++ mc-4.6.2/src/layout.c
+@@ -367,36 +367,36 @@
+
+ while (i--) {
+ s_split_direction[i] = _(s_split_direction[i]);
+- l1 = strlen (s_split_direction[i]) + 7;
++ l1 = mbstrlen (s_split_direction[i]) + 7;
+ if (l1 > first_width)
+ first_width = l1;
+ }
+
+ for (i = 0; i <= 8; i++) {
+ check_options[i].text = _(check_options[i].text);
+- l1 = strlen (check_options[i].text) + 7;
++ l1 = mbstrlen (check_options[i].text) + 7;
+ if (l1 > first_width)
+ first_width = l1;
+ }
+
+- l1 = strlen (title1) + 1;
++ l1 = mbstrlen (title1) + 1;
+ if (l1 > first_width)
+ first_width = l1;
+
+- l1 = strlen (title2) + 1;
++ l1 = mbstrlen (title2) + 1;
+ if (l1 > first_width)
+ first_width = l1;
+
+
+- second_width = strlen (title3) + 1;
++ second_width = mbstrlen (title3) + 1;
+ for (i = 0; i < 6; i++) {
+ check_options[i].text = _(check_options[i].text);
+- l1 = strlen (check_options[i].text) + 7;
++ l1 = mbstrlen (check_options[i].text) + 7;
+ if (l1 > second_width)
+ second_width = l1;
+ }
+ if (console_flag) {
+- l1 = strlen (output_lines_label) + 13;
++ l1 = mbstrlen (output_lines_label) + 13;
+ if (l1 > second_width)
+ second_width = l1;
+ }
+@@ -410,14 +410,14 @@
+ *
+ * Now the last thing to do - properly space buttons...
+ */
+- l1 = 11 + strlen (ok_button) /* 14 - all brackets and inner space */
+- +strlen (save_button) /* notice: it is 3 char less because */
+- +strlen (cancel_button); /* of '&' char in button text */
++ l1 = 11 + mbstrlen (ok_button) /* 14 - all brackets and inner space */
++ +mbstrlen (save_button) /* notice: it is 3 char less because */
++ +mbstrlen (cancel_button); /* of '&' char in button text */
+
+ i = (first_width + second_width - l1) / 4;
+ b1 = 5 + i;
+- b2 = b1 + strlen (ok_button) + i + 6;
+- b3 = b2 + strlen (save_button) + i + 4;
++ b2 = b1 + mbstrlen (ok_button) + i + 6;
++ b3 = b2 + mbstrlen (save_button) + i + 4;
+
+ i18n_layt_flag = 1;
+ }
+@@ -681,7 +681,7 @@
+ panel_do_cols (0);
+ panel_do_cols (1);
+
+- promptl = strlen (prompt);
++ promptl = mbstrlen (prompt);
+
+ widget_set_size (&the_menubar->widget, 0, 0, 1, COLS);
+
+--- mc-4.6.2/src/learn.c
++++ mc-4.6.2/src/learn.c
+@@ -238,7 +238,7 @@
+ learn_but[0].x = 78 / 2 + 4;
+
+ learn_but[1].text = _(learn_but[1].text);
+- learn_but[1].x = 78 / 2 - (strlen (learn_but[1].text) + 9);
++ learn_but[1].x = 78 / 2 - (mbstrlen (learn_but[1].text) + 9);
+
+ learn_title = _(learn_title);
+ i18n_flag = 1;
+--- mc-4.6.2/src/main.c
++++ mc-4.6.2/src/main.c
+@@ -706,7 +706,7 @@
+ int prompt_len;
+
+ tmp_prompt = strip_ctrl_codes (subshell_prompt);
+- prompt_len = strlen (tmp_prompt);
++ prompt_len = mbstrlen (tmp_prompt);
+
+ /* Check for prompts too big */
+ if (COLS > 8 && prompt_len > COLS - 8) {
+@@ -1614,7 +1614,11 @@
+ if (xterm_flag && xterm_title) {
+ p = s = g_strdup (strip_home_and_password (current_panel->cwd));
+ do {
++#ifndef UTF8
+ if (!is_printable ((unsigned char) *s))
++#else /* UTF8 */
++ if (*(unsigned char *)s < ' ')
++#endif /* UTF8 */
+ *s = '?';
+ } while (*++s);
+ if (!alternate_plus_minus)
+--- mc-4.6.2/src/menu.c
++++ mc-4.6.2/src/menu.c
+@@ -23,6 +23,7 @@
+ #include <string.h>
+
+ #include <sys/types.h>
++#include <wchar.h>
+
+ #include "global.h"
+ #include "tty.h"
+@@ -54,35 +55,95 @@
+ {
+ Menu *menu;
+ const char *cp;
++ int wlen = 0;
++ mbstate_t s;
+
+ menu = (Menu *) g_malloc (sizeof (*menu));
+ menu->count = count;
+ menu->max_entry_len = 20;
+ menu->entries = entries;
++ menu->name = g_strdup (name);
++ menu_scan_hotkey (menu);
++#ifdef UTF8
++ menu->wentries = NULL;
++ menu->wname = NULL;
++ if (SLsmg_Is_Unicode) {
++ const char *str = menu->name;
++ memset (&s, 0, sizeof (s));
++ wlen = mbsrtowcs (NULL, &str, -1, &s);
++ if (wlen > 0)
++ ++wlen;
++ else {
++ wlen = 0;
++ memset (&s, 0, sizeof (s));
++ }
++ }
++#endif
+
+ if (entries != (menu_entry*) NULL) {
+ register menu_entry* mp;
+ for (mp = entries; count--; mp++) {
+ if (mp->text[0] != '\0') {
++ int len;
+ #ifdef ENABLE_NLS
+ mp->text = _(mp->text);
+ #endif /* ENABLE_NLS */
+ cp = strchr (mp->text,'&');
++#ifdef UTF8
++ if (SLsmg_Is_Unicode) {
++ len = mbstrlen(mp->text) + 1;
++ wlen += len;
++ menu->max_entry_len = max (len - 1, menu->max_entry_len);
++ } else
++#endif
++ len = strlen (mp->text);
+
+ if (cp != NULL && *(cp+1) != '\0') {
+ mp->hot_key = tolower ((unsigned char) *(cp+1));
+- menu->max_entry_len = max ((int) (strlen (mp->text) - 1),
+- menu->max_entry_len);
++ menu->max_entry_len = max (len - 1, menu->max_entry_len);
+ } else {
+- menu->max_entry_len = max ((int) strlen (mp->text),
+- menu->max_entry_len);
++ menu->max_entry_len = max (len, menu->max_entry_len);
+ }
+ }
+ }
+ }
+
+- menu->name = g_strdup (name);
+- menu_scan_hotkey(menu);
++#ifdef UTF8
++ if (wlen) {
++ wchar_t *wp;
++ const char *str;
++ int len;
++
++ menu->wentries = (wchar_t **)
++ g_malloc (sizeof (wchar_t *) * menu->count
++ + wlen * sizeof (wchar_t));
++ wp = (wchar_t *) (menu->wentries + menu->count);
++ str = menu->name;
++ len = mbsrtowcs (wp, &str, wlen, &s);
++ if (len > 0) {
++ menu->wname = wp;
++ wlen -= len + 1;
++ wp += len + 1;
++ } else
++ memset (&s, 0, sizeof (s));
++ if (menu->entries != NULL)
++ for (count = 0; count < menu->count; ++count)
++ if (menu->entries[count].text[0] != '\0') {
++ str = menu->entries[count].text;
++ menu->wentries[count] = wp;
++ len = mbsrtowcs (wp, &str, wlen, &s);
++ if (len > 0) {
++ wlen -= len + 1;
++ wp += len + 1;
++ } else {
++ memset (&s, 0, sizeof (s));
++ *wp++ = L'\0';
++ --wlen;
++ }
++ }
++ }
++#endif
++
+ menu->start_x = 0;
+ menu->help_node = g_strdup (help_node);
+ return menu;
+@@ -113,8 +174,26 @@
+ const char *text;
+
+ addch((unsigned char)menu->entries [idx].first_letter);
+- for (text = menu->entries [idx].text; *text; text++)
+- {
++#ifdef UTF8
++ if (menu->wentries) {
++ wchar_t *wtext, *wp;
++
++ for (wtext = wp = menu->wentries [idx]; *wtext; wtext++) {
++ if (*wtext == L'&') {
++ if (wtext > wp)
++ SLsmg_write_nwchars (wp, wtext - wp);
++ attrset (color == MENU_SELECTED_COLOR ?
++ MENU_HOTSEL_COLOR : MENU_HOT_COLOR);
++ SLsmg_write_nwchars (++wtext, 1);
++ attrset (color);
++ wp = wtext + 1;
++ }
++ }
++ if (wtext > wp)
++ SLsmg_write_nwchars (wp, wtext - wp);
++ } else
++#endif
++ for (text = menu->entries [idx].text; *text; text++) {
+ if (*text != '&')
+ addch(*text);
+ else {
+@@ -123,7 +202,7 @@
+ addch(*(++text));
+ attrset(color);
+ }
+- }
++ }
+ }
+ widget_move (&menubar->widget, y, x + 1);
+ }
+@@ -169,6 +248,12 @@
+ if (menubar->active)
+ attrset(i == menubar->selected?MENU_SELECTED_COLOR:SELECTED_COLOR);
+ widget_move (&menubar->widget, 0, menubar->menu [i]->start_x);
++#ifdef UTF8
++ if (menubar->menu [i]->wname)
++ SLsmg_write_nwchars (menubar->menu [i]->wname,
++ wcslen (menubar->menu [i]->wname));
++ else
++#endif
+ tty_printf ("%s", menubar->menu [i]->name);
+ }
+
+@@ -494,7 +579,13 @@
+
+ for (i = 0; i < items; i++)
+ {
+- int len = strlen(menubar->menu[i]->name);
++ int len;
++#ifdef UTF8
++ if (menubar->menu[i]->wname)
++ len = wcslen (menubar->menu[i]->wname);
++ else
++#endif
++ len = strlen(menubar->menu[i]->name);
+ menubar->menu[i]->start_x = start_x;
+ start_x += len + gap;
+ }
+@@ -507,7 +598,13 @@
+ for (i = 0; i < items; i++)
+ {
+ /* preserve length here, to be used below */
+- gap -= (menubar->menu[i]->start_x = strlen(menubar->menu[i]->name));
++#ifdef UTF8
++ if (menubar->menu[i]->wname)
++ menubar->menu[i]->start_x = wcslen (menubar->menu[i]->wname);
++ else
++#endif
++ menubar->menu[i]->start_x = strlen (menubar->menu[i]->name);
++ gap -= menubar->menu[i]->start_x;
+ }
+
+ gap /= (items - 1);
+@@ -531,6 +628,9 @@
+ void
+ destroy_menu (Menu *menu)
+ {
++#ifdef UTF8
++ g_free (menu->wentries);
++#endif
+ g_free (menu->name);
+ g_free (menu->help_node);
+ g_free (menu);
+--- mc-4.6.2/src/menu.h
++++ mc-4.6.2/src/menu.h
+@@ -21,6 +21,8 @@
+ menu_entry *entries;
+ int start_x; /* position relative to menubar start */
+ char *help_node;
++ wchar_t **wentries;
++ wchar_t *wname;
+ } Menu;
+
+ extern int menubar_visible;
+--- mc-4.6.2/src/myslang.h
++++ mc-4.6.2/src/myslang.h
+@@ -11,6 +11,16 @@
+ #endif /* HAVE_SLANG_SLANG_H */
+ #endif
+
++#if SLANG_VERSION >= 20000
++#define UTF8 1
++#define SLsmg_Is_Unicode SLsmg_is_utf8_mode()
++void SLsmg_write_nwchars(wchar_t *s, size_t n);
++#endif
++
++#ifdef UTF8
++# include <wchar.h>
++#endif
++
+ enum {
+ KEY_BACKSPACE = 400,
+ KEY_END, KEY_UP, KEY_DOWN, KEY_LEFT, KEY_RIGHT,
+--- mc-4.6.2/src/option.c
++++ mc-4.6.2/src/option.c
+@@ -124,12 +124,12 @@
+ title2 = _(" Pause after run... ");
+ title3 = _(" Other options ");
+
+- first_width = strlen (title1) + 1;
+- second_width = strlen (title3) + 1;
++ first_width = mbstrlen (title1) + 1;
++ second_width = mbstrlen (title3) + 1;
+
+ for (i = 0; check_options[i].text; i++) {
+ check_options[i].text = _(check_options[i].text);
+- l1 = strlen (check_options[i].text) + 7;
++ l1 = mbstrlen (check_options[i].text) + 7;
+ if (i >= OTHER_OPTIONS) {
+ if (l1 > first_width)
+ first_width = l1;
+@@ -142,23 +142,23 @@
+ i = PAUSE_OPTIONS;
+ while (i--) {
+ pause_options[i] = _(pause_options[i]);
+- l1 = strlen (pause_options[i]) + 7;
++ l1 = mbstrlen (pause_options[i]) + 7;
+ if (l1 > first_width)
+ first_width = l1;
+ }
+
+- l1 = strlen (title2) + 1;
++ l1 = mbstrlen (title2) + 1;
+ if (l1 > first_width)
+ first_width = l1;
+
+- l1 = 11 + strlen (ok_button)
+- + strlen (save_button)
+- + strlen (cancel_button);
++ l1 = 11 + mbstrlen (ok_button)
++ + mbstrlen (save_button)
++ + mbstrlen (cancel_button);
+
+ i = (first_width + second_width - l1) / 4;
+ b1 = 5 + i;
+- b2 = b1 + strlen (ok_button) + i + 6;
+- b3 = b2 + strlen (save_button) + i + 4;
++ b2 = b1 + mbstrlen (ok_button) + i + 6;
++ b3 = b2 + mbstrlen (save_button) + i + 4;
+
+ i18n_config_flag = 1;
+ }
+--- mc-4.6.2/src/panelize.c
++++ mc-4.6.2/src/panelize.c
+@@ -129,7 +129,7 @@
+ i = sizeof (panelize_but) / sizeof (panelize_but[0]);
+ while (i--) {
+ panelize_but[i].text = _(panelize_but[i].text);
+- maxlen += strlen (panelize_but[i].text) + 5;
++ maxlen += mbstrlen (panelize_but[i].text) + 5;
+ }
+ maxlen += 10;
+
+@@ -138,11 +138,11 @@
+ panelize_cols = max (panelize_cols, maxlen);
+
+ panelize_but[2].x =
+- panelize_but[3].x + strlen (panelize_but[3].text) + 7;
++ panelize_but[3].x + mbstrlen (panelize_but[3].text) + 7;
+ panelize_but[1].x =
+- panelize_but[2].x + strlen (panelize_but[2].text) + 5;
++ panelize_but[2].x + mbstrlen (panelize_but[2].text) + 5;
+ panelize_but[0].x =
+- panelize_cols - strlen (panelize_but[0].text) - 8 - BX;
++ panelize_cols - mbstrlen (panelize_but[0].text) - 8 - BX;
+
+ #endif /* ENABLE_NLS */
+
+--- mc-4.6.2/src/screen.c
++++ mc-4.6.2/src/screen.c
+@@ -173,21 +173,56 @@
+ static const char *
+ string_file_name (file_entry *fe, int len)
+ {
+- static char buffer [MC_MAXPATHLEN + 1];
+ size_t i;
+
+- for (i = 0; i < sizeof(buffer) - 1; i++) {
+- char c;
++#ifdef UTF8
++ static char buffer [BUF_SMALL * 4];
++ mbstate_t s;
++ int mbmax = MB_CUR_MAX;
++ const char *str = fe->fname;
+
+- c = fe->fname[i];
++ memset (&s, 0, sizeof (s));
++#else
++ static char buffer [BUF_SMALL];
++#endif
+
+- if (!c)
+- break;
++#ifdef UTF8
++ if (SLsmg_Is_Unicode)
++ for (i = 0; i < sizeof (buffer) - 1; i++) {
++ wchar_t wc;
++ int len;
+
+- if (!is_printable(c))
+- c = '?';
++ len = mbrtowc (&wc, str, mbmax, &s);
++ if (!len)
++ break;
++ if (len < 0) {
++ memset (&s, 0, sizeof (s));
++ buffer[i] = '?';
++ str++;
++ continue;
++ }
++ if (!is_printable (wc)) {
++ buffer[i] = '?';
++ str++;
++ continue;
++ }
++ if (i >= sizeof (buffer) - len)
++ break;
++ memcpy (buffer + i, str, len);
++ i += len - 1;
++ str += len;
++ } else
++#endif
++ for (i = 0; i < sizeof(buffer) - 1; i++) {
++ char c;
++
++ c = fe->fname[i];
+
+- buffer[i] = c;
++ if (!c) break;
++
++ if (!is_printable(c)) c = '?';
++
++ buffer[i] = c;
+ }
+
+ buffer[i] = 0;
+@@ -452,42 +487,6 @@
+ { "dot", 1, 0, J_RIGHT, " ", 0, string_dot, NULL },
+ };
+
+-static char *
+-to_buffer (char *dest, int just_mode, int len, const char *txt)
+-{
+- int txtlen = strlen (txt);
+- int still, over;
+-
+- /* Fill buffer with spaces */
+- memset (dest, ' ', len);
+-
+- still = (over=(txtlen > len)) ? (txtlen - len) : (len - txtlen);
+-
+- switch (HIDE_FIT(just_mode)){
+- case J_LEFT:
+- still = 0;
+- break;
+- case J_CENTER:
+- still /= 2;
+- break;
+- case J_RIGHT:
+- default:
+- break;
+- }
+-
+- if (over){
+- if (IS_FIT(just_mode))
+- strcpy (dest, name_trunc(txt, len));
+- else
+- strncpy (dest, txt+still, len);
+- } else
+- strncpy (dest+still, txt, txtlen);
+-
+- dest[len] = '\0';
+-
+- return (dest + len);
+-}
+-
+ static int
+ file_compute_color (int attr, file_entry *fe)
+ {
+@@ -541,14 +540,18 @@
+
+ /* Formats the file number file_index of panel in the buffer dest */
+ static void
+-format_file (char *dest, int limit, WPanel *panel, int file_index, int width, int attr, int isstatus)
++format_file (WPanel *panel, int file_index, int width, int attr, int isstatus)
+ {
+ int color, length, empty_line;
+ const char *txt;
+- char *old_pos;
+- char *cdest = dest;
+ format_e *format, *home;
+ file_entry *fe;
++#ifdef UTF8
++ char buffer[BUF_MEDIUM * sizeof (wchar_t)];
++#else
++ char buffer[BUF_MEDIUM];
++#endif
++ int txtwidth = 0;
+
+ length = 0;
+ empty_line = (file_index >= panel->count);
+@@ -566,34 +569,137 @@
+ break;
+
+ if (format->string_fn){
+- int len;
++ int len, still, over, perm, txtlen, wide;
+
+ if (empty_line)
+ txt = " ";
+ else
+ txt = (*format->string_fn)(fe, format->field_len);
+
+- old_pos = cdest;
+-
+ len = format->field_len;
+ if (len + length > width)
+ len = width - length;
+- if (len + (cdest - dest) > limit)
+- len = limit - (cdest - dest);
++ if (len >= BUF_MEDIUM)
++ len = BUF_MEDIUM - 1;
+ if (len <= 0)
+ break;
+- cdest = to_buffer (cdest, format->just_mode, len, txt);
+- length += len;
+
+- attrset (color);
++ perm = 0;
++ if (permission_mode) {
++ if (!strcmp(format->id, "perm"))
++ perm = 1;
++ else if (!strcmp(format->id, "mode"))
++ perm = 2;
++ }
+
+- if (permission_mode && !strcmp(format->id, "perm"))
+- add_permission_string (old_pos, format->field_len, fe, attr, color, 0);
+- else if (permission_mode && !strcmp(format->id, "mode"))
+- add_permission_string (old_pos, format->field_len, fe, attr, color, 1);
+- else
+- addstr (old_pos);
++ wide = 0;
++#ifdef UTF8
++ if (SLsmg_Is_Unicode && !empty_line && !perm) {
++ mbstate_t s;
++ const char *str = txt;
++
++ memset (&s, 0, sizeof (s));
++ txtlen = mbsrtowcs ((wchar_t *) buffer, &str,
++ sizeof (buffer) / sizeof (wchar_t), &s);
++ if (txtlen < 0) {
++ txt = " ";
++ txtlen = 1;
++ } else {
++ wide = 1;
++ txtwidth = wcswidth((wchar_t*)buffer, txtlen);
++ }
++ } else
++#endif
++ {
++ txtlen = mbstrlen (txt);
++ txtwidth = txtlen;
++ }
++
++ over = txtwidth > len;
++ still = over ? txtlen - len : len - txtlen;
++
++ switch (HIDE_FIT(format->just_mode)) {
++ case J_LEFT:
++ still = 0;
++ break;
++ case J_CENTER:
++ still /= 2;
++ break;
++ case J_RIGHT:
++ default:
++ break;
++ }
++
++ attrset (color);
++
++ if (wide) {
++#ifdef UTF8
++ if (over) {
++ if (IS_FIT (format->just_mode)) {
++ int n1 = 0;
++ int width1 = 0;
++ int n2 = 0;
++ int width2 = 0;
++ int len1 = len / 2;
++ int len2;
++
++ while (1) {
++ int w = wcwidth(((wchar_t *) buffer)[n1]);
++ if (width1 + w <= len1) {
++ width1 += w;
++ n1++;
++ }
++ else
++ break;
++ }
++ len2 = len - width1 - 1;
++
++ while (1) {
++ int w = wcwidth(((wchar_t *) buffer)[txtlen - n2 - 1]);
++ if (width2 + w <= len2) {
++ width2 += w;
++ n2++;
++ }
++ else
++ break;
++ }
++
++
++ SLsmg_write_nwchars ((wchar_t *) buffer, n1);
++ SLsmg_write_nwchars (L"~", 1);
++ printw ("%*s", len - width1 - width2 - 1, "");
++ SLsmg_write_nwchars (((wchar_t *) buffer)
++ + txtlen - n2, n2);
++ } else
++ SLsmg_write_nwchars ((wchar_t *) buffer, len);
++ } else {
++ printw ("%*s", still, "");
++ SLsmg_write_nwchars ((wchar_t *) buffer, txtlen);
++ printw ("%*s", len - txtwidth - still, "");
++ }
++#endif
++ } else {
++ if (over) {
++ if (IS_FIT (format->just_mode))
++ strcpy (buffer, name_trunc(txt, len));
++ else
++ memcpy (buffer, txt + still, len);
++ } else {
++ memset (buffer, ' ', still);
++ memcpy (buffer + still, txt, txtlen);
++ memset (buffer + still + txtlen, ' ',
++ len - txtlen - still);
++ }
++ buffer[len] = '\0';
+
++ if (perm)
++ add_permission_string (buffer, format->field_len, fe,
++ attr, color, perm - 1);
++ else
++ addstr (buffer);
++ }
++
++ length += len;
+ } else {
+ if (attr == SELECTED || attr == MARKED_SELECTED)
+ attrset (SELECTED_COLOR);
+@@ -616,7 +722,6 @@
+ {
+ int second_column = 0;
+ int width, offset;
+- char buffer [BUF_MEDIUM];
+
+ offset = 0;
+ if (!isstatus && panel->split){
+@@ -645,7 +750,7 @@
+ widget_move (&panel->widget, file_index - panel->top_file + 2, 1);
+ }
+
+- format_file (buffer, sizeof(buffer), panel, file_index, width, attr, isstatus);
++ format_file (panel, file_index, width, attr, isstatus);
+
+ if (!isstatus && panel->split){
+ if (second_column)
+@@ -694,7 +799,7 @@
+ ngettext("%s in %d file", "%s in %d files", panel->marked),
+ b_bytes, panel->marked);
+
+- if ((int) strlen (buffer) > cols-2){
++ if ((int) mbstrlen (buffer) > cols-2){
+ buffer [cols] = 0;
+ p += 2;
+ } else
+@@ -1107,6 +1212,12 @@
+ int side, width;
+
+ const char *txt;
++#ifdef UTF8
++ char buffer[30 * sizeof (wchar_t)];
++ mbstate_t s;
++
++ memset (&s, 0, sizeof (s));
++#endif
+ if (!panel->split)
+ adjust_top_file (panel);
+
+@@ -1131,16 +1242,38 @@
+ if (format->string_fn){
+ txt = format->title;
+
+- header_len = strlen (txt);
++ attrset (MARKED_COLOR);
++ width -= format->field_len;
++#ifdef UTF8
++ if (SLsmg_Is_Unicode) {
++ const char *str = txt;
++ header_len = mbsrtowcs ((wchar_t *) buffer, &str,
++ sizeof (buffer) / sizeof (wchar_t),
++ &s);
++ if (header_len < 0) {
++ memset (&s, 0, sizeof (s));
++ printw ("%*s", format->field_len, "");
++ continue;
++ }
++ if (header_len > format->field_len)
++ header_len = format->field_len;
++ spaces = (format->field_len - header_len) / 2;
++ extra = (format->field_len - header_len) % 2;
++ printw ("%*s", spaces, "");
++ SLsmg_write_nwchars ((wchar_t *) buffer, header_len);
++ printw ("%*s", spaces + extra, "");
++ continue;
++ }
++#endif
++
++ header_len = mbstrlen (txt);
+ if (header_len > format->field_len)
+ header_len = format->field_len;
+
+- attrset (MARKED_COLOR);
+ spaces = (format->field_len - header_len) / 2;
+ extra = (format->field_len - header_len) % 2;
+ tty_printf ("%*s%.*s%*s", spaces, "",
+ header_len, txt, spaces+extra, "");
+- width -= 2 * spaces + extra + header_len;
+ } else {
+ attrset (NORMAL_COLOR);
+ one_vline ();
+@@ -1897,11 +2030,24 @@
+ int i;
+ int wrapped = 0;
+ int found;
++ int prevpos, pos;
++ int j;
++ mbstate_t mbs;
+
+ l = strlen (panel->search_buffer);
+ if (c_code == KEY_BACKSPACE) {
+- if (l)
+- panel->search_buffer[--l] = '\0';
++ if (l) {
++ prevpos = pos = 0;
++ memset (&mbs, 0, sizeof (mbs));
++ while (pos < l) {
++ prevpos = pos;
++ j = mbrlen (panel->search_buffer + pos, l - pos, &mbs);
++ if (j <= 0) break;
++ pos += j;
++ }
++ --l;
++ panel->search_buffer[prevpos] = 0;
++ }
+ } else {
+ if (c_code && l < sizeof (panel->search_buffer)) {
+ panel->search_buffer[l] = c_code;
+@@ -1910,6 +2056,14 @@
+ }
+ }
+
++ prevpos = pos = 0;
++ memset (&mbs, 0, sizeof (mbs));
++ while (pos < l) {
++ prevpos = pos;
++ j = mbrlen (panel->search_buffer + pos, l - pos, &mbs);
++ if (j <= 0) break;
++ pos += j;
++ }
+ found = 0;
+ for (i = panel->selected; !wrapped || i != panel->selected; i++) {
+ if (i >= panel->count) {
+@@ -1920,9 +2074,9 @@
+ }
+ if (panel->
+ case_sensitive
+- ? (strncmp (panel->dir.list[i].fname, panel->search_buffer, l)
++ ? (strncmp (panel->dir.list[i].fname, panel->search_buffer, pos)
+ == 0) : (g_strncasecmp (panel->dir.list[i].fname,
+- panel->search_buffer, l) == 0)) {
++ panel->search_buffer, pos) == 0)) {
+ unselect_item (panel);
+ panel->selected = i;
+ select_item (panel);
+@@ -1931,7 +2085,7 @@
+ }
+ }
+ if (!found)
+- panel->search_buffer[--l] = 0;
++ panel->search_buffer[prevpos] = 0;
+
+ paint_panel (panel);
+ }
+--- mc-4.6.2/src/slint.c
++++ mc-4.6.2/src/slint.c
+@@ -142,7 +142,9 @@
+ slang_init (void)
+ {
+ SLtt_get_terminfo ();
+-
++#if SLANG_VERSION >= 20000
++ SLutf8_enable (-1);
++#endif
+ /*
+ * If the terminal in not in terminfo but begins with a well-known
+ * string such as "linux" or "xterm" S-Lang will go on, but the
+--- mc-4.6.2/src/tty.c
++++ mc-4.6.2/src/tty.c
+@@ -134,10 +134,12 @@
+ * defined or not. Congratulations! At least, they left the API call
+ * for SLsmg_write_nchars as it has always been.
+ */
+- char ch;
+-
+- ch = c;
+- SLsmg_write_nchars(&ch, 1);
++
++ /* The above comment is a nonsense, SLsmg_write_char(c) works pretty
++ * good for me. So please don't mess with Red Hat people.
++ * Jindrich Novy (jnovy@redhat.com)
++ */
++ SLsmg_write_char(c);
+ #else
+ addch(c);
+ #endif
+--- mc-4.6.2/src/tty.h
++++ mc-4.6.2/src/tty.h
+@@ -8,6 +8,8 @@
+ of ifdefs in the other files small.
+ */
+
++#include <glib.h> /* gboolean is used here */
++
+ #ifdef HAVE_SLANG
+ # include "myslang.h"
+ #endif
+--- mc-4.6.2/src/util.c
++++ mc-4.6.2/src/util.c
+@@ -34,7 +34,11 @@
+ #include <sys/types.h>
+ #include <sys/stat.h>
+ #include <unistd.h>
++#include <iconv.h>
++#include <langinfo.h>
++#include <errno.h>
+
++#include "tty.h"
+ #include <mhl/escape.h>
+ #include <mhl/string.h>
+
+@@ -50,9 +54,39 @@
+ #include "charsets.h"
+ #endif
+
++#ifdef UTF8
++#include <wctype.h>
++#endif
++
+ static const char app_text [] = "Midnight-Commander";
+ int easy_patterns = 1;
+
++#if SLANG_VERSION >= 20000
++void SLsmg_write_nwchars(wchar_t *s, size_t n)
++{
++ if (SLsmg_is_utf8_mode()) { /* slang can handle it directly */
++ while(n-- && *s)
++ SLsmg_write_char(*s++);
++ }
++ else { /* convert wchars back to 8bit encoding */
++ mbstate_t mbs;
++ memset (&mbs, 0, sizeof (mbs));
++ while (n-- && *s) {
++ char buf[MB_LEN_MAX + 1]; /* should use 1 char, but to be sure */
++ if (*s < 0x80) {
++ SLsmg_write_char(*s++); /* ASCII */
++ }
++ else {
++ if (wcrtomb(buf, *s++, &mbs) == 1)
++ SLsmg_write_char((wchar_t)(buf[0]));
++ else
++ SLsmg_write_char('?'); /* should not happen */
++ }
++ }
++ }
++}
++#endif
++
+ extern void str_replace(char *s, char from, char to)
+ {
+ for (; *s != '\0'; s++) {
+@@ -83,9 +117,106 @@
+ return (c > 31 && c != 127 && c != 155);
+ }
+
++size_t
++mbstrlen (const char *str)
++{
++#ifdef UTF8
++ if (SLsmg_Is_Unicode) {
++ size_t width = 0;
++
++ for (; *str; str++) {
++ wchar_t c;
++ size_t len;
++
++ len = mbrtowc (&c, str, MB_CUR_MAX, NULL);
++
++ if (len == (size_t)(-1) || len == (size_t)(-2)) break;
++
++ if (len > 0) {
++ int wcsize = wcwidth(c);
++ width += wcsize > 0 ? wcsize : 0;
++ str += len-1;
++ }
++ }
++
++ return width;
++ } else
++#endif
++ return strlen (str);
++}
++
++#ifdef UTF8
++
++void
++fix_utf8(char *str)
++{
++ mbstate_t mbs;
++
++ char *p = str;
++
++ while (*p) {
++ int len;
++ memset (&mbs, 0, sizeof (mbs));
++ len = mbrlen(p, MB_CUR_MAX, &mbs);
++ if (len == -1) {
++ *p = '?';
++ p++;
++ } else if (len > 0) {
++ p += len;
++ } else {
++ p++;
++ }
++ }
++}
++#endif
++
++
++
++#ifdef UTF8
++wchar_t *
++mbstr_to_wchar (const char *str)
++{
++ int len = mbstrlen(str);
++ wchar_t *buf = g_malloc((len+1) * sizeof(wchar_t));
++ mbstate_t mbs;
++ memset (&mbs, 0, sizeof (mbs));
++ mbsrtowcs (buf, &str, len, &mbs);
++ buf[len] = 0;
++ return buf;
++}
++
++char *
++wchar_to_mbstr (const wchar_t *wstr)
++{
++ mbstate_t mbs;
++ const wchar_t *wstr2;
++ char * string;
++ int len;
++
++ memset (&mbs, 0, sizeof (mbs));
++ wstr2 = wstr;
++ len = wcsrtombs(NULL, &wstr2, 0, &mbs);
++ if (len <= 0)
++ return NULL;
++
++ string = g_malloc(len + 1);
++
++ wstr2 = wstr;
++ wcsrtombs(string, &wstr2, len, &mbs);
++ string[len] = 0;
++ return string;
++}
++#endif
++
++
++
+ int
+ is_printable (int c)
+ {
++#ifdef UTF8
++ if (SLsmg_Is_Unicode)
++ return iswprint (c);
++#endif
+ c &= 0xff;
+
+ #ifdef HAVE_CHARSET
+@@ -103,7 +234,7 @@
+ #endif /* !HAVE_CHARSET */
+ }
+
+-/* Calculates the message dimensions (lines and columns) */
++/* Calculates the message dimension in columns and lines. */
+ void
+ msglen (const char *text, int *lines, int *columns)
+ {
+@@ -116,8 +247,21 @@
+ nlines++;
+ colindex = 0;
+ } else {
++#ifndef UTF8
+ colindex++;
+ if (colindex > ncolumns)
++#else /* UTF8 */
++ size_t len;
++ wchar_t c;
++
++ len = mbrtowc (&c, text, MB_CUR_MAX, NULL);
++ if (len > 0 && len != (size_t)(-1) && len != (size_t)(-2)) {
++ int wcsize = wcwidth(c);
++ colindex += wcsize > 0 ? wcsize-1 : -1;
++ text += len-1;
++ }
++ if (++colindex > ncolumns)
++#endif /* UTF8 */
+ ncolumns = colindex;
+ }
+ }
+@@ -211,7 +355,24 @@
+ *d++ = '\\';
+ break;
+ }
++#ifndef UTF8
+ *d = *s;
++#else /* UTF8 */
++ {
++ mbstate_t mbs;
++ int len;
++ memset (&mbs, 0, sizeof (mbs));
++ len = mbrlen(s, MB_CUR_MAX, &mbs);
++ if (len > 0) {
++ while (len-- > 1)
++ *d++ = *s++;
++ *d = *s;
++ } else {
++ *d = '?';
++ }
++
++ }
++#endif /* UTF8 */
+ }
+ *d = '\0';
+ return ret;
+@@ -233,25 +394,90 @@
+ name_trunc (const char *txt, int trunc_len)
+ {
+ static char x[MC_MAXPATHLEN + MC_MAXPATHLEN];
+- int txt_len;
++ int txt_len, first, skip;
+ char *p;
++ const char *str;
+
+ if ((size_t) trunc_len > sizeof (x) - 1) {
+ trunc_len = sizeof (x) - 1;
+ }
+- txt_len = strlen (txt);
+- if (txt_len <= trunc_len) {
+- strcpy (x, txt);
+- } else {
+- int y = (trunc_len / 2) + (trunc_len % 2);
+- strncpy (x, txt, y);
+- strncpy (x + y, txt + txt_len - (trunc_len / 2), trunc_len / 2);
+- x[y] = '~';
+- }
+- x[trunc_len] = 0;
+- for (p = x; *p; p++)
+- if (!is_printable (*p))
+- *p = '?';
++ txt_len = mbstrlen (txt);
++ first = 0;
++ skip = 0;
++ if (txt_len > trunc_len) {
++ first = trunc_len / 2;
++ skip = txt_len - trunc_len + 1;
++ }
++
++#ifdef UTF8
++ if (SLsmg_Is_Unicode) {
++ mbstate_t s;
++ int mbmax;
++
++ str = txt;
++ memset (&s, 0, sizeof (s));
++ mbmax = MB_CUR_MAX;
++ p = x;
++ while (p < x + sizeof (x) - 1 && trunc_len) {
++ wchar_t wc;
++ int len;
++
++ len = mbrtowc (&wc, str, mbmax, &s);
++ if (!len)
++ break;
++ if (len < 0) {
++ memset (&s, 0, sizeof (s));
++ *p = '?';
++ len = 1;
++ str++;
++ } else if (!is_printable (wc)) {
++ *p = '?';
++ str += len;
++ len = 1;
++ } else if (p >= x + sizeof (x) - len)
++ break;
++ else {
++ memcpy (p, str, len);
++ str += len;
++ }
++ if (first) {
++ --trunc_len;
++ --first;
++ p += len;
++ if (!first && p < x + sizeof (x) - 1 && trunc_len) {
++ *p++ = '~';
++ --trunc_len;
++ }
++ } else if (skip)
++ --skip;
++ else {
++ --trunc_len;
++ p += len;
++ }
++ }
++ } else
++#endif
++ {
++ str = txt;
++ p = x;
++ while (p < x + sizeof (x) - 1) {
++ if (*str == '\0')
++ break;
++ else if (!is_printable (*str))
++ *p++ = '?';
++ else
++ *p++ = *str;
++ ++str;
++ if (first) {
++ --first;
++ if (!first) {
++ *p++ = '~';
++ str += skip;
++ }
++ }
++ }
++ }
++ *p = '\0';
+ return x;
+ }
+
+@@ -683,11 +909,61 @@
+ }
+
+ char *
++utf8_to_local(char *str)
++{
++ iconv_t cd;
++ size_t buflen = strlen(str);
++ char *output;
++ int retry = 1;
++
++ cd = iconv_open (nl_langinfo(CODESET), "UTF-8");
++ if (cd == (iconv_t) -1) {
++ return g_strdup(str);
++ }
++
++ output = g_malloc(buflen + 1);
++
++ while (retry)
++ {
++ char *wrptr = output;
++ char *inptr = str;
++ size_t insize = buflen;
++ size_t avail = buflen;
++ size_t nconv;
++
++ nconv = iconv (cd, &inptr, &insize, &wrptr, &avail);
++ if (nconv == (size_t) -1)
++ {
++ if (errno == E2BIG)
++ {
++ buflen *= 2;
++ g_free(output);
++ output = g_malloc(buflen + 1);
++ }
++ else
++ {
++ g_free(output);
++ return g_strdup(str);
++ }
++ }
++ else {
++ retry = 0;
++ *wrptr = 0;
++ }
++ }
++
++ iconv_close (cd);
++
++ return output;
++}
++
++char *
+ load_mc_home_file (const char *filename, char **allocated_filename)
+ {
+ char *hintfile_base, *hintfile;
+ char *lang;
+ char *data;
++ char *conv_data;
+
+ hintfile_base = mhl_str_dir_plus_file (mc_home, filename);
+ lang = guess_message_value ();
+@@ -720,7 +996,10 @@
+ else
+ g_free (hintfile);
+
+- return data;
++ conv_data = utf8_to_local(data);
++ g_free(data);
++
++ return conv_data;
+ }
+
+ /* Check strftime() results. Some systems (i.e. Solaris) have different
+@@ -736,10 +1015,12 @@
+ // huh, localtime() doesnt seem to work ... falling back to "(invalid)"
+ length = strlen(INVALID_TIME_TEXT);
+ } else {
+- char buf [MAX_I18NTIMELENGTH + 1];
++ char buf [4 * MAX_I18NTIMELENGTH + 1];
+ size_t a, b;
+- a = strftime (buf, sizeof(buf)-1, _("%b %e %H:%M"), lt);
+- b = strftime (buf, sizeof(buf)-1, _("%b %e %Y"), lt);
++ strftime (buf, sizeof(buf)-1, _("%b %e %H:%M"), lt);
++ a = mbstrlen (buf);
++ strftime (buf, sizeof(buf)-1, _("%b %e %Y"), lt);
++ b = mbstrlen (buf);
+ length = max (a, b);
+ }
+
+@@ -753,15 +1034,12 @@
+ const char *
+ file_date (time_t when)
+ {
+- static char timebuf [MAX_I18NTIMELENGTH + 1];
++ static char timebuf [4 * MAX_I18NTIMELENGTH + 1];
+ time_t current_time = time ((time_t) 0);
+- static size_t i18n_timelength = 0;
+ static const char *fmtyear, *fmttime;
+ const char *fmt;
+
+- if (i18n_timelength == 0){
+- i18n_timelength = i18n_checktimelength() + 1;
+-
++ if (fmtyear == NULL) {
+ /* strftime() format string for old dates */
+ fmtyear = _("%b %e %Y");
+ /* strftime() format string for recent dates */
+@@ -781,7 +1059,7 @@
+ else
+ fmt = fmttime;
+
+- FMT_LOCALTIME(timebuf, i18n_timelength, fmt, when);
++ FMT_LOCALTIME(timebuf, sizeof (timebuf) - 1, fmt, when);
+
+ return timebuf;
+ }
+@@ -912,10 +1190,27 @@
+ r++;
+ continue;
+ }
+-
++#ifndef UTF8
+ if (is_printable(*r))
+ *w++ = *r;
+ ++r;
++#else /* UTF8 */
++ {
++ mbstate_t mbs;
++ int len;
++ memset (&mbs, 0, sizeof (mbs));
++ len = mbrlen(r, MB_CUR_MAX, &mbs);
++
++ if (len > 0 && (unsigned char)*r >= ' ')
++ while (len--)
++ *w++ = *r++;
++ else {
++ if (len == -1)
++ *w++ = '?';
++ r++;
++ }
++ }
++#endif /* UTF8 */
+ }
+ *w = 0;
+ return s;
+--- mc-4.6.2/src/util.h
++++ mc-4.6.2/src/util.h
+@@ -102,6 +102,13 @@
+ char *get_group (int);
+ char *get_owner (int);
+
++void fix_utf8(char *str);
++size_t mbstrlen (const char *);
++wchar_t *mbstr_to_wchar (const char *);
++char *wchar_to_mbstr (const wchar_t *);
++char *utf8_to_local(char *str);
++
++
+ #define MAX_I18NTIMELENGTH 14
+ #define MIN_I18NTIMELENGTH 10
+ #define STD_I18NTIMELENGTH 12
+--- mc-4.6.2/src/view.c
++++ mc-4.6.2/src/view.c
+@@ -44,6 +44,10 @@
+ #include <sys/stat.h>
+ #include <unistd.h>
+
++#ifdef UTF8
++#include <wctype.h>
++#endif /* UTF8 */
++
+ #include "global.h"
+ #include "tty.h"
+ #include "cmd.h" /* For view_other_cmd */
+@@ -1643,7 +1647,7 @@
+ hline (' ', width);
+
+ file_label = _("File: %s");
+- file_label_width = strlen (file_label) - 2;
++ file_label_width = mbstrlen (file_label) - 2;
+ file_name = view->filename ? view->filename
+ : view->command ? view->command
+ : "";
+@@ -1911,6 +1915,12 @@
+ offset_type from;
+ int c;
+ struct hexedit_change_node *curr = view->change_list;
++#ifdef UTF8
++ mbstate_t mbs;
++ char mbbuf[MB_LEN_MAX];
++ int mblen;
++ wchar_t wc;
++#endif /* UTF8 */
+
+ view_display_clean (view);
+ view_display_ruler (view);
+@@ -1923,8 +1933,37 @@
+
+ tty_setcolor (NORMAL_COLOR);
+ for (row = 0, col = 0; row < height && (c = get_byte (view, from)) != -1; from++) {
+-
++#ifndef UTF8
+ if (view->text_nroff_mode && c == '\b') {
++#else /* UTF8 */
++ mblen = 1;
++ mbbuf[0] = convert_to_display_c (c);
++
++ while (mblen < MB_LEN_MAX) {
++ int res;
++ memset (&mbs, 0, sizeof (mbs));
++ res = mbrtowc (&wc, mbbuf, mblen, &mbs);
++ if (res <= 0 && res != -2) {
++ wc = '.';
++ mblen = 1;
++ break;
++ }
++ if (res == mblen)
++ break;
++
++ mbbuf[mblen] = convert_to_display_c (get_byte (view, from + mblen));
++ mblen++;
++ }
++
++ if (mblen == MB_LEN_MAX) {
++ wc = '.';
++ mblen = 1;
++ }
++
++ from += mblen - 1;
++
++ if (view->text_nroff_mode && wc == '\b') {
++#endif /* UTF8 */
+ int c_prev;
+ int c_next;
+
+@@ -1989,10 +2028,17 @@
+ if (col >= view->dpy_text_column
+ && col - view->dpy_text_column < width) {
+ widget_move (view, top + row, left + (col - view->dpy_text_column));
++#ifndef UTF8
+ c = convert_to_display_c (c);
+ if (!is_printable (c))
+ c = '.';
+ tty_print_char (c);
++#else
++ wc = convert_to_display_c (wc);
++ if (!iswprint (wc))
++ wc = '.';
++ tty_print_char (wc);
++#endif
+ }
+ col++;
+ tty_setcolor (NORMAL_COLOR);
+--- mc-4.6.2/src/widget.c
++++ mc-4.6.2/src/widget.c
+@@ -38,6 +38,9 @@
+
+ #include "global.h"
+ #include "tty.h"
++#ifdef UTF8
++#include <wctype.h>
++#endif /* UTF8 */
+ #include "color.h"
+ #include "mouse.h"
+ #include "dialog.h"
+@@ -183,6 +186,11 @@
+ if (b->hotpos >= 0) {
+ widget_selectcolor (w, b->selected, TRUE);
+ widget_move (w, 0, b->hotpos + off);
++#ifdef UTF8
++ if (SLsmg_Is_Unicode)
++ SLsmg_write_nwchars (&b->hotwc, 1);
++ else
++#endif
+ addch ((unsigned char) b->text[b->hotpos]);
+ }
+ return MSG_HANDLED;
+@@ -216,7 +224,7 @@
+ static int
+ button_len (const char *text, unsigned int flags)
+ {
+- int ret = strlen (text);
++ int ret = mbstrlen (text);
+ switch (flags){
+ case DEFPUSH_BUTTON:
+ ret += 6;
+@@ -239,14 +247,36 @@
+ * the button text is g_malloc()ed, we can safely change and shorten it.
+ */
+ static void
+-button_scan_hotkey (WButton *b)
++scan_hotkey (char *text, int *hotposp, int *hotkeyp, wchar_t *hotwcp)
+ {
+- char *cp = strchr (b->text, '&');
++ char *cp = strchr (text, '&');
+
+ if (cp != NULL && cp[1] != '\0') {
+- g_strlcpy (cp, cp + 1, strlen (cp));
+- b->hotkey = tolower ((unsigned char) *cp);
+- b->hotpos = cp - b->text;
++#ifdef UTF8
++ if (SLsmg_Is_Unicode) {
++ mbstate_t s;
++ int len;
++
++ *cp = '\0';
++ memset (&s, 0, sizeof (s));
++ len = mbrtowc (hotwcp, cp + 1, MB_CUR_MAX, &s);
++ if (len > 0) {
++ *hotposp = mbstrlen (text);
++ if (*hotposp < 0) {
++ *hotposp = -1;
++ } else {
++ /* FIXME */
++ *hotkeyp = tolower (*hotwcp);
++ }
++ }
++ } else
++#endif
++ {
++ *hotkeyp = tolower (cp[1]);
++ *hotposp = cp - text;
++ }
++
++ memmove (cp, cp + 1, strlen (cp + 1) + 1);
+ }
+ }
+
+@@ -267,8 +297,9 @@
+ widget_want_hotkey (b->widget, 1);
+ b->hotkey = 0;
+ b->hotpos = -1;
++ b->hotwc = L'\0';
+
+- button_scan_hotkey(b);
++ scan_hotkey(b->text, &b->hotpos, &b->hotkey, &b->hotwc);
+ return b;
+ }
+
+@@ -281,14 +312,13 @@
+ void
+ button_set_text (WButton *b, const char *text)
+ {
+- g_free (b->text);
++ g_free (b->text);
+ b->text = g_strdup (text);
+ b->widget.cols = button_len (text, b->flags);
+- button_scan_hotkey(b);
++ scan_hotkey(b->text, &b->hotpos, &b->hotkey, &b->hotwc);
+ dlg_redraw (b->widget.parent);
+ }
+
+-
+ /* Radio button widget */
+ static int radio_event (Gpm_Event *event, void *);
+
+@@ -363,14 +393,35 @@
+ widget_move (&r->widget, i, 0);
+
+ tty_printf ("(%c) ", (r->sel == i) ? '*' : ' ');
+- for (cp = r->texts[i]; *cp; cp++) {
+- if (*cp == '&') {
+- widget_selectcolor (w, focused, TRUE);
++ cp = strchr (r->texts[i], '&');
++ if (cp != NULL) {
++#ifdef UTF8
++ mbstate_t s;
++ wchar_t wc;
++ int len;
++#endif
++ tty_printf ("%.*s", (int) ((char *) cp - r->texts[i]),
++ r->texts[i]);
++ widget_selectcolor (w, focused, TRUE);
++#ifdef UTF8
++ if (SLsmg_Is_Unicode) {
++ memset (&s, 0, sizeof (s));
++ len = mbrtowc (&wc, cp + 1, MB_CUR_MAX, &s);
++ ++cp;
++ if (len > 0) {
++ tty_printf ("%.*s", len, cp);
++ cp += len;
++ }
++ } else
++#endif
++ {
+ addch (*++cp);
+- widget_selectcolor (w, focused, FALSE);
+- } else
+- addch (*cp);
+- }
++ ++cp;
++ }
++ widget_selectcolor (w, focused, FALSE);
++ } else
++ cp = r->texts[i];
++ addstr ((char *) cp);
+ }
+ return MSG_HANDLED;
+
+@@ -409,7 +460,7 @@
+ /* Compute the longest string */
+ max = 0;
+ for (i = 0; i < count; i++){
+- m = strlen (texts [i]);
++ m = mbstrlen (texts [i]);
+ if (m > max)
+ max = m;
+ }
+@@ -469,6 +520,11 @@
+ if (c->hotpos >= 0) {
+ widget_selectcolor (w, msg == WIDGET_FOCUS, TRUE);
+ widget_move (&c->widget, 0, +c->hotpos + 4);
++#ifdef UTF8
++ if (SLsmg_Is_Unicode)
++ SLsmg_write_nwchars (&c->hotwc, 1);
++ else
++#endif
+ addch ((unsigned char) c->text[c->hotpos]);
+ }
+ return MSG_HANDLED;
+@@ -506,35 +562,20 @@
+ check_new (int y, int x, int state, const char *text)
+ {
+ WCheck *c = g_new (WCheck, 1);
+- const char *s;
+- char *t;
+-
+- init_widget (&c->widget, y, x, 1, strlen (text),
++
++ init_widget (&c->widget, y, x, 1, mbstrlen (text),
+ check_callback, check_event);
+ c->state = state ? C_BOOL : 0;
+ c->text = g_strdup (text);
+ c->hotkey = 0;
+ c->hotpos = -1;
++ c->hotwc = L'\0';
+ widget_want_hotkey (c->widget, 1);
+
+- /* Scan for the hotkey */
+- for (s = text, t = c->text; *s; s++, t++){
+- if (*s != '&'){
+- *t = *s;
+- continue;
+- }
+- s++;
+- if (*s){
+- c->hotkey = tolower ((unsigned char) *s);
+- c->hotpos = t - c->text;
+- }
+- *t = *s;
+- }
+- *t = 0;
++ scan_hotkey (c->text, &c->hotpos, &c->hotkey, &c->hotwc);
+ return c;
+ }
+
+-
+ /* Label widget */
+
+ static cb_ret_t
+@@ -573,7 +614,7 @@
+ }
+ widget_move (&l->widget, y, 0);
+ tty_printf ("%s", p);
+- xlen = l->widget.cols - strlen (p);
++ xlen = l->widget.cols - mbstrlen (p);
+ if (xlen > 0)
+ tty_printf ("%*s", xlen, " ");
+ if (!q)
+@@ -607,7 +648,7 @@
+ if (text){
+ label->text = g_strdup (text);
+ if (label->auto_adjust_cols) {
+- newcols = strlen (text);
++ newcols = mbstrlen (text);
+ if (newcols > label->widget.cols)
+ label->widget.cols = newcols;
+ }
+@@ -631,7 +672,7 @@
+ if (!text || strchr(text, '\n'))
+ width = 1;
+ else
+- width = strlen (text);
++ width = mbstrlen (text);
+
+ l = g_new (WLabel, 1);
+ init_widget (&l->widget, y, x, 1, width, label_callback, NULL);
+@@ -779,13 +820,69 @@
+ /* Pointer to killed data */
+ static char *kill_buffer = 0;
+
++#ifdef UTF8
++static int
++charpos(WInput *in, int idx)
++{
++ int i, pos, l, len;
++ mbstate_t mbs;
++ memset (&mbs, 0, sizeof (mbs));
++ i = 0;
++ pos = 0;
++ len = strlen(in->buffer);
++
++ while (in->buffer[pos]) {
++ if (i == idx)
++ return pos;
++ l = mbrlen(in->buffer + pos, len - pos, &mbs);
++ if (l <= 0)
++ return pos;
++ pos+=l;
++ i++;
++ };
++ return pos;
++}
++
++static int
++charcolumn(WInput *in, int idx)
++{
++ int i, pos, l, width, len;
++ mbstate_t mbs;
++ memset (&mbs, 0, sizeof (mbs));
++ i = 0;
++ pos = 0; width = 0;
++ len = strlen(in->buffer);
++
++ while (in->buffer[pos]) {
++ wchar_t wc;
++ if (i == idx)
++ return width;
++ l = mbrtowc(&wc, in->buffer + pos, len - pos, &mbs);
++ if (l <= 0)
++ return width;
++ pos += l; width += wcwidth(wc);
++ i++;
++ };
++ return width;
++}
++#else
++#define charpos(in, idx) (idx)
++#define charcolumn(in, idx) (idx)
++#endif /* UTF8 */
++
+ void
+ update_input (WInput *in, int clear_first)
+ {
+ int has_history = 0;
+ int i, j;
+- unsigned char c;
+- int buf_len = strlen (in->buffer);
++ int buf_len = mbstrlen (in->buffer);
++#ifndef UTF8
++ unsigned char c;
++#else /* UTF8 */
++ wchar_t c;
++ mbstate_t mbs;
++ memset (&mbs, 0, sizeof (mbs));
++#endif /* UTF8 */
+
+ if (should_show_history_button (in))
+ has_history = HISTORY_BUTTON_WIDTH;
+@@ -795,7 +892,7 @@
+
+ /* Make the point visible */
+ if ((in->point < in->first_shown) ||
+- (in->point >= in->first_shown+in->field_len - has_history)){
++ (charcolumn(in, in->point) >= charcolumn(in, in->first_shown) + in->field_len - has_history)){
+ in->first_shown = in->point - (in->field_len / 3);
+ if (in->first_shown < 0)
+ in->first_shown = 0;
+@@ -815,14 +912,29 @@
+ addch (' ');
+ widget_move (&in->widget, 0, 0);
+
++#ifndef UTF8
+ for (i = 0, j = in->first_shown; i < in->field_len - has_history && in->buffer [j]; i++){
+ c = in->buffer [j++];
+ c = is_printable (c) ? c : '.';
+- if (in->is_password)
++#else /* UTF8 */
++ for (i = 0, j = in->first_shown; (i < in->field_len - has_history) && (j < buf_len); i++,j++){
++ char * chp = in->buffer + charpos(in,j);
++ size_t res = mbrtowc(&c, chp, strlen(chp), &mbs);
++ c = (res && iswprint (c)) ? 0 : '.';
++#endif /* UTF8 */
++ if (in->is_password)
+ c = '*';
++#ifndef UTF8
+ addch (c);
++#else /* UTF8 */
++ if (c) {
++ addch (c);
++ }
++ else
++ SLsmg_write_nchars (chp, res);
++#endif /* UTF8 */
+ }
+- widget_move (&in->widget, 0, in->point - in->first_shown);
++ widget_move (&in->widget, 0, charcolumn(in, in->point) - charcolumn(in, in->first_shown));
+
+ if (clear_first)
+ in->first = 0;
+@@ -975,7 +1087,7 @@
+ show_hist (GList *history, int widget_x, int widget_y)
+ {
+ GList *hi, *z;
+- size_t maxlen = strlen (i18n_htitle ()), i, count = 0;
++ size_t maxlen = mbstrlen (i18n_htitle ()), i, count = 0;
+ int x, y, w, h;
+ char *q, *r = 0;
+ Dlg_head *query_dlg;
+@@ -988,7 +1100,7 @@
+ z = g_list_first (history);
+ hi = z;
+ while (hi) {
+- if ((i = strlen ((char *) hi->data)) > maxlen)
++ if ((i = mbstrlen ((char *) hi->data)) > maxlen)
+ maxlen = i;
+ count++;
+ hi = g_list_next (hi);
+@@ -1158,35 +1270,83 @@
+ in->need_push = 1;
+ in->buffer [0] = 0;
+ in->point = 0;
++ in->charpoint = 0;
+ in->mark = 0;
+ free_completions (in);
+ update_input (in, 0);
+ }
+
++static void
++move_buffer_backward (WInput *in, int point)
++{
++ int i, pos, len;
++ int str_len = mbstrlen (in->buffer);
++ if (point >= str_len) return;
++
++ pos = charpos(in,point);
++ len = charpos(in,point + 1) - pos;
++
++ for (i = pos; in->buffer [i + len - 1]; i++)
++ in->buffer [i] = in->buffer [i + len];
++}
++
+ static cb_ret_t
+ insert_char (WInput *in, int c_code)
+ {
+ size_t i;
++#ifdef UTF8
++ mbstate_t mbs;
++ int res;
++
++ memset (&mbs, 0, sizeof (mbs));
++#else
++ in->charpoint = 0;
++#endif /* UTF8 */
+
+ if (c_code == -1)
+ return MSG_NOT_HANDLED;
+
++#ifdef UTF8
++ if (in->charpoint >= MB_CUR_MAX) return 1;
++
++ in->charbuf[in->charpoint++] = c_code;
++
++ res = mbrlen((char *)in->charbuf, in->charpoint, &mbs);
++ if (res < 0) {
++ if (res != -2) in->charpoint = 0; /* broken multibyte char, skip */
++ return 1;
++ }
++
++#endif /* UTF8 */
+ in->need_push = 1;
+- if (strlen (in->buffer)+1 == (size_t) in->current_max_len){
++ if (strlen (in->buffer) + 1 + in->charpoint >= (size_t) in->current_max_len){
+ /* Expand the buffer */
+- char *narea = g_realloc (in->buffer, in->current_max_len + in->field_len);
++ char *narea = g_realloc (in->buffer, in->current_max_len + in->field_len + in->charpoint);
+ if (narea){
+ in->buffer = narea;
+- in->current_max_len += in->field_len;
++ in->current_max_len += in->field_len + in->charpoint;
+ }
+ }
++#ifndef UTF8
+ if (strlen (in->buffer)+1 < (size_t) in->current_max_len){
+ size_t l = strlen (&in->buffer [in->point]);
+ for (i = l+1; i > 0; i--)
+ in->buffer [in->point+i] = in->buffer [in->point+i-1];
+ in->buffer [in->point] = c_code;
++#else /* UTF8 */
++ if (strlen (in->buffer) + in->charpoint < in->current_max_len){
++ size_t ins_point = charpos(in,in->point); /* bytes from begin */
++ /* move chars */
++ size_t rest_bytes = strlen (in->buffer + ins_point);
++
++ for (i = rest_bytes + 1; i > 0; i--)
++ in->buffer [ins_point + i + in->charpoint - 1] = in->buffer [ins_point + i - 1];
++
++ memcpy(in->buffer + ins_point, in->charbuf, in->charpoint);
++#endif /* UTF8 */
+ in->point++;
+ }
++ in->charpoint = 0;
+ return MSG_HANDLED;
+ }
+
+@@ -1194,12 +1354,14 @@
+ beginning_of_line (WInput *in)
+ {
+ in->point = 0;
++ in->charpoint = 0;
+ }
+
+ static void
+ end_of_line (WInput *in)
+ {
+- in->point = strlen (in->buffer);
++ in->point = mbstrlen (in->buffer);
++ in->charpoint = 0;
+ }
+
+ static void
+@@ -1207,18 +1369,21 @@
+ {
+ if (in->point)
+ in->point--;
++ in->charpoint = 0;
+ }
+
+ static void
+ forward_char (WInput *in)
+ {
+- if (in->buffer [in->point])
++ if (in->buffer [charpos(in,in->point)])
+ in->point++;
++ in->charpoint = 0;
+ }
+
+ static void
+ forward_word (WInput * in)
+ {
++#ifndef UTF8
+ char *p = in->buffer + in->point;
+
+ while (*p
+@@ -1228,11 +1393,39 @@
+ while (*p && isalnum ((unsigned char) *p))
+ p++;
+ in->point = p - in->buffer;
++#else /* UTF8 */
++ mbstate_t mbs;
++ int len = mbstrlen (in->buffer);
++ memset (&mbs, 0, sizeof (mbs));
++
++ while (in->point < len) {
++ wchar_t c;
++ char *p = in->buffer + charpos(in,in->point);
++ size_t res = mbrtowc(&c, p, strlen(p), &mbs);
++ if (res <= 0 || !(iswspace (c) || iswpunct (c)))
++ break;
++ in->point++;
++ }
++
++ memset (&mbs, 0, sizeof (mbs));
++
++ while (in->point < len) {
++ wchar_t c;
++ char *p = in->buffer + charpos(in,in->point);
++ size_t res = mbrtowc(&c, p, strlen(p), &mbs);
++ if (res <= 0 || !iswalnum (c))
++ break;
++ in->point++;
++ }
++
++ in->charpoint = 0;
++#endif /* UTF8 */
+ }
+
+ static void
+ backward_word (WInput *in)
+ {
++#ifndef UTF8
+ char *p = in->buffer + in->point;
+
+ while (p - 1 > in->buffer - 1 && (isspace ((unsigned char) *(p - 1))
+@@ -1242,6 +1435,32 @@
+ while (p - 1 > in->buffer - 1 && isalnum ((unsigned char) *(p - 1)))
+ p--;
+ in->point = p - in->buffer;
++#else /* UTF8 */
++ mbstate_t mbs;
++
++ memset (&mbs, 0, sizeof (mbs));
++ while (in->point > 0) {
++ wchar_t c;
++ char *p = in->buffer + charpos(in,in->point);
++ size_t res = mbrtowc(&c, p, strlen(p), &mbs);
++ if (*p && (res <= 0 || !(iswspace (c) || iswpunct (c))))
++ break;
++ in->point--;
++ }
++
++ memset (&mbs, 0, sizeof (mbs));
++
++ while (in->point > 0) {
++ wchar_t c;
++ char *p = in->buffer + charpos(in,in->point);
++ size_t res = mbrtowc(&c, p, strlen(p), &mbs);
++ if (*p && (res <= 0 || !iswalnum (c)))
++ break;
++ in->point--;
++ }
++
++ in->charpoint = 0;
++#endif /* UTF8 */
+ }
+
+ static void
+@@ -1274,8 +1493,9 @@
+
+ if (!in->point)
+ return;
+- for (i = in->point; in->buffer [i-1]; i++)
+- in->buffer [i-1] = in->buffer [i];
++
++ move_buffer_backward(in, in->point - 1);
++ in->charpoint = 0;
+ in->need_push = 1;
+ in->point--;
+ }
+@@ -1283,10 +1503,8 @@
+ static void
+ delete_char (WInput *in)
+ {
+- int i;
+-
+- for (i = in->point; in->buffer [i]; i++)
+- in->buffer [i] = in->buffer [i+1];
++ move_buffer_backward(in, in->point);
++ in->charpoint = 0;
+ in->need_push = 1;
+ }
+
+@@ -1301,6 +1519,9 @@
+
+ g_free (kill_buffer);
+
++ first=charpos(in,first);
++ last=charpos(in,last);
++
+ kill_buffer = g_strndup(in->buffer+first,last-first);
+ }
+
+@@ -1309,11 +1530,13 @@
+ {
+ int first = min (x_first, x_last);
+ int last = max (x_first, x_last);
+- size_t len = strlen (&in->buffer [last]) + 1;
++ size_t len;
+
+ in->point = first;
+ in->mark = first;
+- memmove (&in->buffer [first], &in->buffer [last], len);
++ len = strlen (&in->buffer [charpos(in,last)]) + 1;
++ memmove (&in->buffer [charpos(in,first)], &in->buffer [charpos(in,last)], len);
++ in->charpoint = 0;
+ in->need_push = 1;
+ }
+
+@@ -1330,6 +1553,8 @@
+ copy_region (in, old_point, new_point);
+ delete_region (in, old_point, new_point);
+ in->need_push = 1;
++ in->charpoint = 0;
++ in->charpoint = 0;
+ }
+
+ static void
+@@ -1373,16 +1598,20 @@
+
+ if (!kill_buffer)
+ return;
++ in->charpoint = 0;
+ for (p = kill_buffer; *p; p++)
+ insert_char (in, *p);
++ in->charpoint = 0;
+ }
+
+ static void
+ kill_line (WInput *in)
+ {
++ int chp = charpos(in,in->point);
+ g_free (kill_buffer);
+- kill_buffer = g_strdup (&in->buffer [in->point]);
+- in->buffer [in->point] = 0;
++ kill_buffer = g_strdup (&in->buffer [chp]);
++ in->buffer [chp] = 0;
++ in->charpoint = 0;
+ }
+
+ void
+@@ -1392,9 +1621,10 @@
+ g_free (in->buffer);
+ in->buffer = g_strdup (text); /* was in->buffer->text */
+ in->current_max_len = strlen (in->buffer) + 1;
+- in->point = strlen (in->buffer);
++ in->point = mbstrlen (in->buffer);
+ in->mark = 0;
+ in->need_push = 1;
++ in->charpoint = 0;
+ }
+
+ static void
+@@ -1521,6 +1751,7 @@
+ *in->buffer = 0;
+ in->point = 0;
+ in->first = 0;
++ in->charpoint = 0;
+ }
+
+ cb_ret_t
+@@ -1549,7 +1780,11 @@
+ }
+ }
+ if (!input_map [i].fn){
++#ifndef UTF8
+ if (c_code > 255 || !is_printable (c_code))
++#else /* UTF8 */
++ if (c_code > 255)
++#endif /* UTF8 */
+ return MSG_NOT_HANDLED;
+ if (in->first){
+ port_region_marked_for_delete (in);
+@@ -1582,6 +1817,9 @@
+ if (pos != in->point)
+ free_completions (in);
+ in->point = pos;
++#ifdef UTF8
++ in->charpoint = 0;
++#endif /* UTF8 */
+ update_input (in, 1);
+ }
+
+@@ -1622,7 +1860,7 @@
+ return MSG_HANDLED;
+
+ case WIDGET_CURSOR:
+- widget_move (&in->widget, 0, in->point - in->first_shown);
++ widget_move (&in->widget, 0, charcolumn(in, in->point) - charcolumn(in, in->first_shown));
+ return MSG_HANDLED;
+
+ case WIDGET_DESTROY:
+@@ -1646,7 +1884,7 @@
+ && should_show_history_button (in)) {
+ do_show_hist (in);
+ } else {
+- in->point = strlen (in->buffer);
++ in->point = mbstrlen (in->buffer);
+ if (event->x - in->first_shown - 1 < in->point)
+ in->point = event->x - in->first_shown - 1;
+ if (in->point < 0)
+@@ -1701,7 +1939,8 @@
+ in->is_password = 0;
+
+ strcpy (in->buffer, def_text);
+- in->point = strlen (in->buffer);
++ in->point = mbstrlen (in->buffer);
++ in->charpoint = 0;
+ return in;
+ }
+
+--- mc-4.6.2/src/widget.h
++++ mc-4.6.2/src/widget.h
+@@ -39,6 +39,7 @@
+ char *text; /* text of button */
+ int hotkey; /* hot KEY */
+ int hotpos; /* offset hot KEY char in text */
++ wchar_t hotwc;
+ bcback callback; /* Callback function */
+ } WButton;
+
+@@ -59,6 +60,7 @@
+ char *text; /* text of check button */
+ int hotkey; /* hot KEY */
+ int hotpos; /* offset hot KEY char in text */
++ wchar_t hotwc;
+ } WCheck;
+
+ typedef struct WGauge {
+@@ -74,16 +76,20 @@
+
+ typedef struct {
+ Widget widget;
+- int point; /* cursor position in the input line */
+- int mark; /* The mark position */
+- int first_shown; /* Index of the first shown character */
+- int current_max_len; /* Maximum length of input line */
+- int field_len; /* Length of the editing field */
++ int point; /* cursor position in the input line (mb chars) */
++ int mark; /* The mark position (mb chars) */
++ int first_shown; /* Index of the first shown character (mb chars) */
++ int current_max_len; /* Maximum length of input line (bytes) */
++ int field_len; /* Length of the editing field (mb chars) */
+ int color; /* color used */
+ int first; /* Is first keystroke? */
+ int disable_update; /* Do we want to skip updates? */
+ int is_password; /* Is this a password input line? */
+ char *buffer; /* pointer to editing buffer */
++#ifdef UTF8
++ char charbuf[MB_LEN_MAX];
++#endif /* UTF8 */
++ int charpoint;
+ GList *history; /* The history */
+ int need_push; /* need to push the current Input on hist? */
+ char **completions; /* Possible completions array */
+--- mc-4.6.2/src/wtools.c
++++ mc-4.6.2/src/wtools.c
+@@ -49,11 +49,11 @@
+ /* Adjust sizes */
+ lines = (lines > LINES - 6) ? LINES - 6 : lines;
+
+- if (title && (cols < (len = strlen (title) + 2)))
++ if (title && (cols < (len = mbstrlen (title) + 2)))
+ cols = len;
+
+ /* no &, but 4 spaces around button for brackets and such */
+- if (cols < (len = strlen (cancel_string) + 3))
++ if (cols < (len = mbstrlen (cancel_string) + 3))
+ cols = len;
+
+ cols = cols > COLS - 6 ? COLS - 6 : cols;
+@@ -124,7 +124,7 @@
+ va_start (ap, count);
+ for (i = 0; i < count; i++) {
+ char *cp = va_arg (ap, char *);
+- win_len += strlen (cp) + 6;
++ win_len += mbstrlen (cp) + 6;
+ if (strchr (cp, '&') != NULL)
+ win_len--;
+ }
+@@ -133,7 +133,7 @@
+
+ /* count coordinates */
+ msglen (text, &lines, &cols);
+- cols = 6 + max (win_len, max ((int) strlen (header), cols));
++ cols = 6 + max (win_len, max ((int) mbstrlen (header), cols));
+ lines += 4 + (count > 0 ? 2 : 0);
+ xpos = COLS / 2 - cols / 2;
+ ypos = LINES / 3 - (lines - 3) / 2;
+@@ -148,7 +148,7 @@
+ va_start (ap, count);
+ for (i = 0; i < count; i++) {
+ cur_name = va_arg (ap, char *);
+- xpos = strlen (cur_name) + 6;
++ xpos = mbstrlen (cur_name) + 6;
+ if (strchr (cur_name, '&') != NULL)
+ xpos--;
+
+@@ -467,7 +467,7 @@
+ }
+
+ msglen (text, &lines, &cols);
+- len = max ((int) strlen (header), cols) + 4;
++ len = max ((int) mbstrlen (header), cols) + 4;
+ len = max (len, 64);
+
+ /* The special value of def_text is used to identify password boxes
+@@ -489,7 +489,7 @@
+ quick_widgets[1].text = _(quick_widgets[1].text);
+ quick_widgets[0].relative_x = len / 2 + 4;
+ quick_widgets[1].relative_x =
+- len / 2 - (strlen (quick_widgets[1].text) + 9);
++ len / 2 - (mbstrlen (quick_widgets[1].text) + 9);
+ quick_widgets[0].x_divisions = quick_widgets[1].x_divisions = len;
+ #endif /* ENABLE_NLS */
+
diff --git a/packages/mc/mc-4.6.2/mhl-stdbool.patch b/packages/mc/mc-4.6.2/mhl-stdbool.patch
new file mode 100644
index 0000000000..43ada3508f
--- /dev/null
+++ b/packages/mc/mc-4.6.2/mhl-stdbool.patch
@@ -0,0 +1,16 @@
+Index: mc-4.6.2/mhl/types.h
+===================================================================
+--- mc-4.6.2.orig/mhl/types.h 2009-02-01 19:30:21.000000000 +0000
++++ mc-4.6.2/mhl/types.h 2009-02-22 16:45:06.000000000 +0000
+@@ -7,10 +7,6 @@
+ #ifndef __MHL_TYPES_H
+ #define __MHL_TYPES_H
+
+-typedef enum
+-{
+- false = 0,
+- true = 1
+-} bool;
++#include <stdbool.h>
+
+ #endif
diff --git a/packages/mc/mc_4.6.2.bb b/packages/mc/mc_4.6.2.bb
new file mode 100644
index 0000000000..a2a5df8afe
--- /dev/null
+++ b/packages/mc/mc_4.6.2.bb
@@ -0,0 +1,60 @@
+require mc.inc
+HOMEPAGE = "http://www.midnight-commander.org/"
+
+# UTF-8 fixes copied from openSUSE Factory:
+# (2009-02-12 by nadvornik@suse.cz)
+# mc-utf8-look-and-feel.patch: debian fix for utf8
+SRC_URI = "http://www.midnight-commander.org/downloads/${P}.tar.gz \
+ file://mhl-stdbool.patch;patch=1 \
+ file://mc-utf8.patch;patch=1 \
+ file://00-70-utf8-common.patch;patch=1 \
+ file://00-73-utf8-bottom-buttons-width.patch;patch=1 \
+ file://00-75-utf8-cmdline-help.patch;patch=1 \
+ file://00-76-utf8-hotlist-highlight.patch;patch=1 \
+ file://00-77-utf8-filename-search-highlight.patch;patch=1 \
+ file://mc-utf8-nlink.patch;patch=1 \
+ file://mc-utf8-look-and-feel.patch;patch=1"
+
+EXTRA_OECONF = "--enable-charset --libexecdir=${libdir}"
+
+do_unpack_append() {
+ bb.build.exec_func('do_utf8_conversion', d)
+}
+do_utf8_conversion() {
+ pwd
+ pushd lib
+ iconv -f iso8859-1 -t utf-8 -o mc.hint.tmp mc.hint && mv mc.hint.tmp mc.hint
+ iconv -f iso8859-1 -t utf-8 -o mc.hint.es.tmp mc.hint.es && mv mc.hint.es.tmp mc.hint.es
+ iconv -f iso8859-1 -t utf-8 -o mc.hint.it.tmp mc.hint.it && mv mc.hint.it.tmp mc.hint.it
+ iconv -f iso8859-1 -t utf-8 -o mc.hint.nl.tmp mc.hint.nl && mv mc.hint.nl.tmp mc.hint.nl
+ iconv -f iso8859-2 -t utf-8 -o mc.hint.cs.tmp mc.hint.cs && mv mc.hint.cs.tmp mc.hint.cs
+ iconv -f iso8859-2 -t utf-8 -o mc.hint.hu.tmp mc.hint.hu && mv mc.hint.hu.tmp mc.hint.hu
+ iconv -f iso8859-2 -t utf-8 -o mc.hint.pl.tmp mc.hint.pl && mv mc.hint.pl.tmp mc.hint.pl
+ iconv -f koi8-r -t utf8 -o mc.hint.ru.tmp mc.hint.ru && mv mc.hint.ru.tmp mc.hint.ru
+ iconv -f koi8-u -t utf8 -o mc.hint.uk.tmp mc.hint.uk && mv mc.hint.uk.tmp mc.hint.uk
+ iconv -f big5 -t utf8 -o mc.hint.zh.tmp mc.hint.zh && mv mc.hint.zh.tmp mc.hint.zh
+ popd
+ # convert docs to utf-8
+ pushd doc
+ pushd es
+ iconv -f iso8859-1 -t utf-8 -o mc.1.in.tmp mc.1.in && mv mc.1.in.tmp mc.1.in
+ iconv -f iso8859-1 -t utf-8 -o xnc.hlp.tmp xnc.hlp && mv xnc.hlp.tmp xnc.hlp
+ popd
+ pushd hu
+ iconv -f iso8859-2 -t utf-8 -o mc.1.in.tmp mc.1.in && mv mc.1.in.tmp mc.1.in
+ iconv -f iso8859-2 -t utf-8 -o xnc.hlp.tmp xnc.hlp && mv xnc.hlp.tmp xnc.hlp
+ popd
+ pushd it
+ iconv -f iso8859-1 -t utf-8 -o mc.1.in.tmp mc.1.in && mv mc.1.in.tmp mc.1.in
+ iconv -f iso8859-1 -t utf-8 -o xnc.hlp.tmp xnc.hlp && mv xnc.hlp.tmp xnc.hlp
+ popd
+ pushd pl
+ iconv -f iso8859-2 -t utf-8 -o mc.1.in.tmp mc.1.in && mv mc.1.in.tmp mc.1.in
+ iconv -f iso8859-2 -t utf-8 -o xnc.hlp.tmp xnc.hlp && mv xnc.hlp.tmp xnc.hlp
+ popd
+ pushd ru
+ iconv -f koi8-r -t utf-8 -o mc.1.in.tmp mc.1.in && mv mc.1.in.tmp mc.1.in
+ iconv -f koi8-r -t utf-8 -o xnc.hlp.tmp xnc.hlp && mv xnc.hlp.tmp xnc.hlp
+ popd
+ popd
+}
diff --git a/packages/meta/run-postinsts/run-postinsts b/packages/meta/run-postinsts/run-postinsts
new file mode 100755
index 0000000000..f632d1c7d3
--- /dev/null
+++ b/packages/meta/run-postinsts/run-postinsts
@@ -0,0 +1,36 @@
+#!/bin/sh
+#
+# Copyright 2007 Openedhand Ltd.
+#
+# Author: Richard Purdie <rpurdie@openedhand.com>
+#
+
+PKGSYSTEM=/var/dpkg
+
+if [ ! -e $PKGSYSTEM/status ]; then
+ if [ -e /usr/lib/opkg/status ]; then
+ PKGSYSTEM=/usr/lib/opkg
+ else
+ echo "No package system found"
+ exit 1
+ fi
+fi
+
+STAMP=$PKGSYSTEM/postinsts-done
+STATFILE=$PKGSYSTEM/status
+STATFILE2=$PKGSYSTEM/status2
+
+if [ -e $STAMP ]; then
+ exit 0
+fi
+
+awk -f /usr/share/run-postinsts/run-postinsts.awk $STATFILE > $STATFILE2
+if [ $? = 0 ]; then
+ mv $STATFILE2 $STATFILE
+ touch $STAMP
+ exit 0
+else
+ rm -f $STATFILE2
+ rm -f $STAMP
+ exit 1
+fi
diff --git a/packages/meta/run-postinsts/run-postinsts.awk b/packages/meta/run-postinsts/run-postinsts.awk
new file mode 100644
index 0000000000..09a1400cf4
--- /dev/null
+++ b/packages/meta/run-postinsts/run-postinsts.awk
@@ -0,0 +1,30 @@
+#
+# Copyright 2007 Openedhand Ltd.
+#
+# Author: Richard Purdie <rpurdie@openedhand.com>
+#
+# Rather hacky proof of concept
+#
+
+BEGIN {
+ rc=system("test -d /usr/dpkg/info/")
+ if (rc==0)
+ pkgdir="/var/dpkg/info"
+ else
+ pkgdir="/usr/lib/opkg/info"
+ package=""
+}
+/Package:.*/ {
+ package = substr($0, 10)
+}
+/Status:.*unpacked.*/ {
+ print "Configuring: " package > "/dev/stderr"
+ ret = system(pkgdir "/" package ".postinst 1>&2")
+ if (ret == 0)
+ $0 = gensub("unpacked", "installed", 1)
+ else
+ print "Postinstall failed for " package > "/dev/stderr"
+}
+{
+ print $0
+}
diff --git a/packages/meta/run-postinsts_1.0.bb b/packages/meta/run-postinsts_1.0.bb
new file mode 100644
index 0000000000..79333dc7fe
--- /dev/null
+++ b/packages/meta/run-postinsts_1.0.bb
@@ -0,0 +1,30 @@
+DESCRIPTION = "Run postinstall scripts on device using awk"
+SECTION = "devel"
+PR = "r6"
+
+SRC_URI = "file://run-postinsts file://run-postinsts.awk"
+
+INITSCRIPT_NAME = "run-postinsts"
+INITSCRIPT_PARAMS = "start 98 S ."
+
+inherit update-rc.d
+
+do_configure() {
+ :
+}
+
+do_compile () {
+ :
+}
+
+do_install() {
+ install -d ${D}${sysconfdir}/init.d/
+ install -m 0755 ${WORKDIR}/run-postinsts ${D}${sysconfdir}/init.d/
+
+ install -d ${D}${datadir}/${PN}/
+ install -m 0644 ${WORKDIR}/run-postinsts.awk ${D}${datadir}/${PN}/
+}
+
+do_stage () {
+ :
+}
diff --git a/packages/motion/motion-3.2.11/ffmpeg-0.4.9.15594svn-20081010.diff b/packages/motion/motion-3.2.11/ffmpeg-0.4.9.15594svn-20081010.diff
new file mode 100644
index 0000000000..af85599f20
--- /dev/null
+++ b/packages/motion/motion-3.2.11/ffmpeg-0.4.9.15594svn-20081010.diff
@@ -0,0 +1,14 @@
+Index: ffmpeg.c
+===================================================================
+--- trunk/ffmpeg.c (revision 434)
++++ trunk/ffmpeg.c (working copy)
+@@ -164,7 +164,8 @@
+ return write(fd, buf, size);
+ }
+
+-static offset_t file_seek(URLContext *h, offset_t pos, int whence)
++
++static int64_t file_seek(URLContext *h, int64_t pos, int whence)
+ {
+ int fd = (size_t)h->priv_data;
+ return lseek(fd, pos, whence);
diff --git a/packages/motion/motion_3.2.11.bb b/packages/motion/motion_3.2.11.bb
index dc7c0ecdbb..999a0ab6bd 100644
--- a/packages/motion/motion_3.2.11.bb
+++ b/packages/motion/motion_3.2.11.bb
@@ -7,13 +7,14 @@ DEPENDS = "jpeg ffmpeg mysql postgresql"
RSUGGESTS = "mysql-client postgresql-client"
-PR = "r0"
+PR = "r1"
-SRC_URI = "${SOURCEFORGE_MIRROR}/${PN}/${PN}-${PV}.tar.gz"
+SRC_URI = "${SOURCEFORGE_MIRROR}/${PN}/${PN}-${PV}.tar.gz \
+ file://ffmpeg-0.4.9.15594svn-20081010.diff;patch=1 "
inherit autotools
-EXTRA_OECONF = " --with-ffmpeg=${STAGING_LIBDIR} \
+EXTRA_OECONF = " --with-ffmpeg=${STAGING_LIBDIR}/../ \
--with-mysql-lib=${STAGING_LIBDIR} \
--with-mysql-include=${STAGING_INCDIR}/mysql \
--with-pgsql-lib=${STAGING_LIBDIR} \
diff --git a/packages/psplash/files/psplash-init b/packages/psplash/files/psplash-init
index 7796a79064..a4fb1dc7d1 100644
--- a/packages/psplash/files/psplash-init
+++ b/packages/psplash/files/psplash-init
@@ -1,13 +1,9 @@
#!/bin/sh
-for x in $(cat /proc/cmdline); do
- case $x in
- psplash=false)
- echo "Boot splashscreen disabled"
- exit 0;
- ;;
- esac
-done
+if grep -qE '\s?psplash=false\s?' /proc/cmdline; then
+ echo "Boot splashscreen disabled"
+ exit 0;
+fi
. /etc/init.d/functions
. /etc/default/psplash
diff --git a/packages/psplash/psplash-openmoko_svn.bb b/packages/psplash/psplash-openmoko_svn.bb
index 4e7dbcce59..1114645040 100644
--- a/packages/psplash/psplash-openmoko_svn.bb
+++ b/packages/psplash/psplash-openmoko_svn.bb
@@ -10,6 +10,7 @@ ALTERNATIVE_PRIORITY = "30"
# You might also want to patch the colors (see patch)
SRC_URI = "svn://svn.o-hand.com/repos/misc/trunk;module=psplash;proto=http \
+ file://logo-math.patch;patch=1 \
file://psplash-hand-img.h \
file://psplash-bar-img.h \
file://psplash-default \
diff --git a/packages/psplash/psplash.inc b/packages/psplash/psplash.inc
index d1df18ff45..ea20436a9a 100644
--- a/packages/psplash/psplash.inc
+++ b/packages/psplash/psplash.inc
@@ -5,6 +5,7 @@ LICENSE = "GPL"
RDEPENDS = "initscripts"
PV = "0.0+svnr${SRCREV}"
+PR = "r1"
# You can create your own pslash-hand-img.h by doing
# ./make-image-header.sh <file>.png HAND
diff --git a/packages/psplash/psplash_svn.bb b/packages/psplash/psplash_svn.bb
index e7cbda5641..f471396843 100644
--- a/packages/psplash/psplash_svn.bb
+++ b/packages/psplash/psplash_svn.bb
@@ -3,7 +3,7 @@ require psplash-ua.inc
ALTERNATIVE_PRIORITY = "10"
-PR = "r17"
+PR = "r18"
SRC_URI = "svn://svn.o-hand.com/repos/misc/trunk;module=psplash;proto=http \
file://psplash-hand-img.h \
diff --git a/packages/tasks/task-gstreamer-ti.bb b/packages/tasks/task-gstreamer-ti.bb
new file mode 100644
index 0000000000..e6d34be966
--- /dev/null
+++ b/packages/tasks/task-gstreamer-ti.bb
@@ -0,0 +1,16 @@
+
+# Task for dsp accelerated gstreamer plugins
+
+DEPENDS = "gst-plugins-base gst-plugins-good gst-plugins-ugly gst-ffmpeg gstreamer-ti gst-openmax"
+
+RDEPENDS_${PN} = " \
+gst-plugins-base-meta \
+gst-plugins-good-meta \
+gst-plugins-ugly-meta \
+gst-ffmpeg \
+gst-openmax \
+gstreamer-ti \
+"
+
+inherit task
+
diff --git a/packages/tuxtype/tuxtype_1.7.3.bb b/packages/tuxtype/tuxtype_1.7.3.bb
new file mode 100644
index 0000000000..9712bcb753
--- /dev/null
+++ b/packages/tuxtype/tuxtype_1.7.3.bb
@@ -0,0 +1,20 @@
+DESCRIPTION = "Typing game"
+HOMEPAGE = "http://tux4kids.alioth.debian.org/"
+PRIORITY = "optional"
+LICENSE = "GPL"
+DEPENDS = "virtual/libsdl libsdl-mixer libsdl-image libsdl-ttf sdlpango"
+
+# warning: when changing package version the download number (2767)
+# must be changed as well
+SRC_URI = "http://alioth.debian.org/frs/download.php/2767/tuxtype_w_fonts-1.7.3.tar.gz"
+
+S = "${WORKDIR}/tuxtype_w_fonts-${PV}"
+
+inherit autotools
+
+FILES_${PN} = "/"
+
+export SDL_CONFIG = "${STAGING_BINDIR_CROSS}/sdl-config"
+export MKDIR_P = "mkdir -p"
+
+PARALLEL_MAKE = ""
diff --git a/packages/u-boot/u-boot-1.3.2/boc01/007-090112-CAPSENSE.patch b/packages/u-boot/u-boot-1.3.2/boc01/007-090217-CAPSENSE.patch
index cc176f20b1..1b7630536f 100644
--- a/packages/u-boot/u-boot-1.3.2/boc01/007-090112-CAPSENSE.patch
+++ b/packages/u-boot/u-boot-1.3.2/boc01/007-090217-CAPSENSE.patch
@@ -349,8 +349,8 @@ Index: u-boot-1.3.2/drivers/i2c/CY8C201xx.c
+ 0x00, 0x00, 0x00, 0x00, 0x00, // CS_SCAN_POS_1x
+ 0x32, 0x00, 0x32, 0x32, 0x32, // CS_FINGER_TH_0x
+ 0x00, 0x00, 0x00, 0x00, 0x32, // CS_FINGER_TH_1x
-+ 0x08, 0x00, 0x08, 0x08, 0x08, // CS_IDAC_0x
-+ 0x00, 0x00, 0x00, 0x00, 0x08 // CS_IDAC_1x
++ 0x14, 0x00, 0x0C, 0x0A, 0x14, // CS_IDAC_0x
++ 0x00, 0x00, 0x00, 0x00, 0x0D // CS_IDAC_1x
+};
+
+static char data_SLEEP[] = {
diff --git a/packages/u-boot/u-boot_1.3.2.bb b/packages/u-boot/u-boot_1.3.2.bb
index 0ed92c70b8..59ebaecabd 100644
--- a/packages/u-boot/u-boot_1.3.2.bb
+++ b/packages/u-boot/u-boot_1.3.2.bb
@@ -2,7 +2,7 @@ require u-boot.inc
DEFAULT_PREFERENCE = "-1"
-PR = "r10"
+PR = "r11"
SRC_URI = "ftp://ftp.denx.de/pub/u-boot/u-boot-${PV}.tar.bz2"
@@ -27,7 +27,7 @@ SRC_URI_append_boc01 = "\
file://003-081205-DTT_LM73.patch;patch=1 \
file://004-081205-WATCHDOG.patch;patch=1 \
file://006-081211-EEPROM_M24C32.patch;patch=1 \
- file://007-090112-CAPSENSE.patch;patch=1 \
+ file://007-090217-CAPSENSE.patch;patch=1 \
file://008-090107-TSEC.patch;patch=1 \
file://009-081212-EXIO.patch;patch=1 \
file://010-081212-LCD.patch;patch=1 \