summaryrefslogtreecommitdiffstats
path: root/tdm/kfrontend
diff options
context:
space:
mode:
authorTimothy Pearson <kb9vqf@pearsoncomputing.net>2012-01-22 01:02:36 -0600
committerTimothy Pearson <kb9vqf@pearsoncomputing.net>2012-01-22 01:02:36 -0600
commitb81e43465b14836b17e4fe2dea91c78a2bdd29b3 (patch)
tree7815d61ce59a6ccb6e655ed44f5fea786f520985 /tdm/kfrontend
parent7021f40c13f949b7cb5ded32d0241d648a43bf6c (diff)
downloadtdebase-b81e43465b14836b17e4fe2dea91c78a2bdd29b3.tar.gz
tdebase-b81e43465b14836b17e4fe2dea91c78a2bdd29b3.zip
Part 2 of prior commit
Diffstat (limited to 'tdm/kfrontend')
-rw-r--r--tdm/kfrontend/CMakeLists.txt101
-rw-r--r--tdm/kfrontend/Makefile.am67
-rw-r--r--tdm/kfrontend/gentdmconf.c2849
-rw-r--r--tdm/kfrontend/kchooser.cpp227
-rw-r--r--tdm/kfrontend/kchooser.h59
-rw-r--r--tdm/kfrontend/kconsole.cpp183
-rw-r--r--tdm/kfrontend/kconsole.h53
-rw-r--r--tdm/kfrontend/kfdialog.cpp182
-rw-r--r--tdm/kfrontend/kfdialog.h65
-rw-r--r--tdm/kfrontend/kgapp.cpp469
-rw-r--r--tdm/kfrontend/kgapp.h50
-rw-r--r--tdm/kfrontend/kgdialog.cpp240
-rw-r--r--tdm/kfrontend/kgdialog.h87
-rw-r--r--tdm/kfrontend/kgreeter.cpp1280
-rw-r--r--tdm/kfrontend/kgreeter.h180
-rw-r--r--tdm/kfrontend/kgverify.cpp1218
-rw-r--r--tdm/kfrontend/kgverify.h249
-rw-r--r--tdm/kfrontend/krootimage.cpp140
-rw-r--r--tdm/kfrontend/krootimage.h48
-rw-r--r--tdm/kfrontend/pics/CMakeLists.txt18
-rw-r--r--tdm/kfrontend/pics/Makefile.am9
-rw-r--r--tdm/kfrontend/pics/default1.pngbin0 -> 2622 bytes
-rw-r--r--tdm/kfrontend/pics/default2.pngbin0 -> 5663 bytes
-rw-r--r--tdm/kfrontend/pics/default3.pngbin0 -> 4260 bytes
-rw-r--r--tdm/kfrontend/pics/kdelogo-crystal.pngbin0 -> 11375 bytes
-rw-r--r--tdm/kfrontend/pics/kdelogo.pngbin0 -> 13450 bytes
-rw-r--r--tdm/kfrontend/pics/root1.pngbin0 -> 3070 bytes
-rw-r--r--tdm/kfrontend/pics/shutdown.jpgbin0 -> 2536 bytes
-rw-r--r--tdm/kfrontend/sakdlg.cc247
-rw-r--r--tdm/kfrontend/sakdlg.h64
-rw-r--r--tdm/kfrontend/sessions/9wm.desktop76
-rw-r--r--tdm/kfrontend/sessions/CMakeLists.txt29
-rw-r--r--tdm/kfrontend/sessions/Makefile.am49
-rw-r--r--tdm/kfrontend/sessions/admin.desktop7
-rw-r--r--tdm/kfrontend/sessions/aewm++.desktop74
-rw-r--r--tdm/kfrontend/sessions/aewm.desktop76
-rw-r--r--tdm/kfrontend/sessions/afterstep.desktop83
-rw-r--r--tdm/kfrontend/sessions/amaterus.desktop75
-rw-r--r--tdm/kfrontend/sessions/amiwm.desktop78
-rw-r--r--tdm/kfrontend/sessions/asclassic.desktop81
-rw-r--r--tdm/kfrontend/sessions/blackbox.desktop88
-rw-r--r--tdm/kfrontend/sessions/cde.desktop74
-rw-r--r--tdm/kfrontend/sessions/ctwm.desktop72
-rw-r--r--tdm/kfrontend/sessions/cwwm.desktop74
-rw-r--r--tdm/kfrontend/sessions/enlightenment.desktop86
-rw-r--r--tdm/kfrontend/sessions/evilwm.desktop77
-rw-r--r--tdm/kfrontend/sessions/fluxbox.desktop81
-rw-r--r--tdm/kfrontend/sessions/flwm.desktop77
-rw-r--r--tdm/kfrontend/sessions/fvwm.desktop71
-rw-r--r--tdm/kfrontend/sessions/fvwm2.desktop70
-rw-r--r--tdm/kfrontend/sessions/fvwm95.desktop76
-rw-r--r--tdm/kfrontend/sessions/gnome.desktop81
-rw-r--r--tdm/kfrontend/sessions/golem.desktop81
-rw-r--r--tdm/kfrontend/sessions/icewm.desktop81
-rw-r--r--tdm/kfrontend/sessions/ion.desktop77
-rw-r--r--tdm/kfrontend/sessions/larswm.desktop72
-rw-r--r--tdm/kfrontend/sessions/lwm.desktop76
-rw-r--r--tdm/kfrontend/sessions/matchbox.desktop82
-rw-r--r--tdm/kfrontend/sessions/metacity.desktop83
-rw-r--r--tdm/kfrontend/sessions/mwm.desktop78
-rw-r--r--tdm/kfrontend/sessions/olvwm.desktop71
-rw-r--r--tdm/kfrontend/sessions/olwm.desktop76
-rw-r--r--tdm/kfrontend/sessions/openbox.desktop84
-rw-r--r--tdm/kfrontend/sessions/oroborus.desktop76
-rw-r--r--tdm/kfrontend/sessions/phluid.desktop80
-rw-r--r--tdm/kfrontend/sessions/pwm.desktop72
-rw-r--r--tdm/kfrontend/sessions/qvwm.desktop80
-rw-r--r--tdm/kfrontend/sessions/ratpoison.desktop82
-rw-r--r--tdm/kfrontend/sessions/sapphire.desktop84
-rw-r--r--tdm/kfrontend/sessions/sawfish.desktop74
-rw-r--r--tdm/kfrontend/sessions/tde.desktop.cmake45
-rw-r--r--tdm/kfrontend/sessions/tde.desktop.in45
-rw-r--r--tdm/kfrontend/sessions/twm.desktop71
-rw-r--r--tdm/kfrontend/sessions/ude.desktop75
-rw-r--r--tdm/kfrontend/sessions/vtwm.desktop72
-rw-r--r--tdm/kfrontend/sessions/w9wm.desktop74
-rw-r--r--tdm/kfrontend/sessions/waimea.desktop77
-rw-r--r--tdm/kfrontend/sessions/wm2.desktop77
-rw-r--r--tdm/kfrontend/sessions/wmaker.desktop82
-rw-r--r--tdm/kfrontend/sessions/xfce.desktop73
-rw-r--r--tdm/kfrontend/sessions/xfce4.desktop72
-rw-r--r--tdm/kfrontend/tdm_config.c1477
-rw-r--r--tdm/kfrontend/tdm_greet.c787
-rw-r--r--tdm/kfrontend/tdm_greet.h91
-rw-r--r--tdm/kfrontend/tdmadmindialog.cpp176
-rw-r--r--tdm/kfrontend/tdmadmindialog.h70
-rw-r--r--tdm/kfrontend/tdmclock.cpp176
-rw-r--r--tdm/kfrontend/tdmclock.h52
-rw-r--r--tdm/kfrontend/tdmconfig.cpp179
-rw-r--r--tdm/kfrontend/tdmconfig.h69
-rw-r--r--tdm/kfrontend/tdmctl.c234
-rw-r--r--tdm/kfrontend/tdmshutdown.cpp925
-rw-r--r--tdm/kfrontend/tdmshutdown.h240
-rw-r--r--tdm/kfrontend/themer/CMakeLists.txt41
-rw-r--r--tdm/kfrontend/themer/Makefile.am16
-rw-r--r--tdm/kfrontend/themer/tdmitem.cpp657
-rw-r--r--tdm/kfrontend/themer/tdmitem.h272
-rw-r--r--tdm/kfrontend/themer/tdmlabel.cpp276
-rw-r--r--tdm/kfrontend/themer/tdmlabel.h87
-rw-r--r--tdm/kfrontend/themer/tdmlayout.cpp168
-rw-r--r--tdm/kfrontend/themer/tdmlayout.h98
-rw-r--r--tdm/kfrontend/themer/tdmpixmap.cpp340
-rw-r--r--tdm/kfrontend/themer/tdmpixmap.h73
-rw-r--r--tdm/kfrontend/themer/tdmrect.cpp181
-rw-r--r--tdm/kfrontend/themer/tdmrect.h67
-rw-r--r--tdm/kfrontend/themer/tdmthemer.cpp404
-rw-r--r--tdm/kfrontend/themer/tdmthemer.h128
-rw-r--r--tdm/kfrontend/themes/CMakeLists.txt13
-rw-r--r--tdm/kfrontend/themes/Makefile.am1
-rw-r--r--tdm/kfrontend/themes/circles/CMakeLists.txt15
-rw-r--r--tdm/kfrontend/themes/circles/GdmGreeterTheme.desktop135
-rw-r--r--tdm/kfrontend/themes/circles/Makefile.am11
-rw-r--r--tdm/kfrontend/themes/circles/background.svg39
-rw-r--r--tdm/kfrontend/themes/circles/circles.xml207
-rw-r--r--tdm/kfrontend/themes/circles/flower.pngbin0 -> 120376 bytes
-rw-r--r--tdm/kfrontend/themes/circles/help.pngbin0 -> 2138 bytes
-rw-r--r--tdm/kfrontend/themes/circles/options.pngbin0 -> 2297 bytes
-rw-r--r--tdm/kfrontend/themes/circles/screenshot.pngbin0 -> 16847 bytes
-rw-r--r--tdm/kfrontend/themes/o2_enterprise/CMakeLists.txt16
-rw-r--r--tdm/kfrontend/themes/o2_enterprise/Dialog.pngbin0 -> 4167 bytes
-rw-r--r--tdm/kfrontend/themes/o2_enterprise/GdmGreeterTheme.desktop10
-rw-r--r--tdm/kfrontend/themes/o2_enterprise/Makefile.am14
-rw-r--r--tdm/kfrontend/themes/o2_enterprise/enter_normal.pngbin0 -> 1639 bytes
-rw-r--r--tdm/kfrontend/themes/o2_enterprise/enter_over.pngbin0 -> 2422 bytes
-rw-r--r--tdm/kfrontend/themes/o2_enterprise/enter_pressed.pngbin0 -> 1639 bytes
-rw-r--r--tdm/kfrontend/themes/o2_enterprise/enterprise.xml99
-rw-r--r--tdm/kfrontend/themes/o2_enterprise/gpl.txt340
-rw-r--r--tdm/kfrontend/themes/o2_enterprise/preview.pngbin0 -> 381843 bytes
-rw-r--r--tdm/kfrontend/themes/o2_enterprise/system_normal.pngbin0 -> 1623 bytes
-rw-r--r--tdm/kfrontend/themes/o2_enterprise/system_over.pngbin0 -> 2491 bytes
-rw-r--r--tdm/kfrontend/themes/o2_enterprise/system_pressed.pngbin0 -> 1623 bytes
131 files changed, 19996 insertions, 0 deletions
diff --git a/tdm/kfrontend/CMakeLists.txt b/tdm/kfrontend/CMakeLists.txt
new file mode 100644
index 00000000..4a069a3a
--- /dev/null
+++ b/tdm/kfrontend/CMakeLists.txt
@@ -0,0 +1,101 @@
+#################################################
+#
+# (C) 2010-2011 Serghei Amelian
+# serghei (DOT) amelian (AT) gmail.com
+#
+# Improvements and feedback are welcome
+#
+# This file is released under GPL >= 2
+#
+#################################################
+
+add_subdirectory( themer )
+add_subdirectory( themes )
+add_subdirectory( pics )
+add_subdirectory( sessions )
+
+include_directories(
+ ${CMAKE_CURRENT_BINARY_DIR}
+ ${CMAKE_BINARY_DIR}
+ ${CMAKE_SOURCE_DIR}/tdm/backend
+ ${CMAKE_SOURCE_DIR}/tdmlib
+ ${CMAKE_SOURCE_DIR}/kcontrol/background
+ ${TDE_INCLUDE_DIR}
+ ${TQT_INCLUDE_DIRS}
+)
+
+link_directories(
+ ${TQT_LIBRARY_DIRS}
+)
+
+
+##### other data ################################
+
+if( NOT DEFINED GENTDMCONF_FLAGS )
+ set( GENTDMCONF_FLAGS "--no-old" )
+endif( )
+
+install( CODE "execute_process( COMMAND ${CMAKE_CURRENT_BINARY_DIR}/gentdmconf --in \$ENV{DESTDIR}${CONFIG_INSTALL_DIR}/tdm --no-in-notice --face-src ${CMAKE_CURRENT_SOURCE_DIR}/pics ${GENTDMCONF_FLAGS} )" )
+
+
+##### config.ci (generated) #####################
+
+add_custom_command( OUTPUT config.ci
+ COMMAND perl -w ${CMAKE_SOURCE_DIR}/tdm/confproc.pl ${CMAKE_SOURCE_DIR}/tdm/config.def config.ci
+ DEPENDS ${CMAKE_SOURCE_DIR}/tdm/confproc.pl ${CMAKE_SOURCE_DIR}/tdm/config.def )
+
+
+##### tdm_config (executable) ###################
+
+set_property( SOURCE tdm_config.c APPEND PROPERTY OBJECT_DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/config.ci )
+
+tde_add_executable( tdm_config
+ SOURCES tdm_config.c
+ LINK
+ DESTINATION ${BIN_INSTALL_DIR}
+)
+
+
+##### tdm_greet (executable) ####################
+if( WITH_XRANDR )
+ set( TDMGREET_OPTIONAL_LINK "krandr-shared" )
+endif ( )
+
+tde_add_executable( tdm_greet AUTOMOC
+ SOURCES
+ tdm_greet.c tdmconfig.cpp tdmclock.cpp kconsole.cpp
+ kfdialog.cpp kgdialog.cpp kchooser.cpp kgverify.cpp
+ tdmshutdown.cpp tdmadmindialog.cpp kgreeter.cpp
+ kgapp.cpp sakdlg.cc
+ LINK tdmthemer-static tdeui-shared Xtst ${TDMGREET_OPTIONAL_LINK}
+ DESTINATION ${BIN_INSTALL_DIR}
+)
+
+
+##### krootimage (executable) ###################
+
+tde_add_executable( krootimage AUTOMOC
+ SOURCES krootimage.cpp
+ LINK bgnd-static kio-shared
+ DESTINATION ${BIN_INSTALL_DIR}
+)
+
+
+##### gentdmconf (executable) ###################
+
+set_property( SOURCE gentdmconf.c APPEND PROPERTY OBJECT_DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/config.ci )
+
+tde_add_executable( gentdmconf AUTOMOC
+ SOURCES gentdmconf.c
+ LINK X11
+ DESTINATION ${BIN_INSTALL_DIR}
+)
+
+
+##### tdmctl (executable) #######################
+
+tde_add_executable( tdmctl
+ SOURCES tdmctl.c
+ LINK
+ DESTINATION ${BIN_INSTALL_DIR}
+)
diff --git a/tdm/kfrontend/Makefile.am b/tdm/kfrontend/Makefile.am
new file mode 100644
index 00000000..7c58dc67
--- /dev/null
+++ b/tdm/kfrontend/Makefile.am
@@ -0,0 +1,67 @@
+# use 'make GENTDMCONF_FLAGS=... install' to override
+GENTDMCONF_FLAGS = --no-old
+
+SUBDIRS = themer themes pics sessions
+
+AM_CPPFLAGS = -I$(srcdir)/../backend -I.. -I$(top_srcdir)/kcontrol/background \
+ -I$(top_srcdir)/tdmlib $(all_includes)
+
+bin_PROGRAMS = tdm_config tdm_greet krootimage gentdmconf tdmctl
+
+tdm_config_SOURCES = tdm_config.c
+tdm_config_LDADD = $(LIBRESOLV) $(LIBSOCKET) $(LIBPOSIX4)
+
+tdm_greet_SOURCES = \
+ tdm_greet.c \
+ tdmconfig.cpp \
+ tdmclock.cpp \
+ kconsole.cpp \
+ kfdialog.cpp \
+ kgdialog.cpp \
+ kchooser.cpp \
+ kgverify.cpp \
+ tdmshutdown.cpp \
+ tdmadmindialog.cpp \
+ kgreeter.cpp \
+ kgapp.cpp
+tdm_greet_LDFLAGS = $(all_libraries) $(KDE_RPATH) $(LIB_QT) -lDCOP $(LIB_TDECORE) $(LIB_TDEUI) -ltdefx $(LIB_KIO) -lktexteditor
+tdm_greet_LDADD = themer/libtdmthemer.a $(LIB_TDEUI) $(XTESTLIB) $(LIBPOSIX4)
+
+krootimage_SOURCES = krootimage.cpp
+krootimage_LDFLAGS = $(all_libraries) $(KDE_RPATH) $(LIB_QT) -lDCOP $(LIB_TDECORE) $(LIB_TDEUI) -ltdefx $(LIB_KIO) -lktexteditor
+krootimage_LDADD = $(top_builddir)/kcontrol/background/libbgnd.la $(LIB_KIO)
+
+METASOURCES = AUTO
+
+gentdmconf_SOURCES = gentdmconf.c
+gentdmconf_LDFLAGS = $(X_LDFLAGS) $(X_RPATH)
+gentdmconf_LDADD = $(LIB_X11)
+
+tdmctl_SOURCES = tdmctl.c
+tdmctl_LDADD = $(LIBSOCKET)
+
+install-data-local: gentdmconf
+ ./gentdmconf --in $(DESTDIR)$(kde_confdir)/tdm --no-in-notice --face-src $(srcdir)/pics $(GENTDMCONF_FLAGS)
+
+messages:
+ $(XGETTEXT) `find . -name "*.cpp"` -o $(podir)/tdmgreet.pot
+
+noinst_HEADERS = \
+ tdm_greet.h \
+ tdmconfig.h \
+ tdmclock.h \
+ kconsole.h \
+ kfdialog.h \
+ kgdialog.h \
+ kchooser.h \
+ kgverify.h \
+ tdmshutdown.h \
+ kgreeter.h \
+ kgapp.h \
+ \
+ krootimage.h
+
+tdm_greet_COMPILE_FIRST = ../config.ci
+tdm_config_COMPILE_FIRST = ../config.ci
+gentdmconf_COMPILE_FIRST = ../config.ci
+
diff --git a/tdm/kfrontend/gentdmconf.c b/tdm/kfrontend/gentdmconf.c
new file mode 100644
index 00000000..f55ffbbb
--- /dev/null
+++ b/tdm/kfrontend/gentdmconf.c
@@ -0,0 +1,2849 @@
+/*
+
+Create a suitable configuration for tdm taking old xdm/tdm
+installations into account
+
+Copyright (C) 2001-2005 Oswald Buddenhagen <ossi@kde.org>
+
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#include <X11/Xlib.h>
+#include <X11/Xresource.h>
+
+#include <config.h>
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdarg.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <utime.h>
+#include <dirent.h>
+#include <errno.h>
+#include <pwd.h>
+#include <time.h>
+#include <limits.h>
+#include <sys/stat.h>
+#include <sys/param.h>
+#ifdef BSD
+# include <utmp.h>
+#endif
+
+#include "config.ci"
+
+#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 4)
+# define ATTR_UNUSED __attribute__((unused))
+#else
+# define ATTR_UNUSED
+#endif
+
+#if defined(__sun) && !defined(__sun__)
+# define __sun__
+#endif
+
+#define as(ar) ((int)(sizeof(ar)/sizeof(ar[0])))
+
+#define __stringify(x) #x
+#define stringify(x) __stringify(x)
+
+#define RCVERSTR stringify(RCVERMAJOR) "." stringify(RCVERMINOR)
+
+static int old_scripts, no_old_scripts, old_confs, no_old,
+ no_backup, no_in_notice, use_destdir, mixed_scripts;
+static const char *newdir = TDMCONF, *facesrc = TDMDATA "/pics/users",
+ *oldxdm, *oldkde;
+
+static int oldver;
+
+
+typedef struct StrList {
+ struct StrList *next;
+ const char *str;
+} StrList;
+
+
+static void *
+mmalloc( size_t sz )
+{
+ void *ptr;
+
+ if (!(ptr = malloc( sz ))) {
+ fprintf( stderr, "Out of memory\n" );
+ exit( 1 );
+ }
+ return ptr;
+}
+
+static void *
+mcalloc( size_t sz )
+{
+ void *ptr;
+
+ if (!(ptr = calloc( 1, sz ))) {
+ fprintf( stderr, "Out of memory\n" );
+ exit( 1 );
+ }
+ return ptr;
+}
+
+static void *
+mrealloc( void *optr, size_t sz )
+{
+ void *ptr;
+
+ if (!(ptr = realloc( optr, sz ))) {
+ fprintf( stderr, "Out of memory\n" );
+ exit( 1 );
+ }
+ return ptr;
+}
+
+static char *
+mstrdup( const char *optr )
+{
+ char *ptr;
+
+ if (!optr)
+ return 0;
+ if (!(ptr = strdup( optr ))) {
+ fprintf( stderr, "Out of memory\n" );
+ exit( 1 );
+ }
+ return ptr;
+}
+
+
+#define NO_LOGGER
+#define STATIC static
+#include <printf.c>
+
+typedef struct {
+ char *buf;
+ int clen, blen, tlen;
+} OCABuf;
+
+static void
+OutCh_OCA( void *bp, char c )
+{
+ OCABuf *ocabp = (OCABuf *)bp;
+
+ ocabp->tlen++;
+ if (ocabp->clen >= ocabp->blen) {
+ ocabp->blen = ocabp->blen * 3 / 2 + 100;
+ ocabp->buf = mrealloc( ocabp->buf, ocabp->blen );
+ }
+ ocabp->buf[ocabp->clen++] = c;
+}
+
+static int
+VASPrintf( char **strp, const char *fmt, va_list args )
+{
+ OCABuf ocab = { 0, 0, 0, -1 };
+
+ DoPr( OutCh_OCA, &ocab, fmt, args );
+ OutCh_OCA( &ocab, 0 );
+ *strp = realloc( ocab.buf, ocab.clen );
+ if (!*strp)
+ *strp = ocab.buf;
+ return ocab.tlen;
+}
+
+static int
+ASPrintf( char **strp, const char *fmt, ... )
+{
+ va_list args;
+ int len;
+
+ va_start( args, fmt );
+ len = VASPrintf( strp, fmt, args );
+ va_end( args );
+ return len;
+}
+
+static void
+StrCat( char **strp, const char *fmt, ... )
+{
+ char *str, *tstr;
+ va_list args;
+ int el;
+
+ va_start( args, fmt );
+ el = VASPrintf( &str, fmt, args );
+ va_end( args );
+ if (*strp) {
+ int ol = strlen( *strp );
+ tstr = mmalloc( el + ol + 1 );
+ memcpy( tstr, *strp, ol );
+ memcpy( tstr + ol, str, el + 1 );
+ free( *strp );
+ free( str );
+ *strp = tstr;
+ } else
+ *strp = str;
+}
+
+
+#define WANT_CLOSE 1
+
+typedef struct File {
+ char *buf, *eof, *cur;
+#if defined(HAVE_MMAP) && defined(WANT_CLOSE)
+ int ismapped;
+#endif
+} File;
+
+static int
+readFile( File *file, const char *fn )
+{
+ off_t flen;
+ int fd;
+
+ if ((fd = open( fn, O_RDONLY )) < 0)
+ return 0;
+
+ flen = lseek( fd, 0, SEEK_END );
+#ifdef HAVE_MMAP
+# ifdef WANT_CLOSE
+ file->ismapped = 0;
+# endif
+ file->buf = mmap( 0, flen + 1, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0 );
+# ifdef WANT_CLOSE
+ if (file->buf)
+ file->ismapped = 1;
+ else
+# else
+ if (!file->buf)
+# endif
+#endif
+ {
+ file->buf = mmalloc( flen + 1 );
+ lseek( fd, 0, SEEK_SET );
+ if (read( fd, file->buf, flen ) != flen) {
+ free( file->buf );
+ close( fd );
+ fprintf( stderr, "Cannot read file\n" );
+ return 0; /* maybe better abort? */
+ }
+ }
+ file->eof = file->buf + flen;
+ close( fd );
+ return 1;
+}
+
+#ifdef WANT_CLOSE
+static void
+freeBuf( File *file )
+{
+# ifdef HAVE_MMAP
+ if (file->ismapped)
+ munmap( file->buf, file->eof - file->buf );
+ else
+# endif
+ free( file->buf );
+}
+#endif
+
+static int
+isTrue( const char *val )
+{
+ return !strcmp( val, "true" ) ||
+ !strcmp( val, "yes" ) ||
+ !strcmp( val, "on" ) ||
+ atoi( val );
+}
+
+static int
+mkdirp( const char *name, int mode, const char *what, int existok )
+{
+ char *mfname = mstrdup( name );
+ int i;
+ struct stat st;
+
+ for (i = 1; mfname[i]; i++)
+ if (mfname[i] == '/') {
+ mfname[i] = 0;
+ if (stat( mfname, &st )) {
+ if (mkdir( mfname, 0755 )) {
+ fprintf( stderr, "Cannot create parent %s of %s directory %s: %s\n",
+ mfname, what, name, strerror( errno ) );
+ free( mfname );
+ return 0;
+ }
+ chmod( mfname, 0755 );
+ }
+ mfname[i] = '/';
+ }
+ free( mfname );
+ if (stat( name, &st )) {
+ if (mkdir( name, mode )) {
+ fprintf( stderr, "Cannot create %s directory %s: %s\n",
+ what, name, strerror( errno ) );
+ return 0;
+ }
+ chmod( name, mode );
+ return 1;
+ }
+ return existok;
+}
+
+
+static void
+displace( const char *fn )
+{
+ if (!no_backup) {
+ char bn[PATH_MAX + 4];
+ sprintf( bn, "%s.bak", fn ); /* won't overflow if only existing paths are passed */
+ rename( fn, bn );
+ } else
+ unlink( fn );
+}
+
+
+static char *
+locate( const char *exe )
+{
+ int len;
+ char *path, *name, *thenam, nambuf[PATH_MAX+1];
+ char *pathe;
+
+ if (!(path = getenv( "PATH" )))
+ return 0;
+ len = strlen( exe );
+ name = nambuf + PATH_MAX - len;
+ memcpy( name, exe, len + 1 );
+ *--name = '/';
+ do {
+ if (!(pathe = strchr( path, ':' )))
+ pathe = path + strlen( path );
+ len = pathe - path;
+ if (len && !(len == 1 && *path == '.')) {
+ thenam = name - len;
+ if (thenam >= nambuf) {
+ memcpy( thenam, path, len );
+ if (!access( thenam, X_OK ))
+ return mstrdup( thenam );
+ }
+ }
+ path = pathe;
+ } while (*path++ != '\0');
+ return 0;
+}
+
+
+/*
+ * target data to be written to tdmrc
+ */
+
+typedef struct Entry {
+ struct Entry *next;
+ struct Ent *spec;
+ const char *value;
+ int active:1;
+ int written:1;
+} Entry;
+
+typedef struct Section {
+ struct Section *next;
+ struct Sect *spec;
+ const char *name;
+ const char *comment;
+ Entry *ents;
+} Section;
+
+static Section *config; /* the tdmrc data to be written */
+
+/*
+ * Specification of the (currently possible) tdmrc entries
+ */
+
+typedef struct Ent {
+ const char *key;
+ int prio;
+ void (*func)( Entry *ce, Section *cs );
+ const char *comment;
+} Ent;
+
+typedef struct Sect {
+ const char *name;
+ Ent *ents;
+ int nents;
+} Sect;
+
+static Sect *findSect( const char *name );
+static Ent *findEnt( Sect *sect, const char *key );
+
+/*
+ * Functions to manipulate the current tdmrc data
+ */
+
+static const char *
+getfqval( const char *sect, const char *key, const char *defval )
+{
+ Section *cs;
+ Entry *ce;
+
+ for (cs = config; cs; cs = cs->next)
+ if (!strcmp( cs->name, sect )) {
+ for (ce = cs->ents; ce; ce = ce->next)
+ if (!strcmp( ce->spec->key, key )) {
+ if (ce->active && ce->written)
+ return ce->value;
+ break;
+ }
+ break;
+ }
+ return defval;
+}
+
+static void
+putfqval( const char *sect, const char *key, const char *value )
+{
+ Section *cs, **csp;
+ Entry *ce, **cep;
+
+ if (!value)
+ return;
+
+ for (csp = &config; (cs = *csp); csp = &(cs->next))
+ if (!strcmp( sect, cs->name ))
+ goto havesec;
+ cs = mcalloc( sizeof(*cs) );
+ ASPrintf( (char **)&cs->name, "%s", sect );
+ cs->spec = findSect( sect );
+ *csp = cs;
+ havesec:
+
+ for (cep = &(cs->ents); (ce = *cep); cep = &(ce->next))
+ if (!strcmp( key, ce->spec->key ))
+ goto haveent;
+ ce = mcalloc( sizeof(*ce) );
+ ce->spec = findEnt( cs->spec, key );
+ *cep = ce;
+ haveent:
+ ASPrintf( (char **)&ce->value, "%s", value );
+ ce->written = ce->active = 1;
+}
+
+static const char *csect;
+
+#define setsect(se) csect = se
+
+static void
+putval( const char *key, const char *value )
+{
+ putfqval( csect, key, value );
+}
+
+
+static void
+wrconf( FILE *f )
+{
+ Section *cs;
+ Entry *ce;
+ StrList *sl = 0, *sp;
+ const char *cmt;
+
+ putfqval( "General", "ConfigVersion", RCVERSTR );
+ for (cs = config; cs; cs = cs->next) {
+ fprintf( f, "%s[%s]\n",
+ cs->comment ? cs->comment : "\n", cs->name );
+ for (ce = cs->ents; ce; ce = ce->next) {
+ if (ce->spec->comment) {
+ cmt = ce->spec->comment;
+ for (sp = sl; sp; sp = sp->next)
+ if (sp->str == cmt) {
+ cmt = "# See above\n";
+ goto havit;
+ }
+ if (!(sp = malloc( sizeof(*sp) )))
+ fprintf( stderr, "Warning: Out of memory\n" );
+ else {
+ sp->str = cmt;
+ sp->next = sl; sl = sp;
+ }
+ } else
+ cmt = "";
+ havit:
+ fprintf( f, "%s%s%s=%s\n",
+ cmt, ce->active ? "" : "#", ce->spec->key, ce->value );
+ }
+ }
+}
+
+
+/*
+ * defaults
+ */
+#ifdef XDMCP
+static const char def_xaccess[] =
+"# Xaccess - Access control file for XDMCP connections\n"
+"#\n"
+"# To control Direct and Broadcast access:\n"
+"#\n"
+"# pattern\n"
+"#\n"
+"# To control Indirect queries:\n"
+"#\n"
+"# pattern list of hostnames and/or macros ...\n"
+"#\n"
+"# To use the chooser:\n"
+"#\n"
+"# pattern CHOOSER BROADCAST\n"
+"#\n"
+"# or\n"
+"#\n"
+"# pattern CHOOSER list of hostnames and/or macros ...\n"
+"#\n"
+"# To define macros:\n"
+"#\n"
+"# %name list of hosts ...\n"
+"#\n"
+"# The first form tells xdm which displays to respond to itself.\n"
+"# The second form tells xdm to forward indirect queries from hosts matching\n"
+"# the specified pattern to the indicated list of hosts.\n"
+"# The third form tells xdm to handle indirect queries using the chooser;\n"
+"# the chooser is directed to send its own queries out via the broadcast\n"
+"# address and display the results on the terminal.\n"
+"# The fourth form is similar to the third, except instead of using the\n"
+"# broadcast address, it sends DirectQuerys to each of the hosts in the list\n"
+"#\n"
+"# In all cases, xdm uses the first entry which matches the terminal;\n"
+"# for IndirectQuery messages only entries with right hand sides can\n"
+"# match, for Direct and Broadcast Query messages, only entries without\n"
+"# right hand sides can match.\n"
+"#\n"
+"\n"
+"#* #any host can get a login window\n"
+"\n"
+"#\n"
+"# To hardwire a specific terminal to a specific host, you can\n"
+"# leave the terminal sending indirect queries to this host, and\n"
+"# use an entry of the form:\n"
+"#\n"
+"\n"
+"#terminal-a host-a\n"
+"\n"
+"\n"
+"#\n"
+"# The nicest way to run the chooser is to just ask it to broadcast\n"
+"# requests to the network - that way new hosts show up automatically.\n"
+"# Sometimes, however, the chooser can't figure out how to broadcast,\n"
+"# so this may not work in all environments.\n"
+"#\n"
+"\n"
+"#* CHOOSER BROADCAST #any indirect host can get a chooser\n"
+"\n"
+"#\n"
+"# If you'd prefer to configure the set of hosts each terminal sees,\n"
+"# then just uncomment these lines (and comment the CHOOSER line above)\n"
+"# and edit the %hostlist line as appropriate\n"
+"#\n"
+"\n"
+"#%hostlist host-a host-b\n"
+"\n"
+"#* CHOOSER %hostlist #\n";
+#endif
+
+#ifdef XDMCP
+static const char def_willing[] =
+"#! /bin/sh\n"
+"# The output of this script is displayed in the chooser window\n"
+"# (instead of \"Willing to manage\").\n"
+"\n"
+"load=`uptime|sed -e 's/^.*load[^0-9]*//'`\n"
+"nrusers=`who|cut -c 1-8|sort -u|wc -l|sed 's/^[ \t]*//'`\n"
+"s=\"\"; [ \"$nrusers\" != 1 ] && s=s\n"
+"\n"
+"echo \"${nrusers} user${s}, load: ${load}\"\n";
+#endif
+
+static const char def_setup[] =
+"#! /bin/sh\n"
+"# Xsetup - run as root before the login dialog appears\n"
+"\n"
+"#xconsole -geometry 480x130-0-0 -notify -verbose -fn fixed -exitOnFail -file /dev/xconsole &\n";
+
+static const char def_startup[] =
+"#! /bin/sh\n"
+"# Xstartup - run as root before session starts\n"
+"\n"
+"\n"
+"\n"
+"if [ -e /etc/nologin ]; then\n"
+" # always display the nologin message, if possible\n"
+" if [ -s /etc/nologin ] && which xmessage > /dev/null 2>&1; then\n"
+" xmessage -file /etc/nologin -geometry 640x480\n"
+" fi\n"
+" if [ \"$(id -u)\" != \"0\" ] && \\\n"
+" ! grep -qs '^ignore-nologin' /etc/trinity/tdm/tdm.options; then\n"
+" exit 1\n"
+" fi\n"
+"fi\n"
+"\n"
+"if grep -qs '^use-sessreg' /etc/trinity/tdm/tdm.options && \\\n"
+" which sessreg > /dev/null 2>&1; then\n"
+" exec sessreg -a -l \"$DISPLAY\" -u /var/run/utmp \\\n"
+" -h \"`echo $DISPLAY | cut -d: -f1`\" \"$USER\"\n"
+" # NOTREACHED\n"
+"fi\n";
+
+static const char def_reset[] =
+"#! /bin/sh\n"
+"# Xreset - run as root after session exits\n"
+"\n"
+"# Reassign ownership of the console to root, this should disallow\n"
+"# assignment of console output to any random users's xterm. See Xstartup.\n"
+"#\n"
+"#chown root /dev/console\n"
+"#chmod 622 /dev/console\n"
+"\n"
+#ifdef _AIX
+"#devname=`echo $DISPLAY | cut -c1-8`\n"
+"#exec sessreg -d -l xdm/$devname -h \"`echo $DISPLAY | cut -d: -f1`\""
+#else
+"if grep -qs '^use-sessreg' /etc/trinity/tdm/tdm.options && \\\n"
+" which sessreg > /dev/null 2>&1; then\n"
+" exec sessreg -d -l \"$DISPLAY\" -u /var/run/utmp \\\n"
+" -h \"`echo $DISPLAY | cut -d: -f1`\" \"$USER\"\n"
+" # NOTREACHED\n"
+"fi\n";
+#endif /* _AIX */
+
+static const char def_session1[] =
+"#! /bin/sh\n"
+"# Xsession - run as user\n"
+"\n"
+"session=$1\n"
+"\n"
+"# Note that the respective logout scripts are not sourced.\n"
+"case $SHELL in\n"
+" */bash)\n"
+" [ -z \"$BASH\" ] && exec $SHELL $0 \"$@\"\n"
+" set +o posix\n"
+" [ -f /etc/profile ] && . /etc/profile\n"
+" if [ -f $HOME/.bash_profile ]; then\n"
+" . $HOME/.bash_profile\n"
+" elif [ -f $HOME/.bash_login ]; then\n"
+" . $HOME/.bash_login\n"
+" elif [ -f $HOME/.profile ]; then\n"
+" . $HOME/.profile\n"
+" fi\n"
+" ;;\n"
+" */zsh)\n"
+" [ -z \"$ZSH_NAME\" ] && exec $SHELL $0 \"$@\"\n"
+" emulate -R zsh\n"
+" [ -d /etc/zsh ] && zdir=/etc/zsh || zdir=/etc\n"
+" zhome=${ZDOTDIR:-$HOME}\n"
+" # zshenv is always sourced automatically.\n"
+" [ -f $zdir/zprofile ] && . $zdir/zprofile\n"
+" [ -f $zhome/.zprofile ] && . $zhome/.zprofile\n"
+" [ -f $zdir/zlogin ] && . $zdir/zlogin\n"
+" [ -f $zhome/.zlogin ] && . $zhome/.zlogin\n"
+" setopt shwordsplit noextendedglob\n"
+" ;;\n"
+" */csh|*/tcsh)\n"
+" # [t]cshrc is always sourced automatically.\n"
+" # Note that sourcing csh.login after .cshrc is non-standard.\n"
+" xsess_tmp=";
+static const char def_session2[] =
+"\n"
+" $SHELL -c \"if (-f /etc/csh.login) source /etc/csh.login; if (-f ~/.login) source ~/.login; /bin/sh -c export -p >! $xsess_tmp\"\n"
+" . $xsess_tmp\n"
+" rm -f $xsess_tmp\n"
+" ;;\n"
+" *) # Plain sh, ksh, and anything we don't know.\n"
+" [ -f /etc/profile ] && . /etc/profile\n"
+" [ -f $HOME/.profile ] && . $HOME/.profile\n"
+" ;;\n"
+"esac\n"
+"# invoke global X session script\n"
+". /etc/X11/Xsession\n";
+
+static const char def_background[] =
+"[Desktop0]\n"
+"BackgroundMode=Flat\n"
+"BlendBalance=100\n"
+"BlendMode=NoBlending\n"
+"ChangeInterval=60\n"
+"Color1=0,0,200\n"
+"Color2=192,192,192\n"
+"CurrentWallpaper=0\n"
+"LastChange=0\n"
+"MinOptimizationDepth=1\n"
+"MultiWallpaperMode=NoMulti\n"
+"Pattern=fish\n"
+"Program=\n"
+"ReverseBlending=false\n"
+"UseSHM=false\n"
+"Wallpaper=isadora.png\n"
+"WallpaperList=\n"
+"WallpaperMode=Scaled\n";
+
+static char *
+prepName( const char *fn )
+{
+ const char *tname;
+ char *nname;
+
+ tname = strrchr( fn, '/' );
+ ASPrintf( &nname, "%s/%s", newdir, tname ? tname + 1 : fn );
+ displace( nname );
+ return nname;
+}
+
+static FILE *
+Create( const char *fn, int mode )
+{
+ char *nname;
+ FILE *f;
+
+ nname = prepName( fn );
+ if (!(f = fopen( nname, "w" ))) {
+ fprintf( stderr, "Cannot create %s\n", nname );
+ exit( 1 );
+ }
+ chmod( nname, mode );
+ free( nname );
+ return f;
+}
+
+static void
+WriteOut( const char *fn, int mode, time_t stamp, const char *buf, size_t len )
+{
+ char *nname;
+ int fd;
+ struct utimbuf utim;
+
+ nname = prepName( fn );
+ if ((fd = creat( nname, mode )) < 0) {
+ fprintf( stderr, "Cannot create %s\n", nname );
+ exit( 1 );
+ }
+ write( fd, buf, len );
+ close( fd );
+ if (stamp) {
+ utim.actime = utim.modtime = stamp;
+ utime( nname, &utim );
+ }
+ free( nname );
+}
+
+
+/* returns static array! */
+static const char *
+resect( const char *sec, const char *name )
+{
+ static char sname[64];
+ char *p;
+
+ if ((p = strrchr( sec, '-' ))) {
+ sprintf( sname, "%.*s-%s", p - sec, sec, name );
+ return sname;
+ } else
+ return name;
+}
+
+static int
+inNewDir( const char *name )
+{
+ return !memcmp( name, TDMCONF "/", sizeof(TDMCONF) );
+}
+
+static int
+inList( StrList *sp, const char *s )
+{
+ for (; sp; sp = sp->next)
+ if (!strcmp( sp->str, s ))
+ return 1;
+ return 0;
+}
+
+static void
+addStr( StrList **sp, const char *s )
+{
+ for (; *sp; sp = &(*sp)->next)
+ if (!strcmp( (*sp)->str, s ))
+ return;
+ *sp = mcalloc( sizeof(**sp) );
+ ASPrintf( (char **)&(*sp)->str, "%s", s );
+}
+
+StrList *aflist, *uflist, *eflist, *cflist, *lflist;
+
+/* file is part of new config */
+static void
+addedFile( const char *fn )
+{
+ addStr( &aflist, fn );
+}
+
+/* file from old config was parsed */
+static void
+usedFile( const char *fn )
+{
+ addStr( &uflist, fn );
+}
+
+/* file from old config was copied with slight modifications */
+static void
+editedFile( const char *fn )
+{
+ addStr( &eflist, fn );
+}
+
+/* file from old config was copied verbatim */
+static void
+copiedFile( const char *fn )
+{
+ addStr( &cflist, fn );
+}
+
+/* file from old config is still being used */
+static void
+linkedFile( const char *fn )
+{
+ addStr( &lflist, fn );
+}
+
+/*
+ * XXX this stuff is highly borked. it does not handle collisions at all.
+ */
+static int
+copyfile( Entry *ce, const char *tname, int mode, int (*proc)( File * ) )
+{
+ const char *tptr;
+ char *nname;
+ File file;
+ int rt;
+
+ if (!*ce->value)
+ return 1;
+
+ tptr = strrchr( tname, '/' );
+ ASPrintf( &nname, TDMCONF "/%s", tptr ? tptr + 1 : tname );
+ if (inList( cflist, ce->value ) ||
+ inList( eflist, ce->value ) ||
+ inList( lflist, ce->value ))
+ {
+ rt = 1;
+ goto doret;
+ }
+ if (!readFile( &file, ce->value )) {
+ fprintf( stderr, "Warning: cannot copy file %s\n", ce->value );
+ rt = 0;
+ } else {
+ if (!proc || !proc( &file )) {
+ if (!use_destdir && !strcmp( ce->value, nname ))
+ linkedFile( nname );
+ else {
+ struct stat st;
+ stat( ce->value, &st );
+ WriteOut( nname, mode, st.st_mtime, file.buf, file.eof - file.buf );
+ copiedFile( ce->value );
+ }
+ } else {
+ WriteOut( nname, mode, 0, file.buf, file.eof - file.buf );
+ editedFile( ce->value );
+ }
+ if (strcmp( ce->value, nname ) && inNewDir( ce->value ) && !use_destdir)
+ displace( ce->value );
+ addedFile( nname );
+ rt = 1;
+ }
+ doret:
+ ce->value = nname;
+ return rt;
+}
+
+static void
+dlinkfile( const char *name )
+{
+ File file;
+
+ if (!readFile( &file, name )) {
+ fprintf( stderr, "Warning: cannot read file %s\n", name );
+ return;
+ }
+ if (inNewDir( name ) && use_destdir) {
+ struct stat st;
+ stat( name, &st );
+ WriteOut( name, st.st_mode, st.st_mtime, file.buf, file.eof - file.buf );
+ copiedFile( name );
+ } else
+ linkedFile( name );
+ addedFile( name );
+}
+
+static void
+linkfile( Entry *ce )
+{
+ if (ce->written && *ce->value)
+ dlinkfile( ce->value );
+}
+
+static void
+writefile( const char *tname, int mode, const char *cont )
+{
+ WriteOut( tname, mode, 0, cont, strlen( cont ) );
+ addedFile( tname );
+}
+
+
+char *background;
+
+static void
+handBgCfg( Entry *ce, Section *cs ATTR_UNUSED )
+{
+ if (!ce->active) /* can be only the X-*-Greeter one */
+ writefile( def_BackgroundCfg, 0644,
+ background ? background : def_background );
+#if 0 /* risk of kcontrol clobbering the original file */
+ else if (old_confs)
+ linkfile( ce );
+#endif
+ else {
+ if (!copyfile( ce, ce->value, 0644, 0 )) {
+ if (!strcmp( cs->name, "X-*-Greeter" ))
+ writefile( def_BackgroundCfg, 0644, def_background );
+ ce->active = 0;
+ }
+ }
+}
+
+
+#ifdef HAVE_VTS
+static char *
+mem_mem( char *mem, int lmem, const char *smem, int lsmem )
+{
+ for (; lmem >= lsmem; mem++, lmem--)
+ if (!memcmp( mem, smem, lsmem ))
+ return mem + lsmem;
+ return 0;
+}
+
+static int maxTTY, TTYmask;
+
+static void
+getInitTab( void )
+{
+ File it;
+ char *p, *eol, *ep;
+ int tty;
+
+ if (maxTTY)
+ return;
+ if (!maxTTY) {
+ maxTTY = 6;
+ TTYmask = 0x3f;
+ }
+}
+#endif
+
+
+/* TODO: handle solaris' local_uid specs */
+
+static char *
+ReadWord( File *file, int EOFatEOL )
+{
+ char *wordp, *wordBuffer;
+ int quoted;
+ char c;
+
+ rest:
+ wordp = wordBuffer = file->cur;
+ mloop:
+ quoted = 0;
+ qloop:
+ if (file->cur == file->eof) {
+ doeow:
+ if (wordp == wordBuffer)
+ return 0;
+ retw:
+ *wordp = '\0';
+ return wordBuffer;
+ }
+ c = *file->cur++;
+ switch (c) {
+ case '#':
+ if (quoted)
+ break;
+ do {
+ if (file->cur == file->eof)
+ goto doeow;
+ c = *file->cur++;
+ } while (c != '\n');
+ case '\0':
+ case '\n':
+ if (EOFatEOL && !quoted) {
+ file->cur--;
+ goto doeow;
+ }
+ if (wordp != wordBuffer) {
+ file->cur--;
+ goto retw;
+ }
+ goto rest;
+ case ' ':
+ case '\t':
+ if (wordp != wordBuffer)
+ goto retw;
+ goto rest;
+ case '\\':
+ if (!quoted) {
+ quoted = 1;
+ goto qloop;
+ }
+ break;
+ }
+ *wordp++ = c;
+ goto mloop;
+}
+
+/* backslashes are double-escaped - for KConfig and for parseArgs */
+static const char *
+joinArgs( StrList *argv )
+{
+ StrList *av;
+ const char *s, *rs;
+ char *str;
+ int slen;
+
+ if (!argv)
+ return "";
+ for (slen = 0, av = argv; slen++, av; av = av->next) {
+ int nq = 0;
+ for (s = av->str; *s; s++, slen++)
+ if (isspace( *s ) || *s == '\'')
+ nq = 2;
+ else if (*s == '"')
+ slen += 2;
+ else if (*s == '\\')
+ slen += 3;
+ slen += nq;
+ }
+ rs = str = mmalloc( slen );
+ for (av = argv; av; av = av->next) {
+ int nq = 0;
+ for (s = av->str; *s; s++)
+ if (isspace( *s ) || *s == '\'')
+ nq = 2;
+ if (av != argv)
+ *str++ = ' ';
+ if (nq)
+ *str++ = '"';
+ for (s = av->str; *s; s++) {
+ if (*s == '\\')
+ *str++ = '\\';
+ if (*s == '"' || *s == '\\') {
+ *str++ = '\\';
+ *str++ = '\\';
+ }
+ *str++ = *s;
+ }
+ if (nq)
+ *str++ = '"';
+ }
+ *str = 0;
+ return rs;
+}
+
+# define dLocation 1
+# define dLocal 0
+# define dForeign 1
+
+static struct displayMatch {
+ const char *name;
+ int len, type;
+} displayTypes[] = {
+ { "local", 5, dLocal },
+ { "foreign", 7, dForeign },
+};
+
+static int
+parseDisplayType( const char *string, const char **atPos )
+{
+ struct displayMatch *d;
+
+ *atPos = 0;
+ for (d = displayTypes; d < displayTypes + as(displayTypes); d++) {
+ if (!memcmp( d->name, string, d->len ) &&
+ (!string[d->len] || string[d->len] == '@'))
+ {
+ if (string[d->len] == '@' && string[d->len + 1])
+ *atPos = string + d->len + 1;
+ return d->type;
+ }
+ }
+ return -1;
+}
+
+typedef struct serverEntry {
+ struct serverEntry *next;
+ const char *name, *class2, *console, *argvs, *arglvs;
+ StrList *argv, *arglv;
+ int type, reserve, vt;
+} ServerEntry;
+
+static void
+absorb_xservers( const char *sect ATTR_UNUSED, char **value )
+{
+ ServerEntry *se, *se1, *serverList, **serverPtr;
+ const char *word, *word2;
+ char *sdpys, *rdpys;
+ StrList **argp, **arglp, *ap, *ap2;
+ File file;
+ int nldpys = 0, nrdpys = 0, dpymask = 0;
+ int cpcmd, cpcmdl;
+#ifdef HAVE_VTS
+ int dn, cpvt, mtty;
+#endif
+
+ if (**value == '/') {
+ if (!readFile( &file, *value ))
+ return;
+ usedFile( *value );
+ } else {
+ file.buf = *value;
+ file.eof = *value + strlen( *value );
+ }
+ file.cur = file.buf;
+
+ serverPtr = &serverList;
+#ifdef HAVE_VTS
+ bustd:
+#endif
+ while ((word = ReadWord( &file, 0 ))) {
+ se = mcalloc( sizeof(*se) );
+ se->name = word;
+ if (!(word = ReadWord( &file, 1 )))
+ continue;
+ se->type = parseDisplayType( word, &se->console );
+ if (se->type < 0) {
+ se->class2 = word;
+ if (!(word = ReadWord( &file, 1 )))
+ continue;
+ se->type = parseDisplayType( word, &se->console );
+ if (se->type < 0) {
+ while (ReadWord( &file, 1 ));
+ continue;
+ }
+ }
+ word = ReadWord( &file, 1 );
+ if (word && !strcmp( word, "reserve" )) {
+ se->reserve = 1;
+ word = ReadWord( &file, 1 );
+ }
+ if (((se->type & dLocation) == dLocal) != (word != 0))
+ continue;
+ argp = &se->argv;
+ arglp = &se->arglv;
+ while (word) {
+#ifdef HAVE_VTS
+ if (word[0] == 'v' && word[1] == 't')
+ se->vt = atoi( word + 2 );
+ else if (!strcmp( word, "-crt" )) { /* SCO style */
+ if (!(word = ReadWord( &file, 1 )) ||
+ memcmp( word, "/dev/tty", 8 ))
+ goto bustd;
+ se->vt = atoi( word + 8 );
+ } else
+#endif
+ if (strcmp( word, se->name )) {
+ ap = mmalloc( sizeof(*ap) );
+ ap->str = word;
+ if (!strcmp( word, "-nolisten" )) {
+ if (!(word2 = ReadWord( &file, 1 )))
+ break;
+ ap2 = mmalloc( sizeof(*ap2) );
+ ap2->str = word2;
+ ap->next = ap2;
+ if (!strcmp( word2, "unix" )) {
+ *argp = ap;
+ argp = &ap2->next;
+ } else {
+ *arglp = ap;
+ arglp = &ap2->next;
+ }
+ } else {
+ *argp = ap;
+ argp = &ap->next;
+ }
+ }
+ word = ReadWord( &file, 1 );
+ }
+ *argp = *arglp = 0;
+ if ((se->type & dLocation) == dLocal) {
+ nldpys++;
+ dpymask |= 1 << atoi( se->name + 1 );
+ if (se->reserve)
+ nrdpys++;
+ }
+ *serverPtr = se;
+ serverPtr = &se->next;
+ }
+ *serverPtr = 0;
+
+#ifdef HAVE_VTS
+ /* don't copy only if all local displays are ordered and have a vt */
+ cpvt = 0;
+ getInitTab();
+ for (se = serverList, mtty = maxTTY; se; se = se->next)
+ if ((se->type & dLocation) == dLocal) {
+ mtty++;
+ if (se->vt != mtty) {
+ cpvt = 1;
+ break;
+ }
+ }
+#endif
+
+ for (se = serverList; se; se = se->next) {
+ se->argvs = joinArgs( se->argv );
+ se->arglvs = joinArgs( se->arglv );
+ }
+
+ se1 = 0, cpcmd = cpcmdl = 0;
+ for (se = serverList; se; se = se->next)
+ if ((se->type & dLocation) == dLocal) {
+ if (!se1)
+ se1 = se;
+ else {
+ if (strcmp( se1->argvs, se->argvs ))
+ cpcmd = 1;
+ if (strcmp( se1->arglvs, se->arglvs ))
+ cpcmdl = 1;
+ }
+ }
+ if (se1) {
+ putfqval( "X-:*-Core", "ServerCmd", se1->argvs );
+ putfqval( "X-:*-Core", "ServerArgsLocal", se1->arglvs );
+ for (se = serverList; se; se = se->next)
+ if ((se->type & dLocation) == dLocal) {
+ char sec[32];
+ sprintf( sec, "X-%s-Core", se->name );
+ if (cpcmd)
+ putfqval( sec, "ServerCmd", se->argvs );
+ if (cpcmdl)
+ putfqval( sec, "ServerArgsLocal", se->arglvs );
+#ifdef HAVE_VTS
+ if (cpvt && se->vt) {
+ char vt[8];
+ sprintf( vt, "%d", se->vt );
+ putfqval( sec, "ServerVT", vt );
+ }
+#else
+ if (se->console)
+ putfqval( sec, "ServerTTY", se->console );
+#endif
+ }
+ }
+
+ sdpys = rdpys = 0;
+ for (se = serverList; se; se = se->next)
+ StrCat( se->reserve ? &rdpys : &sdpys,
+ se->class2 ? ",%s_%s" : ",%s", se->name, se->class2 );
+
+#ifdef HAVE_VTS
+ /* add reserve dpys */
+ if (nldpys < 4 && nldpys && !nrdpys)
+ for (; nldpys < 4; nldpys++) {
+ for (dn = 0; dpymask & (1 << dn); dn++);
+ dpymask |= (1 << dn);
+ StrCat( &rdpys, ",:%d", dn );
+ }
+#endif
+
+ putfqval( "General", "StaticServers", sdpys ? sdpys + 1 : "" );
+ putfqval( "General", "ReserveServers", rdpys ? rdpys + 1 : "" );
+
+ if (**value == '/' && inNewDir( *value ) && !use_destdir)
+ displace( *value );
+}
+
+#ifdef HAVE_VTS
+static void
+upd_servervts( Entry *ce, Section *cs ATTR_UNUSED )
+{
+ if (!ce->active) { /* there is only the Global one */
+#ifdef __linux__ /* XXX actually, sysvinit */
+ getInitTab();
+ ASPrintf( (char **)&ce->value, "-%d", maxTTY + 1 );
+ ce->active = ce->written = 1;
+#endif
+ }
+}
+
+static void
+upd_consolettys( Entry *ce, Section *cs ATTR_UNUSED )
+{
+ if (!ce->active) { /* there is only the Global one */
+#ifdef __linux__ /* XXX actually, sysvinit */
+ char *buf;
+ int i;
+
+ getInitTab();
+ for (i = 0, buf = 0; i < 16; i++)
+ if (TTYmask & (1 << i))
+ StrCat( &buf, ",tty%d", i + 1 );
+ if (buf) {
+ ce->value = buf + 1;
+ ce->active = ce->written = 1;
+ }
+#endif
+ }
+}
+#endif
+
+#ifdef XDMCP
+static void
+cp_keyfile( Entry *ce, Section *cs ATTR_UNUSED )
+{
+ if (!ce->active) /* there is only the Global one */
+ return;
+ if (old_confs)
+ linkfile( ce );
+ else
+ if (!copyfile( ce, "tdmkeys", 0600, 0 ))
+ ce->active = 0;
+}
+
+static void
+mk_xaccess( Entry *ce, Section *cs ATTR_UNUSED )
+{
+ if (!ce->active) /* there is only the Global one */
+ writefile( def_Xaccess, 0644, def_xaccess );
+ else if (old_confs)
+ linkfile( ce );
+ else
+ copyfile( ce, "Xaccess", 0644, 0 ); /* don't handle error, it will disable Xdmcp automatically */
+}
+
+static void
+mk_willing( Entry *ce, Section *cs ATTR_UNUSED )
+{
+ char *fname;
+
+ if (!ce->active) /* there is only the Global one */
+ goto dflt;
+ else {
+ if (!(fname = strchr( ce->value, '/' )))
+ return; /* obviously in-line (or empty) */
+ if (old_scripts || inNewDir( fname ))
+ dlinkfile( fname );
+ else {
+ dflt:
+ ce->value = TDMCONF "/Xwilling";
+ ce->active = ce->written = 1;
+ writefile( ce->value, 0755, def_willing );
+ }
+ }
+}
+#endif
+
+/*
+static int
+edit_resources( File *file )
+{
+ // XXX remove any login*, chooser*, ... resources
+ return 0;
+}
+*/
+
+static void
+cp_resources( Entry *ce, Section *cs ATTR_UNUSED )
+{
+ if (!ce->active) /* the X-*-Greeter one */
+ return;
+ if (old_confs)
+ linkfile( ce );
+ else
+ if (!copyfile( ce, ce->value, 0644, 0/*edit_resources*/ ))
+ ce->active = 0;
+}
+
+static int
+delstr( File *fil, const char *pat )
+{
+ char *p, *pp, *bpp;
+ const char *pap, *paap;
+
+ *fil->eof = 0;
+ for (p = fil->buf; *p; p++) {
+ for (pp = p, pap = pat; ; ) {
+ if (!*pap) {
+ *p = '\n';
+ memcpy( p + 1, pp, fil->eof - pp + 1 );
+ fil->eof -= pp - p - 1;
+ return 1;
+ } else if (!memcmp( pap, "*/", 2 )) {
+ paap = pap += 2;
+ while (!isspace( *pap ))
+ pap++;
+ if (*pp != '/')
+ break;
+ for (;;)
+ for (bpp = ++pp; *pp != '/'; pp++)
+ if (!*pp || isspace( *pp ))
+ goto wbrk;
+ wbrk:
+ if ((pp - bpp != pap - paap) || memcmp( bpp, paap, pap - paap ))
+ break;
+ } else if (*pap == '\t') {
+ pap++;
+ while (*pp == ' ' || *pp == '\t')
+ pp++;
+ } else if (*pap == '[') {
+ pap++;
+ for (;;) {
+ if (!*pap) {
+ fprintf( stderr, "Internal error: unterminated char set\n" );
+ exit( 1 );
+ }
+ if (*pap == *pp) {
+ while (*++pap != ']')
+ if (!*pap) {
+ fprintf( stderr, "Internal error: unterminated char set\n" );
+ exit( 1 );
+ }
+ pap++;
+ pp++;
+ break;
+ }
+ if (*++pap == ']')
+ goto no;
+ }
+ } else {
+ if (*pap == '\n')
+ while (*pp == ' ' || *pp == '\t')
+ pp++;
+ if (*pap != *pp)
+ break;
+ pap++;
+ pp++;
+ }
+ }
+ no: ;
+ }
+ return 0;
+}
+
+/* XXX
+ the UseBackground voodoo will horribly fail, if multiple sections link
+ to the same Xsetup file
+*/
+
+static int mod_usebg;
+
+static int
+edit_setup( File *file )
+{
+ int chg =
+ delstr( file, "\n"
+ "(\n"
+ " PIDFILE=/var/run/tdmdesktop-$DISPLAY.pid\n"
+ " */tdmdesktop\t&\n"
+ " echo $! >$PIDFILE\n"
+ " wait $!\n"
+ " rm $PIDFILE\n"
+ ")\t&\n" ) |
+ delstr( file, "\n"
+ "*/tdmdesktop\t&\n" ) |
+ delstr( file, "\n"
+ "tdmdesktop\t&\n" ) |
+ delstr( file, "\n"
+ "tdmdesktop\n" );
+ putval( "UseBackground", chg ? "true" : "false" );
+ return chg;
+}
+
+static void
+mk_setup( Entry *ce, Section *cs )
+{
+ setsect( resect( cs->name, "Greeter" ) );
+ if (old_scripts || mixed_scripts) {
+ if (mod_usebg && *ce->value)
+ putval( "UseBackground", "false" );
+ linkfile( ce );
+ } else {
+ if (ce->active && inNewDir( ce->value )) {
+ if (mod_usebg)
+ copyfile( ce, ce->value, 0755, edit_setup );
+ else
+ linkfile( ce );
+ } else {
+ ce->value = TDMCONF "/Xsetup";
+ ce->active = ce->written = 1;
+ writefile( ce->value, 0755, def_setup );
+ }
+ }
+}
+
+static int
+edit_startup( File *file )
+{
+ int chg1 = 0, chg2 = 0;
+
+ if (mod_usebg &&
+ (delstr( file, "\n"
+ "PIDFILE=/var/run/tdmdesktop-$DISPLAY.pid\n"
+ "if [[] -f $PIDFILE ] ; then\n"
+ " kill `cat $PIDFILE`\n"
+ "fi\n" ) ||
+ delstr( file, "\n"
+ "PIDFILE=/var/run/tdmdesktop-$DISPLAY.pid\n"
+ "test -f $PIDFILE && kill `cat $PIDFILE`\n" )))
+ chg1 = 1;
+ if (oldver < 0x0203) {
+ chg2 =
+#ifdef _AIX
+ delstr( file, "\n"
+"# We create a pseudodevice for finger. (host:0 becomes [kx]dm/host_0)\n" );
+"# Without it, finger errors out with \"Can't stat /dev/host:0\".\n"
+"#\n"
+"if [[] -f /usr/lib/X11/xdm/sessreg ]; then\n"
+" devname=`echo $DISPLAY | /usr/bin/sed -e 's/[[]:\\.]/_/g' | /usr/bin/cut -c1-8`\n"
+" hostname=`echo $DISPLAY | /usr/bin/cut -d':' -f1`\n"
+"\n"
+" if [[] -z \"$devname\" ]; then\n"
+" devname=\"unknown\"\n"
+" fi\n"
+" if [[] ! -d /dev/[kx]dm ]; then\n"
+" /usr/bin/mkdir /dev/[kx]dm\n"
+" /usr/bin/chmod 755 /dev/[kx]dm\n"
+" fi\n"
+" /usr/bin/touch /dev/[kx]dm/$devname\n"
+" /usr/bin/chmod 644 /dev/[kx]dm/$devname\n"
+"\n"
+" if [[] -z \"$hostname\" ]; then\n"
+" exec /usr/lib/X11/xdm/sessreg -a -l [kx]dm/$devname $USER\n"
+" else\n"
+" exec /usr/lib/X11/xdm/sessreg -a -l [kx]dm/$devname -h $hostname $USER\n"
+" fi\n"
+"fi\n") |
+#else
+# ifdef BSD
+ delstr( file, "\n"
+"exec sessreg -a -l $DISPLAY -x */Xservers -u " _PATH_UTMP " $USER\n" ) |
+# endif
+#endif /* _AIX */
+ delstr( file, "\n"
+"exec sessreg -a -l $DISPLAY"
+#ifdef BSD
+" -x */Xservers"
+#endif
+" $USER\n" ) |
+ delstr( file, "\n"
+"exec sessreg -a -l $DISPLAY -u /var/run/utmp -x */Xservers $USER\n" );
+ putval( "UseSessReg", chg2 ? "true" : "false");
+ }
+ return chg1 | chg2;
+}
+
+static void
+mk_startup( Entry *ce, Section *cs )
+{
+ setsect( cs->name );
+ if (old_scripts || mixed_scripts)
+ linkfile( ce );
+ else {
+ if (ce->active && inNewDir( ce->value )) {
+ if (mod_usebg || oldver < 0x0203)
+ copyfile( ce, ce->value, 0755, edit_startup );
+ else
+ linkfile( ce );
+ } else {
+ ce->value = TDMCONF "/Xstartup";
+ ce->active = ce->written = 1;
+ writefile( ce->value, 0755, def_startup );
+ }
+ }
+}
+
+static int
+edit_reset( File *file )
+{
+ return
+#ifdef _AIX
+ delstr( file, "\n"
+"if [[] -f /usr/lib/X11/xdm/sessreg ]; then\n"
+" devname=`echo $DISPLAY | /usr/bin/sed -e 's/[[]:\\.]/_/g' | /usr/bin/cut -c1-8`\n"
+" exec /usr/lib/X11/xdm/sessreg -d -l [kx]dm/$devname $USER\n"
+"fi\n" ) |
+#else
+# ifdef BSD
+ delstr( file, "\n"
+"exec sessreg -d -l $DISPLAY -x */Xservers -u " _PATH_UTMP " $USER\n" ) |
+# endif
+#endif /* _AIX */
+ delstr( file, "\n"
+"exec sessreg -d -l $DISPLAY"
+# ifdef BSD
+" -x */Xservers"
+# endif
+" $USER\n" ) |
+ delstr( file, "\n"
+"exec sessreg -d -l $DISPLAY -u /var/run/utmp -x */Xservers $USER\n" );
+}
+
+static void
+mk_reset( Entry *ce, Section *cs ATTR_UNUSED )
+{
+ if (old_scripts || mixed_scripts)
+ linkfile( ce );
+ else {
+ if (ce->active && inNewDir( ce->value )) {
+ if (oldver < 0x0203)
+ copyfile( ce, ce->value, 0755, edit_reset );
+ else
+ linkfile( ce );
+ } else {
+ ce->value = TDMCONF "/Xreset";
+ ce->active = ce->written = 1;
+ writefile( ce->value, 0755, def_reset );
+ }
+ }
+}
+
+static void
+mk_session( Entry *ce, Section *cs ATTR_UNUSED )
+{
+ char *def_session;
+ const char *tmpf;
+
+ if ((old_scripts || (ce->active && inNewDir( ce->value ))) &&
+ oldver >= 0x202)
+ linkfile( ce );
+ else {
+ tmpf = locate( "mktemp" ) ?
+ "`mktemp /tmp/xsess-env-XXXXXX`" :
+ locate( "tempfile" ) ?
+ "`tempfile`" :
+ "$HOME/.xsession-env-$DISPLAY";
+ ASPrintf( &def_session, "%s%s%s", def_session1, tmpf, def_session2 );
+ ce->value = TDMCONF "/Xsession";
+ ce->active = ce->written = 1;
+ writefile( ce->value, 0755, def_session );
+ }
+}
+
+static void
+upd_language( Entry *ce, Section *cs ATTR_UNUSED )
+{
+ if (!strcmp( ce->value, "C" ))
+ ce->value = (char *)"en_US";
+}
+
+static void
+upd_guistyle( Entry *ce, Section *cs ATTR_UNUSED )
+{
+ if (!strcmp( ce->value, "Motif+" ))
+ ce->value = (char *)"MotifPlus";
+ else if (!strcmp( ce->value, "KDE" ))
+ ce->value = (char *)"Default";
+}
+
+static void
+upd_showusers( Entry *ce, Section *cs )
+{
+ if (!strcmp( ce->value, "All" ))
+ ce->value = (char *)"NotHidden";
+ else if (!strcmp( ce->value, "None" )) {
+ if (ce->active)
+ putfqval( cs->name, "UserList", "false" );
+ ce->value = (char *)"Selected";
+ ce->active = 0;
+ ce->written = 1;
+ }
+}
+
+static const char *defminuid, *defmaxuid;
+
+static void
+upd_minshowuid( Entry *ce, Section *cs ATTR_UNUSED )
+{
+ if (!ce->active) {
+ ce->value = defminuid;
+ ce->active = ce->written = 1;
+ }
+}
+
+static void
+upd_maxshowuid( Entry *ce, Section *cs ATTR_UNUSED )
+{
+ if (!ce->active) {
+ ce->value = defmaxuid;
+ ce->active = ce->written = 1;
+ }
+}
+
+static void
+upd_hiddenusers( Entry *ce, Section *cs ATTR_UNUSED )
+{
+ char *nv;
+ const char *msu, *pt, *et;
+ struct passwd *pw;
+ unsigned minuid, maxuid;
+ char nbuf[128];
+
+ if (!ce->active)
+ return;
+
+ msu = getfqval( cs->name, "MinShowUID", "0" );
+ sscanf( msu, "%u", &minuid );
+ msu = getfqval( cs->name, "MaxShowUID", "65535" );
+ sscanf( msu, "%u", &maxuid );
+
+ nv = 0;
+ pt = ce->value;
+ for (;;) {
+ et = strpbrk( pt, ";," );
+ if (et) {
+ memcpy( nbuf, pt, et - pt );
+ nbuf[et - pt] = 0;
+ } else
+ strcpy( nbuf, pt );
+ if ((pw = getpwnam( nbuf ))) {
+ if (!pw->pw_uid ||
+ (pw->pw_uid >= minuid && pw->pw_uid <= maxuid))
+ {
+ if (nv)
+ StrCat( &nv, ",%s", nbuf );
+ else
+ nv = mstrdup( nbuf );
+ }
+ }
+ if (!et)
+ break;
+ pt = et + 1;
+ }
+ ce->value = nv ? nv : "";
+}
+
+static void
+upd_forgingseed( Entry *ce, Section *cs ATTR_UNUSED )
+{
+ if (!ce->active) {
+ ASPrintf( (char **)&ce->value, "%d", time( 0 ) );
+ ce->active = ce->written = 1;
+ }
+}
+
+static void
+upd_fifodir( Entry *ce, Section *cs ATTR_UNUSED )
+{
+ const char *dir;
+ struct stat st;
+
+ if (use_destdir)
+ return;
+ dir = ce->active ? ce->value : def_FifoDir;
+ stat( dir, &st );
+ chmod( dir, st.st_mode | 0755 );
+}
+
+static void
+upd_datadir( Entry *ce, Section *cs ATTR_UNUSED )
+{
+ char *oldsts, *newsts;
+ const char *dir;
+
+ if (use_destdir)
+ return;
+ dir = ce->active ? ce->value : def_DataDir;
+ if (mkdirp( dir, 0755, "data", 0 ) && oldkde) {
+ ASPrintf( &oldsts, "%s/tdm/tdmsts", oldkde );
+ ASPrintf( &newsts, "%s/tdmsts", dir );
+ rename( oldsts, newsts );
+ }
+}
+
+static void
+CopyFile( const char *from, const char *to )
+{
+ File file;
+ int fd;
+
+ if (readFile( &file, from )) {
+ if ((fd = creat( to, 0644 )) >= 0) {
+ write( fd, file.buf, file.eof - file.buf );
+ close( fd );
+ }
+ freeBuf( &file );
+ }
+}
+
+static void
+upd_facedir( Entry *ce, Section *cs ATTR_UNUSED )
+{
+ char *oldpic, *newpic, *defpic, *rootpic;
+ const char *dir;
+ struct passwd *pw;
+
+ if (use_destdir)
+ return;
+ dir = ce->active ? ce->value : def_FaceDir;
+ if (mkdirp( dir, 0755, "user face", 0 )) {
+ ASPrintf( &defpic, "%s/.default.face.icon", dir );
+ ASPrintf( &rootpic, "%s/root.face.icon", dir );
+ if (oldkde) {
+ setpwent();
+ while ((pw = getpwent()))
+ if (strcmp( pw->pw_name, "root" )) {
+ ASPrintf( &oldpic, "%s/../apps/tdm/pics/users/%s.png",
+ oldkde, pw->pw_name );
+ ASPrintf( &newpic, "%s/%s.face.icon", dir, pw->pw_name );
+ rename( oldpic, newpic );
+ free( newpic );
+ free( oldpic );
+ }
+ endpwent();
+ ASPrintf( &oldpic, "%s/../apps/tdm/pics/users/default.png", oldkde );
+ if (!rename( oldpic, defpic ))
+ defpic = 0;
+ ASPrintf( &oldpic, "%s/../apps/tdm/pics/users/root.png", oldkde );
+ if (!rename( oldpic, rootpic ))
+ rootpic = 0;
+ }
+ if (defpic) {
+ ASPrintf( &oldpic, "%s/default1.png", facesrc );
+ CopyFile( oldpic, defpic );
+ }
+ if (rootpic) {
+ ASPrintf( &oldpic, "%s/root1.png", facesrc );
+ CopyFile( oldpic, rootpic );
+ }
+ }
+}
+
+CONF_GEN_ENTRIES
+
+static Sect *
+findSect( const char *name )
+{
+ const char *p;
+ int i;
+
+ p = strrchr( name, '-' );
+ if (!p)
+ p = name;
+ for (i = 0; i < as(allSects); i++)
+ if (!strcmp( allSects[i]->name, p ))
+ return allSects[i];
+ fprintf( stderr, "Internal error: unknown section %s\n", name );
+ exit( 1 );
+}
+
+static Ent *
+findEnt( Sect *sect, const char *key )
+{
+ int i;
+
+ for (i = 0; i < sect->nents; i++)
+ if (!strcmp( sect->ents[i].key, key ))
+ return sect->ents + i;
+ fprintf( stderr, "Internal error: unknown key %s in section %s\n",
+ key, sect->name );
+ exit( 1 );
+}
+
+
+/*
+ * defaults
+ */
+
+typedef struct DEnt {
+ const char *key;
+ const char *value;
+ int active;
+} DEnt;
+
+typedef struct DSect {
+ const char *name;
+ DEnt *ents;
+ int nents;
+ const char *comment;
+} DSect;
+
+CONF_GEN_EXAMPLE
+
+static void
+mkdefconf( void )
+{
+ Section *cs, **csp;
+ Entry *ce, **cep;
+ int sc, ec;
+
+ for (csp = &config, sc = 0; sc < as(dAllSects); csp = &(cs->next), sc++) {
+ cs = mcalloc( sizeof(*cs) );
+ *csp = cs;
+ cs->spec = findSect( dAllSects[sc].name );
+ cs->name = dAllSects[sc].name;
+ cs->comment = dAllSects[sc].comment;
+ for (cep = &(cs->ents), ec = 0; ec < dAllSects[sc].nents;
+ cep = &(ce->next), ec++)
+ {
+ ce = mcalloc( sizeof(*ce) );
+ *cep = ce;
+ ce->spec = findEnt( cs->spec, dAllSects[sc].ents[ec].key );
+ ce->value = dAllSects[sc].ents[ec].value;
+ ce->active = dAllSects[sc].ents[ec].active;
+ }
+ }
+}
+
+
+/*
+ * read rc file structure
+ */
+
+typedef struct REntry {
+ struct REntry *next;
+ const char *key;
+ char *value;
+} REntry;
+
+typedef struct RSection {
+ struct RSection *next;
+ const char *name;
+ REntry *ents;
+} RSection;
+
+static RSection *
+ReadConf( const char *fname )
+{
+ char *nstr;
+ char *s, *e, *st, *en, *ek, *sl;
+ RSection *rootsec = 0, *cursec;
+ REntry *curent;
+ int nlen;
+ int line, sectmoan;
+ File file;
+
+ if (!readFile( &file, fname ))
+ return 0;
+ usedFile( fname );
+
+ for (s = file.buf, line = 0, cursec = 0, sectmoan = 1; s < file.eof; s++) {
+ line++;
+
+ while ((s < file.eof) && isspace( *s ) && (*s != '\n'))
+ s++;
+
+ if ((s < file.eof) && ((*s == '\n') || (*s == '#'))) {
+ sktoeol:
+ while ((s < file.eof) && (*s != '\n'))
+ s++;
+ continue;
+ }
+ sl = s;
+
+ if (*s == '[') {
+ while ((s < file.eof) && (*s != '\n'))
+ s++;
+ e = s - 1;
+ while ((e > sl) && isspace( *e ))
+ e--;
+ if (*e != ']') {
+ fprintf( stderr, "Invalid section header at %s:%d\n",
+ fname, line );
+ continue;
+ }
+ sectmoan = 0;
+ nstr = sl + 1;
+ nlen = e - nstr;
+ for (cursec = rootsec; cursec; cursec = cursec->next)
+ if (!memcmp( nstr, cursec->name, nlen ) &&
+ !cursec->name[nlen])
+ {
+#if 0 /* not our business ... */
+ fprintf( stderr, "Warning: Multiple occurrences of section "
+ "[%.*s] in %s. Consider merging them.\n",
+ nlen, nstr, fname );
+#endif
+ goto secfnd;
+ }
+ cursec = mmalloc( sizeof(*cursec) );
+ ASPrintf( (char **)&cursec->name, "%.*s", nlen, nstr );
+ cursec->ents = 0;
+ cursec->next = rootsec;
+ rootsec = cursec;
+ secfnd:
+ continue;
+ }
+
+ if (!cursec) {
+ if (sectmoan) {
+ sectmoan = 0;
+ fprintf( stderr, "Entry outside any section at %s:%d",
+ fname, line );
+ }
+ goto sktoeol;
+ }
+
+ for (; (s < file.eof) && (*s != '\n'); s++)
+ if (*s == '=')
+ goto haveeq;
+ fprintf( stderr, "Invalid entry (missing '=') at %s:%d\n", fname, line );
+ continue;
+
+ haveeq:
+ for (ek = s - 1;; ek--) {
+ if (ek < sl) {
+ fprintf( stderr, "Invalid entry (empty key) at %s:%d\n",
+ fname, line );
+ goto sktoeol;
+ }
+ if (!isspace( *ek ))
+ break;
+ }
+
+ s++;
+ while ((s < file.eof) && isspace( *s ) && (*s != '\n'))
+ s++;
+ st = s;
+ while ((s < file.eof) && (*s != '\n'))
+ s++;
+ for (en = s - 1; en >= st && isspace( *en ); en--);
+
+ nstr = sl;
+ nlen = ek - sl + 1;
+ for (curent = cursec->ents; curent; curent = curent->next)
+ if (!memcmp( nstr, curent->key, nlen ) &&
+ !curent->key[nlen]) {
+ fprintf( stderr, "Multiple occurrences of key '%s' in section "
+ "[%s] of %s.\n", curent->key, cursec->name, fname );
+ goto keyfnd;
+ }
+ curent = mmalloc( sizeof(*curent) );
+ ASPrintf( (char **)&curent->key, "%.*s", nlen, nstr );
+ ASPrintf( (char **)&curent->value, "%.*s", en - st + 1, st );
+ curent->next = cursec->ents;
+ cursec->ents = curent;
+ keyfnd:
+ continue;
+ }
+ return rootsec;
+}
+
+
+static int
+mergeKdmRcOld( const char *path )
+{
+ char *p;
+ struct stat st;
+
+ ASPrintf( &p, "%s/tdmrc", path );
+ if (stat( p, &st )) {
+ free( p );
+ return 0;
+ }
+ printf( "Information: ignoring old tdmrc %s from kde < 2.2\n", p );
+ free( p );
+ return 1;
+}
+
+typedef struct {
+ const char *sect, *key, *def;
+ int (*cond)( void );
+} FDefs;
+
+static void
+applydefs( FDefs *chgdef, int ndefs, const char *path )
+{
+ char *p;
+ int i;
+
+ for (i = 0; i < ndefs; i++)
+ if (!getfqval( chgdef[i].sect, chgdef[i].key, 0 ) &&
+ (!chgdef[i].cond || chgdef[i].cond()))
+ {
+ ASPrintf( &p, chgdef[i].def, path );
+ putfqval( chgdef[i].sect, chgdef[i].key, p );
+ free( p );
+ }
+}
+
+#ifdef XDMCP
+static FDefs tdmdefs_all[] = {
+{ "Xdmcp", "Xaccess", "%s/tdm/Xaccess", 0 },
+{ "Xdmcp", "Willing", "", 0 },
+};
+#endif
+
+static FDefs tdmdefs_eq_22[] = {
+{ "General", "PidFile", "/var/run/xdm.pid", 0 },
+{ "X-*-Core", "Setup", "%s/tdm/Xsetup", 0 },
+{ "X-*-Core", "Startup", "%s/tdm/Xstartup", 0 },
+{ "X-*-Core", "Reset", "%s/tdm/Xreset", 0 },
+{ "X-*-Core", "Session", "%s/tdm/Xsession", 0 },
+};
+
+#ifdef XDMCP
+static int
+if_xdmcp (void)
+{
+ return isTrue( getfqval( "Xdmcp", "Enable", "true" ) );
+}
+
+static FDefs tdmdefs_le_30[] = {
+{ "Xdmcp", "KeyFile", "%s/tdm/tdmkeys", if_xdmcp },
+};
+#endif
+
+/* HACK: misused by is22conf() below */
+static FDefs tdmdefs_ge_30[] = {
+{ "X-*-Core", "Setup", "", 0 },
+{ "X-*-Core", "Startup", "", 0 },
+{ "X-*-Core", "Reset", "", 0 },
+{ "X-*-Core", "Session", XBINDIR "/xterm -ls -T", 0 },
+};
+
+static int
+if_usebg (void)
+{
+ return isTrue( getfqval( "X-*-Greeter", "UseBackground", "true" ) );
+}
+
+static FDefs tdmdefs_ge_31[] = {
+{ "X-*-Greeter","BackgroundCfg","%s/tdm/backgroundrc", if_usebg },
+};
+
+static int
+is22conf( const char *path )
+{
+ char *p;
+ const char *val;
+ int i, sl;
+
+ sl = ASPrintf( &p, "%s/tdm/", path );
+ /* safe bet, i guess ... */
+ for (i = 0; i < 4; i++) {
+ val = getfqval( "X-*-Core", tdmdefs_ge_30[i].key, 0 );
+ if (val && !memcmp( val, p, sl )) {
+ free( p );
+ return 0;
+ }
+ }
+ free( p );
+ return 1;
+}
+
+typedef struct KUpdEnt {
+ const char *okey, *nsec, *nkey;
+ void (*func)( const char *sect, char **value );
+} KUpdEnt;
+
+typedef struct KUpdSec {
+ const char *osec;
+ KUpdEnt *ents;
+ int nents;
+} KUpdSec;
+
+#ifdef XDMCP
+static void
+P_EnableChooser( const char *sect ATTR_UNUSED, char **value )
+{
+ *value = (char *)(isTrue( *value ) ? "DefaultLocal" : "LocalOnly");
+}
+#endif
+
+static void
+P_UseLilo( const char *sect ATTR_UNUSED, char **value )
+{
+ *value = (char *)(isTrue( *value ) ? "Lilo" : "None");
+}
+
+CONF_GEN_KMERGE
+
+static int
+mergeKdmRcNewer( const char *path )
+{
+ char *p;
+ const char *cp, *sec, *key;
+ RSection *rootsect, *cs;
+ REntry *ce;
+ int i, j;
+ static char sname[64];
+
+ ASPrintf( &p, "%s/tdm/tdmrc", path );
+ if (!(rootsect = ReadConf( p ))) {
+ free( p );
+ return 0;
+ }
+ printf( "Information: reading current tdmrc %s (from kde >= 2.2.x)\n", p );
+ free( p );
+
+ for (cs = rootsect; cs; cs = cs->next) {
+ if (!strcmp( cs->name, "Desktop0" )) {
+ background = mstrdup( "[Desktop0]\n" );
+ for (ce = cs->ents; ce; ce = ce->next)
+ StrCat( &background, "%s=%s\n", ce->key, ce->value );
+ } else {
+ cp = strrchr( cs->name, '-' );
+ if (!cp)
+ cp = cs->name;
+ else if (cs->name[0] != 'X' || cs->name[1] != '-')
+ goto dropsec;
+ for (i = 0; i < as(kupsects); i++)
+ if (!strcmp( cp, kupsects[i].osec )) {
+ for (ce = cs->ents; ce; ce = ce->next) {
+ for (j = 0; j < kupsects[i].nents; j++)
+ if (!strcmp( ce->key, kupsects[i].ents[j].okey )) {
+ if (kupsects[i].ents[j].nsec == (char *)-1) {
+ kupsects[i].ents[j].func( 0, &ce->value );
+ goto gotkey;
+ }
+ if (!kupsects[i].ents[j].nsec)
+ sec = cs->name;
+ else {
+ sec = sname;
+ sprintf( sname, "%.*s-%s", cp - cs->name, cs->name,
+ kupsects[i].ents[j].nsec );
+ }
+ if (!kupsects[i].ents[j].nkey)
+ key = ce->key;
+ else
+ key = kupsects[i].ents[j].nkey;
+ if (kupsects[i].ents[j].func)
+ kupsects[i].ents[j].func( sec, &ce->value );
+ putfqval( sec, key, ce->value );
+ goto gotkey;
+ }
+ printf( "Information: dropping key %s from section [%s]\n",
+ ce->key, cs->name );
+ gotkey: ;
+ }
+ goto gotsec;
+ }
+ dropsec:
+ printf( "Information: dropping section [%s]\n", cs->name );
+ gotsec: ;
+ }
+ }
+
+#ifdef XDMCP
+ applydefs( tdmdefs_all, as(tdmdefs_all), path );
+#endif
+ if (!*(cp = getfqval( "General", "ConfigVersion", "" ))) { /* < 3.1 */
+ mod_usebg = 1;
+ if (is22conf( path )) {
+ /* work around 2.2.x defaults borkedness */
+ applydefs( tdmdefs_eq_22, as(tdmdefs_eq_22), path );
+ printf( "Information: current tdmrc is from kde 2.2\n" );
+ } else {
+ applydefs( tdmdefs_ge_30, as(tdmdefs_ge_30), path );
+ printf( "Information: current tdmrc is from kde 3.0\n" );
+ }
+#ifdef XDMCP
+ /* work around minor <= 3.0.x defaults borkedness */
+ applydefs( tdmdefs_le_30, as(tdmdefs_le_30), path );
+#endif
+ } else {
+ int ma, mi;
+ sscanf( cp, "%d.%d", &ma, &mi );
+ oldver = (ma << 8) | mi;
+ printf( "Information: current tdmrc is from kde >= 3.1 (config version %d.%d)\n", ma, mi );
+ applydefs( tdmdefs_ge_30, as(tdmdefs_ge_30), path );
+ applydefs( tdmdefs_ge_31, as(tdmdefs_ge_31), path );
+ }
+
+ return 1;
+}
+
+
+typedef struct XResEnt {
+ const char *xname;
+ const char *ksec, *kname;
+ void (*func)( const char *sect, char **value );
+} XResEnt;
+
+static void
+handleXdmVal( const char *dpy, const char *key, char *value,
+ const XResEnt *ents, int nents )
+{
+ const char *kname;
+ int i;
+ char knameb[80], sname[80];
+
+ for (i = 0; i < nents; i++)
+ if (!strcmp( key, ents[i].xname ) ||
+ (key[0] == toupper( ents[i].xname[0] ) &&
+ !strcmp( key + 1, ents[i].xname + 1 )))
+ {
+ if (ents[i].ksec == (char *)-1) {
+ ents[i].func (0, &value);
+ break;
+ }
+ sprintf( sname, ents[i].ksec, dpy );
+ if (ents[i].kname)
+ kname = ents[i].kname;
+ else {
+ kname = knameb;
+ sprintf( knameb, "%c%s",
+ toupper( ents[i].xname[0] ), ents[i].xname + 1 );
+ }
+ if (ents[i].func)
+ ents[i].func( sname, &value );
+ putfqval( sname, kname, value );
+ break;
+ }
+}
+
+static void
+P_List( const char *sect ATTR_UNUSED, char **value )
+{
+ int is, d, s;
+ char *st;
+
+ for (st = *value, is = d = s = 0; st[s]; s++)
+ if (st[s] == ' ' || st[s] == '\t') {
+ if (!is)
+ st[d++] = ',';
+ is = 1;
+ } else {
+ st[d++] = st[s];
+ is = 0;
+ }
+ st[d] = 0;
+}
+
+static void
+P_authDir( const char *sect ATTR_UNUSED, char **value )
+{
+ int l;
+
+ l = strlen( *value );
+ if (l < 4) {
+ *value = 0;
+ return;
+ }
+ if ((*value)[l-1] == '/')
+ (*value)[--l] = 0;
+ if (!strncmp( *value, "/tmp/", 5 ) ||
+ !strncmp( *value, "/var/tmp/", 9 ))
+ {
+ printf( "Warning: Resetting inappropriate value %s for AuthDir to default\n",
+ *value );
+ *value = 0;
+ return;
+ }
+ if ((l >= 4 && !strcmp( *value + l - 4, "/tmp" )) ||
+ (l >= 6 && !strcmp( *value + l - 6, "/xauth" )) ||
+ (l >= 8 && !strcmp( *value + l - 8, "/authdir" )) ||
+ (l >= 10 && !strcmp( *value + l - 10, "/authfiles" )))
+ return;
+ ASPrintf( value, "%s/authdir", *value );
+}
+
+static void
+P_openDelay( const char *sect, char **value )
+{
+ putfqval( sect, "ServerTimeout", *value );
+}
+
+static void
+P_noPassUsers( const char *sect, char **value ATTR_UNUSED )
+{
+ putfqval( sect, "NoPassEnable", "true" );
+}
+
+static void
+P_autoUser( const char *sect, char **value ATTR_UNUSED )
+{
+ putfqval( sect, "AutoLoginEnable", "true" );
+}
+
+#ifdef XDMCP
+static void
+P_requestPort( const char *sect, char **value )
+{
+ if (!strcmp( *value, "0" )) {
+ *value = 0;
+ putfqval( sect, "Enable", "false" );
+ } else
+ putfqval( sect, "Enable", "true" );
+}
+#endif
+
+static int tdmrcmode = 0644;
+
+static void
+P_autoPass( const char *sect ATTR_UNUSED, char **value ATTR_UNUSED )
+{
+ tdmrcmode = 0600;
+}
+
+CONF_GEN_XMERGE
+
+static XrmQuark XrmQString, empty = NULLQUARK;
+
+static Bool
+DumpEntry( XrmDatabase *db ATTR_UNUSED,
+ XrmBindingList bindings,
+ XrmQuarkList quarks,
+ XrmRepresentation *type,
+ XrmValuePtr value,
+ XPointer data ATTR_UNUSED )
+{
+ const char *dpy, *key;
+ int el, hasu;
+ char dpybuf[80];
+
+ if (*type != XrmQString)
+ return False;
+ if (*bindings == XrmBindLoosely ||
+ strcmp( XrmQuarkToString (*quarks), "DisplayManager" ))
+ return False;
+ bindings++, quarks++;
+ if (!*quarks)
+ return False;
+ if (*bindings != XrmBindLoosely && !quarks[1]) { /* DM.foo */
+ key = XrmQuarkToString (*quarks);
+ handleXdmVal( 0, key, value->addr, globents, as(globents) );
+ return False;
+ } else if (*bindings == XrmBindLoosely && !quarks[1]) { /* DM*bar */
+ dpy = "*";
+ key = XrmQuarkToString (*quarks);
+ } else if (*bindings != XrmBindLoosely && quarks[1] &&
+ *bindings != XrmBindLoosely && !quarks[2])
+ { /* DM.foo.bar */
+ dpy = dpybuf + 4;
+ strcpy( dpybuf + 4, XrmQuarkToString (*quarks) );
+ for (hasu = 0, el = 4; dpybuf[el]; el++)
+ if (dpybuf[el] == '_')
+ hasu = 1;
+ if (!hasu/* && isupper (dpy[0])*/) {
+ dpy = dpybuf;
+ memcpy( dpybuf, "*:*_", 4 );
+ } else {
+ for (; --el >= 0; )
+ if (dpybuf[el] == '_') {
+ dpybuf[el] = ':';
+ for (; --el >= 4; )
+ if (dpybuf[el] == '_')
+ dpybuf[el] = '.';
+ break;
+ }
+ }
+ key = XrmQuarkToString (quarks[1]);
+ } else
+ return False;
+ handleXdmVal( dpy, key, value->addr, dpyents, as(dpyents) );
+ return False;
+}
+
+static FDefs xdmdefs[] = {
+#ifdef XDMCP
+{ "Xdmcp", "Xaccess", "%s/Xaccess", 0 },
+{ "Xdmcp", "Willing", "", 0 },
+#endif
+{ "X-*-Core", "Setup", "", 0 },
+{ "X-*-Core", "Startup", "", 0 },
+{ "X-*-Core", "Reset", "", 0 },
+{ "X-*-Core", "Session", "", 0 },
+};
+
+static int
+mergeXdmCfg( const char *path )
+{
+ char *p;
+ XrmDatabase db;
+
+ ASPrintf( &p, "%s/xdm-config", path );
+ if ((db = XrmGetFileDatabase( p ))) {
+ printf( "Information: reading current xdm config file %s\n", p );
+ usedFile( p );
+ free( p );
+ XrmEnumerateDatabase( db, &empty, &empty, XrmEnumAllLevels,
+ DumpEntry, (XPointer)0 );
+ applydefs( xdmdefs, as(xdmdefs), path );
+ mod_usebg = 1;
+ return 1;
+ }
+ free( p );
+ return 0;
+}
+
+static void
+fwrapprintf( FILE *f, const char *msg, ... )
+{
+ char *txt, *ftxt, *line;
+ va_list ap;
+ int col, lword, fspace;
+
+ va_start( ap, msg );
+ VASPrintf( &txt, msg, ap );
+ va_end( ap );
+ ftxt = 0;
+ for (line = txt, col = 0, lword = fspace = -1; line[col]; ) {
+ if (line[col] == '\n') {
+ StrCat( &ftxt, "%.*s", ++col, line );
+ line += col;
+ col = 0;
+ lword = fspace = -1;
+ continue;
+ } else if (line[col] == ' ') {
+ if (lword >= 0) {
+ fspace = col;
+ lword = -1;
+ }
+ } else {
+ if (lword < 0)
+ lword = col;
+ if (col >= 78 && fspace >= 0) {
+ StrCat( &ftxt, "%.*s\n", fspace, line );
+ line += lword;
+ col -= lword;
+ lword = 0;
+ fspace = -1;
+ }
+ }
+ col++;
+ }
+ free( txt );
+ fputs( ftxt, f );
+ free( ftxt );
+}
+
+
+static const char *oldkdes[] = {
+ KDE_CONFDIR,
+ "/opt/trinity/share/config",
+ "/usr/local/trinity/share/config",
+
+ "/opt/kde/share/config",
+ "/usr/local/kde/share/config",
+ "/usr/local/share/config",
+ "/usr/share/config",
+
+ "/opt/kde2/share/config",
+ "/usr/local/kde2/share/config",
+};
+
+static const char *oldxdms[] = {
+ "/etc/X11/xdm",
+ XLIBDIR "/xdm",
+};
+
+int main( int argc, char **argv )
+{
+ const char **where;
+ char *newtdmrc;
+ FILE *f;
+ StrList *fp;
+ Section *cs;
+ Entry *ce, **cep;
+ int i, ap, newer, locals, foreigns;
+ int no_old_xdm = 0, no_old_kde = 0;
+ struct stat st;
+ char *nname;
+
+ for (ap = 1; ap < argc; ap++) {
+ if (!strcmp( argv[ap], "--help" )) {
+ printf(
+"gentdmconf - generate configuration files for tdm\n"
+"\n"
+"If an older xdm/tdm configuration is found, its config files are \"absorbed\";\n"
+"if it lives in the new target directory, its scripts are reused (and possibly\n"
+"modified) as well, otherwise the scripts are ignored and default scripts are\n"
+"installed.\n"
+"\n"
+"options:\n"
+" --in /path/to/new/tdm-config-dir\n"
+" In which directory to put the new configuration. You can use this\n"
+" to support a $(DESTDIR), but not to change the final location of\n"
+" the installation - the paths inside the files are not affected.\n"
+" Default is " TDMCONF ".\n"
+" --old-xdm /path/to/old/xdm-dir\n"
+" Where to look for the config files of an xdm/older tdm.\n"
+" Default is to scan /etc/X11/tdm, $XLIBDIR/tdm, /etc/X11/xdm,\n"
+" $XLIBDIR/xdm; there in turn look for tdm-config and xdm-config.\n"
+" Note that you possibly need to use --no-old-kde to make this take effect.\n"
+" --old-kde /path/to/old/kde-config-dir\n"
+" Where to look for the tdmrc of an older tdm.\n"
+" Default is to scan " KDE_CONFDIR " and\n"
+" {/usr,/usr/local,{/opt,/usr/local}/{trinity,kde,kde2,kde1}}/share/config.\n"
+" --no-old\n"
+" Don't look at older xdm/tdm configurations, just create default config.\n"
+" --no-old-xdm\n"
+" Don't look at older xdm configurations.\n"
+" --no-old-kde\n"
+" Don't look at older tdm configurations.\n"
+" --old-scripts\n"
+" Directly use all scripts from the older xdm/tdm configuration.\n"
+" --no-old-scripts\n"
+" Don't use scripts from the older xdm/tdm configuration even if it lives\n"
+" in the new target directory.\n"
+" --old-confs\n"
+" Directly use all ancillary config files from the older xdm/tdm\n"
+" configuration. This is usually a bad idea.\n"
+" --no-backup\n"
+" Overwrite/delete old config files instead of backing them up.\n"
+" --no-in-notice\n"
+" Don't put the notice about --in being used into the generated README.\n"
+);
+ exit( 0 );
+ }
+ if (!strcmp( argv[ap], "--no-old" )) {
+ no_old = 1;
+ continue;
+ }
+ if (!strcmp( argv[ap], "--old-scripts" )) {
+ old_scripts = 1;
+ continue;
+ }
+ if (!strcmp( argv[ap], "--no-old-scripts" )) {
+ no_old_scripts = 1;
+ continue;
+ }
+ if (!strcmp( argv[ap], "--old-confs" )) {
+ old_confs = 1;
+ continue;
+ }
+ if (!strcmp( argv[ap], "--no-old-xdm" )) {
+ no_old_xdm = 1;
+ continue;
+ }
+ if (!strcmp( argv[ap], "--no-old-kde" )) {
+ no_old_kde = 1;
+ continue;
+ }
+ if (!strcmp( argv[ap], "--no-backup" )) {
+ no_backup = 1;
+ continue;
+ }
+ if (!strcmp( argv[ap], "--no-in-notice" )) {
+ no_in_notice = 1;
+ continue;
+ }
+ where = 0;
+ if (!strcmp( argv[ap], "--in" ))
+ where = &newdir;
+ else if (!strcmp( argv[ap], "--old-xdm" ))
+ where = &oldxdm;
+ else if (!strcmp( argv[ap], "--old-kde" ))
+ where = &oldkde;
+ else if (!strcmp( argv[ap], "--face-src" ))
+ where = &facesrc;
+ else {
+ fprintf( stderr, "Unknown command line option '%s', try --help\n", argv[ap] );
+ exit( 1 );
+ }
+ if (ap + 1 == argc || argv[ap + 1][0] == '-') {
+ fprintf( stderr, "Missing argument to option '%s', try --help\n", argv[ap] );
+ exit( 1 );
+ }
+ *where = argv[++ap];
+ }
+ if (memcmp( newdir, TDMCONF, sizeof(TDMCONF) ))
+ use_destdir = 1;
+
+ if (!mkdirp( newdir, 0755, "target", 1 ))
+ exit( 1 );
+
+ mkdefconf();
+ newer = 0;
+ if (no_old) {
+ DIR *dir;
+ if ((dir = opendir( newdir ))) {
+ struct dirent *ent;
+ char bn[PATH_MAX];
+ while ((ent = readdir( dir ))) {
+ int l;
+ if (!strcmp( ent->d_name, "." ) || !strcmp( ent->d_name, ".." ))
+ continue;
+ l = sprintf( bn, "%s/%s", newdir, ent->d_name ); /* cannot overflow (kernel would not allow the creation of a longer path) */
+ if (!stat( bn, &st ) && !S_ISREG( st.st_mode ))
+ continue;
+ if (no_backup || !memcmp( bn + l - 4, ".bak", 5 ))
+ unlink( bn );
+ else
+ displace( bn );
+ }
+ closedir( dir );
+ }
+ } else {
+ if (oldkde) {
+ if (!(newer = mergeKdmRcNewer( oldkde )) && !mergeKdmRcOld( oldkde ))
+ fprintf( stderr,
+ "Cannot read old tdmrc at specified location\n" );
+ } else if (!no_old_kde) {
+ for (i = 0; i < as(oldkdes); i++) {
+ if ((newer = mergeKdmRcNewer( oldkdes[i] )) ||
+ mergeKdmRcOld( oldkdes[i] )) {
+ oldkde = oldkdes[i];
+ break;
+ }
+ }
+ }
+ if (!newer && !no_old_xdm) {
+ XrmInitialize();
+ XrmQString = XrmPermStringToQuark( "String" );
+ if (oldxdm) {
+ if (!mergeXdmCfg( oldxdm ))
+ fprintf( stderr,
+ "Cannot read old tdm-config/xdm-config at specified location\n" );
+ } else
+ for (i = 0; i < as(oldxdms); i++)
+ if (mergeXdmCfg( oldxdms[i] )) {
+ oldxdm = oldxdms[i];
+ break;
+ }
+ } else
+ oldxdm = 0;
+ }
+ if (no_old_scripts)
+ goto no_old_s;
+ if (!old_scripts) {
+ locals = foreigns = 0;
+ for (cs = config; cs; cs = cs->next)
+ if (!strcmp( cs->spec->name, "-Core" )) {
+ for (ce = cs->ents; ce; ce = ce->next)
+ if (ce->active &&
+ (!strcmp( ce->spec->key, "Setup" ) ||
+ !strcmp( ce->spec->key, "Startup" ) ||
+ !strcmp( ce->spec->key, "Reset" )))
+ {
+ if (inNewDir( ce->value ))
+ locals = 1;
+ else
+ foreigns = 1;
+ }
+ }
+ if (foreigns) {
+ if (locals) {
+ fprintf( stderr,
+ "Warning: both local and foreign scripts referenced. "
+ "Won't touch any.\n" );
+ mixed_scripts = 1;
+ } else {
+ no_old_s:
+ for (cs = config; cs; cs = cs->next) {
+ if (!strcmp( cs->spec->name, "Xdmcp" )) {
+ for (ce = cs->ents; ce; ce = ce->next)
+ if (!strcmp( ce->spec->key, "Willing" ))
+ ce->active = ce->written = 0;
+ } else if (!strcmp( cs->spec->name, "-Core" )) {
+ for (cep = &cs->ents; (ce = *cep); ) {
+ if (ce->active &&
+ (!strcmp( ce->spec->key, "Setup" ) ||
+ !strcmp( ce->spec->key, "Startup" ) ||
+ !strcmp( ce->spec->key, "Reset" ) ||
+ !strcmp( ce->spec->key, "Session" )))
+ {
+ if (!memcmp( cs->name, "X-*-", 4 ))
+ ce->active = ce->written = 0;
+ else {
+ *cep = ce->next;
+ free( ce );
+ continue;
+ }
+ }
+ cep = &ce->next;
+ }
+ }
+ }
+ }
+ }
+ }
+#ifdef __linux__
+ if (!stat( "/etc/debian_version", &st )) { /* debian */
+ defminuid = "1000";
+ defmaxuid = "29999";
+ } else if (!stat( "/usr/portage", &st )) { /* gentoo */
+ defminuid = "1000";
+ defmaxuid = "65000";
+ } else if (!stat( "/etc/mandrake-release", &st )) { /* mandrake - check before redhat! */
+ defminuid = "500";
+ defmaxuid = "65000";
+ } else if (!stat( "/etc/redhat-release", &st )) { /* redhat */
+ defminuid = "100";
+ defmaxuid = "65000";
+ } else /* if (!stat( "/etc/SuSE-release", &st )) */ { /* suse */
+ defminuid = "500";
+ defmaxuid = "65000";
+ }
+#else
+ defminuid = "1000";
+ defmaxuid = "65000";
+#endif
+ for (i = 0; i < CONF_MAX_PRIO; i++)
+ for (cs = config; cs; cs = cs->next)
+ for (ce = cs->ents; ce; ce = ce->next)
+ if (ce->spec->func && i == ce->spec->prio)
+ ce->spec->func( ce, cs );
+ ASPrintf( &newtdmrc, "%s/tdmrc", newdir );
+ f = Create( newtdmrc, tdmrcmode );
+ wrconf( f );
+ fclose( f );
+
+ ASPrintf( &nname, "%s/README", newdir );
+ f = Create( nname, 0644 );
+ fprintf( f,
+"This automatically generated configuration consists of the following files:\n" );
+ fprintf( f, "- " TDMCONF "/tdmrc\n" );
+ for (fp = aflist; fp; fp = fp->next)
+ fprintf( f, "- %s\n", fp->str );
+ if (use_destdir && !no_in_notice)
+ fwrapprintf( f,
+"All files destined for " TDMCONF " were actually saved in %s; "
+"this config won't be workable until moved in place.\n", newdir );
+ if (uflist || eflist || cflist || lflist) {
+ fprintf( f,
+"\n"
+"This config was derived from existing files. As the used algorithms are\n"
+"pretty dumb, it may be broken.\n" );
+ if (uflist) {
+ fprintf( f,
+"Information from these files was extracted:\n" );
+ for (fp = uflist; fp; fp = fp->next)
+ fprintf( f, "- %s\n", fp->str );
+ }
+ if (lflist) {
+ fprintf( f,
+"These files were directly incorporated:\n" );
+ for (fp = lflist; fp; fp = fp->next)
+ fprintf( f, "- %s\n", fp->str );
+ }
+ if (cflist) {
+ fprintf( f,
+"These files were copied verbatim:\n" );
+ for (fp = cflist; fp; fp = fp->next)
+ fprintf( f, "- %s\n", fp->str );
+ }
+ if (eflist) {
+ fprintf( f,
+"These files were copied with modifications:\n" );
+ for (fp = eflist; fp; fp = fp->next)
+ fprintf( f, "- %s\n", fp->str );
+ }
+ if (!no_backup && !use_destdir)
+ fprintf( f,
+"Old files that would have been overwritten were renamed to <oldname>.bak.\n" );
+ }
+ fprintf( f,
+"\nTry 'gentdmconf --help' if you want to generate another configuration.\n"
+"\nYou may delete this README.\n" );
+ fclose( f );
+
+ return 0;
+}
diff --git a/tdm/kfrontend/kchooser.cpp b/tdm/kfrontend/kchooser.cpp
new file mode 100644
index 00000000..00b08cd3
--- /dev/null
+++ b/tdm/kfrontend/kchooser.cpp
@@ -0,0 +1,227 @@
+/*
+
+chooser widget for TDM
+
+Copyright (C) 2002-2003 Oswald Buddenhagen <ossi@kde.org>
+based on the chooser (C) 1999 by Harald Hoyer <Harald.Hoyer@RedHat.de>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#include <config.h>
+
+#ifdef XDMCP
+
+#include "kchooser.h"
+#include "kconsole.h"
+#include "tdmconfig.h"
+#include "tdm_greet.h"
+
+#include <klocale.h>
+
+#include <tqlayout.h>
+#include <tqlabel.h>
+#include <tqpushbutton.h>
+#include <tqpopupmenu.h>
+#include <tqsocketnotifier.h>
+#include <tqlistview.h>
+#include <tqlineedit.h>
+
+#include <stdlib.h> // for free()
+
+class ChooserListViewItem : public TQListViewItem {
+ public:
+ ChooserListViewItem( TQListView* parent, int _id, const TQString& nam, const TQString& sts )
+ : TQListViewItem( parent, nam, sts ) { id = _id; };
+
+ int id;
+};
+
+
+ChooserDlg::ChooserDlg()
+ : inherited()
+{
+ completeMenu( LOGIN_REMOTE_ONLY, ex_greet, i18n("&Local Login"), ALT+Key_L );
+
+ TQBoxLayout *vbox = new TQVBoxLayout( this, 10, 10 );
+
+ TQLabel *title = new TQLabel( i18n("XDMCP Host Menu"), this );
+ title->setAlignment( AlignCenter );
+ vbox->addWidget( title );
+
+ host_view = new TQListView( this, "hosts" );
+ host_view->addColumn( i18n("Hostname") );
+ host_view->setColumnWidth( 0, fontMetrics().width( "login.crap.net" ) );
+ host_view->addColumn( i18n("Status") );
+ host_view->setMinimumWidth( fontMetrics().width( "login.crap.com Display not authorized to connect this server" ) );
+ host_view->setResizeMode( TQListView::LastColumn );
+ host_view->setAllColumnsShowFocus( true );
+ vbox->addWidget( host_view );
+
+ iline = new TQLineEdit( this );
+ iline->setEnabled( TRUE );
+ TQLabel *itxt = new TQLabel( iline, i18n("Hos&t:"), this );
+ TQPushButton *addButton = new TQPushButton( i18n("A&dd"), this );
+ connect( addButton, TQT_SIGNAL(clicked()), TQT_SLOT(addHostname()) );
+ TQBoxLayout *hibox = new TQHBoxLayout( vbox, 10 );
+ hibox->addWidget( itxt );
+ hibox->addWidget( iline );
+ hibox->addWidget( addButton );
+
+ // Buttons
+ TQPushButton *acceptButton = new TQPushButton( i18n("&Accept"), this );
+ acceptButton->setDefault( true );
+ TQPushButton *pingButton = new TQPushButton( i18n("&Refresh"), this );
+
+ TQBoxLayout *hbox = new TQHBoxLayout( vbox, 20 );
+ hbox->addWidget( acceptButton );
+ hbox->addWidget( pingButton );
+ hbox->addStretch( 1 );
+
+ if (optMenu) {
+ TQPushButton *menuButton = new TQPushButton( i18n("&Menu"), this );
+ menuButton->setPopup( optMenu );
+ hbox->addWidget( menuButton );
+ hbox->addStretch( 1 );
+ }
+
+// TQPushButton *helpButton = new TQPushButton( i18n("&Help"), this );
+// hbox->addWidget( helpButton );
+
+#ifdef WITH_TDM_XCONSOLE
+ if (consoleView)
+ vbox->addWidget( consoleView );
+#endif
+
+ sn = new TQSocketNotifier( rfd, TQSocketNotifier::Read, TQT_TQOBJECT(this) );
+ connect( sn, TQT_SIGNAL(activated( int )), TQT_SLOT(slotReadPipe()) );
+
+ connect( pingButton, TQT_SIGNAL(clicked()), TQT_SLOT(pingHosts()) );
+ connect( acceptButton, TQT_SIGNAL(clicked()), TQT_SLOT(accept()) );
+// connect( helpButton, TQT_SIGNAL(clicked()), TQT_SLOT(slotHelp()) );
+ connect( host_view, TQT_SIGNAL(doubleClicked(TQListViewItem *)), TQT_SLOT(accept()) );
+
+ adjustGeometry();
+}
+
+/*
+void ChooserDlg::slotHelp()
+{
+ KMessageBox::information(0,
+ i18n("Choose a host, you want to work on,\n"
+ "in the list or add one.\n\n"
+ "After this box, you must press cancel\n"
+ "in the Host Menu to enter a host. :("));
+ iline->setFocus();
+}
+*/
+
+void ChooserDlg::addHostname()
+{
+ if (!iline->text().isEmpty()) {
+ GSendInt( G_Ch_RegisterHost );
+ GSendStr( iline->text().latin1() );
+ iline->clear();
+ }
+}
+
+void ChooserDlg::pingHosts()
+{
+ GSendInt( G_Ch_Refresh );
+}
+
+void ChooserDlg::accept()
+{
+ if (focusWidget() == iline) {
+ if (!iline->text().isEmpty()) {
+ GSendInt( G_Ch_DirectChoice );
+ GSendStr( iline->text().latin1() );
+ iline->clear();
+ }
+ return;
+ } else /*if (focusWidget() == host_view)*/ {
+ TQListViewItem *item = host_view->currentItem();
+ if (item) {
+ GSendInt( G_Ready );
+ GSendInt( ((ChooserListViewItem *)item)->id );
+ ::exit( EX_NORMAL );
+ }
+ }
+}
+
+void ChooserDlg::reject()
+{
+}
+
+TQString ChooserDlg::recvStr()
+{
+ char *arr = GRecvStr();
+ if (arr) {
+ TQString str = TQString::fromLatin1( arr );
+ free( arr );
+ return str;
+ } else
+ return i18n("<unknown>");
+}
+
+TQListViewItem *ChooserDlg::findItem( int id )
+{
+ TQListViewItem *itm;
+ for (TQListViewItemIterator it( host_view ); (itm = it.current()); ++it)
+ if (((ChooserListViewItem *)itm)->id == id)
+ return itm;
+ return 0;
+}
+
+void ChooserDlg::slotReadPipe()
+{
+ int id;
+ TQString nam, sts;
+
+ int cmd = GRecvInt();
+ switch (cmd) {
+ case G_Ch_AddHost:
+ case G_Ch_ChangeHost:
+ id = GRecvInt();
+ nam = recvStr();
+ sts = recvStr();
+ GRecvInt(); /* swallow willing for now */
+ if (cmd == G_Ch_AddHost)
+ host_view->insertItem(
+ new ChooserListViewItem( host_view, id, nam, sts ) );
+ else {
+ TQListViewItem *itm = findItem( id );
+ itm->setText( 0, nam );
+ itm->setText( 1, sts );
+ }
+ break;
+ case G_Ch_RemoveHost:
+ delete findItem( GRecvInt() );
+ break;
+ case G_Ch_BadHost:
+ KFMsgBox::box( this, TQMessageBox::Warning, i18n("Unknown host %1").arg( recvStr() ) );
+ break;
+ case G_Ch_Exit:
+ done( ex_exit );
+ break;
+ default: /* XXX huuh ...? */
+ break;
+ }
+}
+
+#include "kchooser.moc"
+
+#endif
diff --git a/tdm/kfrontend/kchooser.h b/tdm/kfrontend/kchooser.h
new file mode 100644
index 00000000..fcf14b1e
--- /dev/null
+++ b/tdm/kfrontend/kchooser.h
@@ -0,0 +1,59 @@
+/*
+
+chooser widget for TDM
+
+Copyright (C) 2002-2003 Oswald Buddenhagen <ossi@kde.org>
+based on the chooser (C) 1999 by Harald Hoyer <Harald.Hoyer@RedHat.de>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#ifndef KCHOOSER_H
+#define KCHOOSER_H
+
+#include "kgdialog.h"
+
+class TQSocketNotifier;
+class TQPopupMenu;
+class TQLineEdit;
+class TQListView;
+class TQListViewItem;
+
+class ChooserDlg : public KGDialog {
+ Q_OBJECT
+ typedef KGDialog inherited;
+
+ public:
+ ChooserDlg();
+
+ public slots:
+ void slotReadPipe();
+ void addHostname();
+// void slotHelp();
+ void pingHosts();
+ void accept();
+ void reject();
+
+ private:
+ TQString recvStr();
+ TQListViewItem *findItem( int id );
+
+ TQListView *host_view;
+ TQLineEdit *iline;
+ TQSocketNotifier *sn;
+};
+
+#endif /* KCHOOSER_H */
diff --git a/tdm/kfrontend/kconsole.cpp b/tdm/kfrontend/kconsole.cpp
new file mode 100644
index 00000000..834507bd
--- /dev/null
+++ b/tdm/kfrontend/kconsole.cpp
@@ -0,0 +1,183 @@
+/*
+
+xconsole widget for TDM
+
+Copyright (C) 2002-2003 Oswald Buddenhagen <ossi@kde.org>
+
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#include <config.h>
+
+#ifdef WITH_TDM_XCONSOLE
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/ioctl.h>
+
+#ifdef HAVE_TERMIOS_H
+/* for HP-UX (some versions) the extern C is needed, and for other
+ platforms it doesn't hurt */
+extern "C" {
+#include <termios.h>
+}
+#endif
+#if !defined(__osf__)
+#ifdef HAVE_TERMIO_H
+/* needed at least on AIX */
+#include <termio.h>
+#endif
+#endif
+
+#if defined (_HPUX_SOURCE)
+#define _TERMIOS_INCLUDED
+#include <bsdtty.h>
+#endif
+
+
+#include "kconsole.h"
+#include "tdmconfig.h"
+#include "tdm_greet.h"
+
+#include <klocale.h>
+#include <kpty.h>
+
+#include <tqsocketnotifier.h>
+
+KConsole::KConsole( TQWidget *_parent )
+ : inherited( _parent )
+ , pty( 0 )
+ , notifier( 0 )
+ , fd( -1 )
+{
+ setReadOnly( true );
+ setWordWrap( NoWrap );
+ setTextFormat( PlainText );
+
+ if (!OpenConsole())
+ append( i18n("Cannot open console") );
+}
+
+KConsole::~KConsole()
+{
+ CloseConsole();
+}
+
+int
+KConsole::OpenConsole()
+{
+#ifdef TIOCCONS
+ static const char on = 1;
+#endif
+
+ if (*_logSource) {
+ if ((fd = open( _logSource, O_RDONLY | O_NONBLOCK )) >= 0)
+ goto gotcon;
+ LogError( "Cannot open log source %s, "
+ "falling back to /dev/console.\n", _logSource );
+ }
+
+ pty = new KPty;
+ if (!pty->open()) {
+ delete pty;
+ pty = 0;
+ return 0;
+ }
+
+#ifdef TIOCCONS
+ if (ioctl( pty->slaveFd(), TIOCCONS, &on ) < 0) {
+ perror( "ioctl TIOCCONS" );
+ delete pty;
+ pty = 0;
+ return 0;
+ }
+#else
+ int consfd;
+ if ((consfd = open( "/dev/console", O_RDONLY )) < 0) {
+ perror( "opening /dev/console" );
+ delete pty;
+ pty = 0;
+ return 0;
+ }
+ if (ioctl( consfd, SRIOCSREDIR, slave_fd ) < 0) {
+ perror( "ioctl SRIOCSREDIR" );
+ ::close( consfd );
+ delete pty;
+ pty = 0;
+ return 0;
+ }
+ ::close( consfd );
+#endif
+ fd = pty->masterFd();
+
+ gotcon:
+ notifier = new TQSocketNotifier( fd, TQSocketNotifier::Read, this );
+ connect( notifier, TQT_SIGNAL(activated( int )), TQT_SLOT(slotData()) );
+ return 1;
+}
+
+void
+KConsole::CloseConsole()
+{
+ delete notifier;
+ notifier = 0;
+ if (pty) {
+ delete pty;
+ pty = 0;
+ } else
+ ::close( fd );
+ fd = -1;
+}
+
+void
+KConsole::slotData()
+{
+ int n;
+ char buffer[1024];
+
+ if ((n = read( fd, buffer, sizeof(buffer) )) <= 0) {
+ CloseConsole();
+ if (!n)
+ if (!OpenConsole())
+ append( i18n("\n*** Cannot open console log source ***") );
+ } else {
+ bool as = !verticalScrollBar()->isVisible() ||
+ (verticalScrollBar()->value() ==
+ verticalScrollBar()->maxValue());
+ TQString str( TQString::fromLocal8Bit( buffer, n ).remove( '\r' ) );
+ int pos, opos;
+ for (opos = 0; (pos = str.find( '\n', opos )) >= 0; opos = pos + 1) {
+ if (paragraphs() == 100)
+ removeParagraph( 0 );
+ if (!leftover.isEmpty()) {
+ append( leftover + str.mid( opos, pos - opos ) );
+ leftover = TQString::null;
+ } else
+ append( str.mid( opos, pos - opos ) );
+ }
+ leftover += str.mid( opos );
+ if (as)
+ scrollToBottom();
+ }
+}
+
+#include "kconsole.moc"
+
+#endif
diff --git a/tdm/kfrontend/kconsole.h b/tdm/kfrontend/kconsole.h
new file mode 100644
index 00000000..2b3e2aac
--- /dev/null
+++ b/tdm/kfrontend/kconsole.h
@@ -0,0 +1,53 @@
+/*
+
+xconsole widget for TDM
+
+Copyright (C) 2002-2003 Oswald Buddenhagen <ossi@kde.org>
+
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#ifndef KCONSOLE_H
+#define KCONSOLE_H
+
+#include <tqtextedit.h>
+
+class TQSocketNotifier;
+class KPty;
+
+class KConsole : public TQTextEdit {
+ Q_OBJECT
+ typedef TQTextEdit inherited;
+
+ public:
+ KConsole( TQWidget *_parent = 0 );
+ ~KConsole();
+
+ private slots:
+ void slotData();
+
+ private:
+ int OpenConsole();
+ void CloseConsole();
+
+ KPty *pty;
+ TQSocketNotifier *notifier;
+ TQString leftover;
+ int fd;
+};
+
+#endif // KCONSOLE_H
diff --git a/tdm/kfrontend/kfdialog.cpp b/tdm/kfrontend/kfdialog.cpp
new file mode 100644
index 00000000..98b5773c
--- /dev/null
+++ b/tdm/kfrontend/kfdialog.cpp
@@ -0,0 +1,182 @@
+/*
+
+Dialog class that handles input focus in absence of a wm
+
+Copyright (C) 1997, 1998 Steffen Hansen <hansen@kde.org>
+Copyright (C) 2000-2003 Oswald Buddenhagen <ossi@kde.org>
+
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#include "kfdialog.h"
+#include "tdmconfig.h"
+
+#include <klocale.h>
+#include <kpushbutton.h>
+#include <kstdguiitem.h>
+#include <kglobalsettings.h>
+
+#include <tqlabel.h>
+#include <tqlayout.h>
+#include <tqapplication.h>
+#include <tqcursor.h>
+
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+
+extern bool has_twin;
+extern bool is_themed;
+
+FDialog::FDialog( TQWidget *parent, bool framed )
+ : inherited( parent, 0, true, (framed&&has_twin)?0:WX11BypassWM ), winFrame(NULL), m_wmTitle(has_twin)
+{
+ if (framed) {
+ // Signal that we do not want any window controls to be shown at all
+ Atom kde_wm_system_modal_notification;
+ kde_wm_system_modal_notification = XInternAtom(qt_xdisplay(), "_KDE_WM_MODAL_SYS_NOTIFICATION", False);
+ XChangeProperty(qt_xdisplay(), winId(), kde_wm_system_modal_notification, XA_INTEGER, 32, PropModeReplace, (unsigned char *) "TRUE", 1L);
+ }
+
+ if (framed) {
+ winFrame = new TQFrame( this, 0, TQt::WNoAutoErase );
+ if (m_wmTitle)
+ winFrame->setFrameStyle( TQFrame::NoFrame );
+ else
+ winFrame->setFrameStyle( TQFrame::WinPanel | TQFrame::Raised );
+ winFrame->setLineWidth( 2 );
+ } else
+ winFrame = 0;
+
+ setCaption(TDM_LOGIN_SCREEN_BASE_TITLE);
+
+ if (framed) {
+ if (m_wmTitle) setFixedSize(sizeHint());
+ }
+}
+
+void
+FDialog::resizeEvent( TQResizeEvent *e )
+{
+ inherited::resizeEvent( e );
+ if (winFrame) {
+ winFrame->resize( size() );
+ winFrame->erase();
+ if (m_wmTitle) setFixedSize(sizeHint());
+ }
+}
+
+void
+FDialog::adjustGeometry()
+{
+ TQDesktopWidget *dsk = tqApp->desktop();
+
+ if (_greeterScreen < 0)
+ _greeterScreen = _greeterScreen == -2 ?
+ dsk->screenNumber( TQPoint( dsk->width() - 1, 0 ) ) :
+ dsk->screenNumber( TQPoint( 0, 0 ) );
+
+ TQRect scr = dsk->screenGeometry( _greeterScreen );
+ if (!winFrame)
+ setFixedSize( scr.size() );
+ else {
+ setMaximumSize( scr.size() * .9 );
+ adjustSize();
+ }
+
+ if (parentWidget())
+ return;
+
+ TQRect grt( rect() );
+ if (winFrame) {
+ unsigned x = 50, y = 50;
+ sscanf( _greeterPos, "%u,%u", &x, &y );
+ grt.moveCenter( TQPoint( scr.x() + scr.width() * x / 100,
+ scr.y() + scr.height() * y / 100 ) );
+ int di;
+ if ((di = scr.right() - grt.right()) < 0)
+ grt.moveBy( di, 0 );
+ if ((di = scr.left() - grt.left()) > 0)
+ grt.moveBy( di, 0 );
+ if ((di = scr.bottom() - grt.bottom()) < 0)
+ grt.moveBy( 0, di );
+ if ((di = scr.top() - grt.top()) > 0)
+ grt.moveBy( 0, di );
+ setGeometry( grt );
+ }
+
+ if (dsk->screenNumber( TQCursor::pos() ) != _greeterScreen)
+ TQCursor::setPos( grt.center() );
+}
+
+struct WinList {
+ struct WinList *next;
+ TQWidget *win;
+};
+
+int
+FDialog::exec()
+{
+ static WinList *wins;
+ WinList *win;
+
+ win = new WinList;
+ win->win = this;
+ win->next = wins;
+ wins = win;
+ show();
+ setActiveWindow();
+ inherited::exec();
+ hide();
+ wins = win->next;
+ delete win;
+ if (wins)
+ wins->win->setActiveWindow();
+ return result();
+}
+
+void
+FDialog::box( TQWidget *parent, TQMessageBox::Icon type, const TQString &text )
+{
+ KFMsgBox dlg( parent, type, text.stripWhiteSpace() );
+ dlg.exec();
+}
+
+KFMsgBox::KFMsgBox( TQWidget *parent, TQMessageBox::Icon type, const TQString &text )
+ : inherited( parent, !is_themed )
+{
+ if (type == TQMessageBox::NoIcon) setCaption(TDM_LOGIN_SCREEN_BASE_TITLE);
+ if (type == TQMessageBox::Question) setCaption(TDM_LOGIN_SCREEN_BASE_TITLE + " - " + i18n("Question"));
+ if (type == TQMessageBox::Information) setCaption(TDM_LOGIN_SCREEN_BASE_TITLE + " - " + i18n("Information"));
+ if (type == TQMessageBox::Warning) setCaption(TDM_LOGIN_SCREEN_BASE_TITLE + " - " + i18n("Warning"));
+ if (type == TQMessageBox::Critical) setCaption(TDM_LOGIN_SCREEN_BASE_TITLE + " - " + i18n("Error"));
+
+ TQLabel *label1 = new TQLabel( this );
+ label1->setPixmap( TQMessageBox::standardIcon( type ) );
+ TQLabel *label2 = new TQLabel( text, this );
+ TQRect d = KGlobalSettings::desktopGeometry(this);
+ if ( label2->fontMetrics().size( 0, text).width() > d.width() * 3 / 5)
+ label2->setAlignment(TQt::WordBreak | TQt::AlignAuto );
+ KPushButton *button = new KPushButton( KStdGuiItem::ok(), this );
+ button->setDefault( true );
+ button->setSizePolicy( TQSizePolicy( TQSizePolicy::Preferred, TQSizePolicy::Preferred ) );
+ connect( button, TQT_SIGNAL(clicked()), TQT_SLOT(accept()) );
+
+ TQGridLayout *grid = new TQGridLayout( this, 2, 2, 10 );
+ grid->addWidget( label1, 0, 0, Qt::AlignCenter );
+ grid->addWidget( label2, 0, 1, Qt::AlignCenter );
+ grid->addMultiCellWidget( button, 1,1, 0,1, Qt::AlignCenter );
+}
diff --git a/tdm/kfrontend/kfdialog.h b/tdm/kfrontend/kfdialog.h
new file mode 100644
index 00000000..851d9a2d
--- /dev/null
+++ b/tdm/kfrontend/kfdialog.h
@@ -0,0 +1,65 @@
+/*
+
+Dialog class that handles input focus in absence of a wm
+
+Copyright (C) 1997, 1998 Steffen Hansen <hansen@kde.org>
+Copyright (C) 2000-2003 Oswald Buddenhagen <ossi@kde.org>
+
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#define TDM_LOGIN_SCREEN_BASE_TITLE i18n("Login to TDE")
+
+#ifndef FDIALOG_H
+#define FDIALOG_H
+
+#include <tqdialog.h>
+#include <tqmessagebox.h>
+
+class TQFrame;
+
+class FDialog : public TQDialog {
+ typedef TQDialog inherited;
+
+ public:
+ FDialog( TQWidget *parent = 0, bool framed = true );
+ virtual int exec();
+
+ static void box( TQWidget *parent, TQMessageBox::Icon type,
+ const TQString &text );
+#define errorbox TQMessageBox::Critical
+#define sorrybox TQMessageBox::Warning
+#define infobox TQMessageBox::Information
+ void MsgBox( TQMessageBox::Icon typ, const TQString &msg ) { box( this, typ, msg ); }
+
+ protected:
+ virtual void resizeEvent( TQResizeEvent *e );
+ void adjustGeometry();
+
+ private:
+ TQFrame *winFrame;
+ bool m_wmTitle;
+};
+
+class KFMsgBox : public FDialog {
+ typedef FDialog inherited;
+
+ public:
+ KFMsgBox( TQWidget *parent, TQMessageBox::Icon type, const TQString &text );
+};
+
+#endif /* FDIALOG_H */
diff --git a/tdm/kfrontend/kgapp.cpp b/tdm/kfrontend/kgapp.cpp
new file mode 100644
index 00000000..5ad52dda
--- /dev/null
+++ b/tdm/kfrontend/kgapp.cpp
@@ -0,0 +1,469 @@
+/*
+
+Greeter module for xdm
+
+Copyright (C) 1997, 1998 Steffen Hansen <hansen@kde.org>
+Copyright (C) 2000-2003 Oswald Buddenhagen <ossi@kde.org>
+
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#include <config.h>
+
+#include "tdm_greet.h"
+#include "tdmshutdown.h"
+#include "tdmconfig.h"
+#include "kgapp.h"
+#include "kgreeter.h"
+#ifdef XDMCP
+# include "kchooser.h"
+#endif
+#include "sakdlg.h"
+
+#include <kprocess.h>
+#include <kcmdlineargs.h>
+#include <kcrash.h>
+#include <kstandarddirs.h>
+#include <ksimpleconfig.h>
+#include <klocale.h>
+#include <kdebug.h>
+#ifdef WITH_XRANDR
+#include <libkrandr/libkrandr.h>
+#endif
+
+#include <tqtimer.h>
+#include <tqstring.h>
+#include <tqcursor.h>
+#include <tqpalette.h>
+
+#include <stdlib.h> // free(), exit()
+#include <unistd.h> // alarm()
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/keysym.h>
+#include <X11/cursorfont.h>
+
+#ifdef HAVE_XCOMPOSITE
+#include <X11/extensions/Xrender.h>
+#include <X11/extensions/Xcomposite.h>
+#endif
+
+#include <pwd.h>
+
+bool argb_visual_available = false;
+bool has_twin = false;
+bool is_themed = false;
+bool trinity_desktop_lock_use_sak = TRUE;
+
+static int
+ignoreXError( Display *dpy ATTR_UNUSED, XErrorEvent *event ATTR_UNUSED )
+{
+ return 0;
+}
+
+extern "C" {
+
+static void
+sigAlarm( int )
+{
+ exit( EX_RESERVER_DPY );
+}
+
+}
+
+GreeterApp::GreeterApp()
+{
+ pingInterval = _isLocal ? 0 : _pingInterval;
+ if (pingInterval) {
+ struct sigaction sa;
+ sigemptyset( &sa.sa_mask );
+ sa.sa_flags = 0;
+ sa.sa_handler = sigAlarm;
+ sigaction( SIGALRM, &sa, 0 );
+ alarm( pingInterval * 70 ); // sic! give the "proper" pinger enough time
+ startTimer( pingInterval * 60000 );
+ }
+}
+
+GreeterApp::GreeterApp(Display *dpy, Qt::HANDLE visual, Qt::HANDLE colormap) : KApplication(dpy, visual, colormap)
+{
+ pingInterval = _isLocal ? 0 : _pingInterval;
+ if (pingInterval) {
+ struct sigaction sa;
+ sigemptyset( &sa.sa_mask );
+ sa.sa_flags = 0;
+ sa.sa_handler = sigAlarm;
+ sigaction( SIGALRM, &sa, 0 );
+ alarm( pingInterval * 70 ); // sic! give the "proper" pinger enough time
+ startTimer( pingInterval * 60000 );
+ }
+}
+
+void
+GreeterApp::timerEvent( TQTimerEvent * )
+{
+ alarm( 0 );
+ if (!PingServer( qt_xdisplay() ))
+ ::exit( EX_RESERVER_DPY );
+ alarm( pingInterval * 70 ); // sic! give the "proper" pinger enough time
+}
+
+bool
+GreeterApp::x11EventFilter( XEvent * ev )
+{
+ KeySym sym;
+
+ switch (ev->type) {
+ case FocusIn:
+ case FocusOut:
+ // Hack to tell dialogs to take focus when the keyboard is grabbed
+ ev->xfocus.mode = NotifyNormal;
+ break;
+ case KeyPress:
+ sym = XLookupKeysym( &ev->xkey, 0 );
+ if (sym != XK_Return && !IsModifierKey( sym ))
+ emit activity();
+ break;
+ case ButtonPress:
+ emit activity();
+ /* fall through */
+ case ButtonRelease:
+ // Hack to let the RMB work as LMB
+ if (ev->xbutton.button == 3)
+ ev->xbutton.button = 1;
+ /* fall through */
+ case MotionNotify:
+ if (ev->xbutton.state & Button3Mask)
+ ev->xbutton.state = (ev->xbutton.state & ~Button3Mask) | Button1Mask;
+ break;
+ }
+ return false;
+}
+
+extern bool kde_have_kipc;
+
+extern "C" {
+
+static int
+xIOErr( Display * )
+{
+ exit( EX_RESERVER_DPY );
+}
+
+//KSimpleConfig *iccconfig;
+
+void
+checkSAK(GreeterApp* app)
+{
+ app->restoreOverrideCursor();
+ SAKDlg sak(0);
+ sak.exec();
+ app->setOverrideCursor( Qt::WaitCursor );
+}
+
+void
+kg_main( const char *argv0 )
+{
+ static char *argv[] = { (char *)"tdmgreet", 0 };
+ KCmdLineArgs::init( 1, argv, *argv, 0, 0, 0, true );
+
+ kdDebug() << timestamp() << "start" << endl;
+ kde_have_kipc = false;
+ KApplication::disableAutoDcopRegistration();
+ KCrash::setSafer( true );
+
+ KProcess *tsak = 0;
+ KProcess *proc = 0;
+ KProcess *comp = 0;
+ KProcess *twin = 0;
+
+ trinity_desktop_lock_use_sak = _useSAK;
+ if (trinity_desktop_lock_use_sak) {
+ tsak = new KProcess;
+ *tsak << TQCString( argv0, strrchr( argv0, '/' ) - argv0 + 2 ) + "tsak";
+ tsak->start(KProcess::Block);
+ }
+ if (tsak) {
+ tsak->closeStdin();
+ tsak->detach();
+ delete tsak;
+ }
+
+#ifdef HAVE_XCOMPOSITE
+ // Begin ARGB initialization
+ XSetErrorHandler( ignoreXError );
+ argb_visual_available = false;
+ char *display = 0;
+
+ Display *dpyi = XOpenDisplay( display );
+ if ( !dpyi ) {
+ kdError() << "cannot connect to X server " << display << endl;
+ exit( 1 );
+ }
+
+ int screen = DefaultScreen( dpyi );
+ Colormap colormap = 0;
+ Visual *visual = 0;
+ int event_base, error_base;
+
+ if ( XRenderQueryExtension( dpyi, &event_base, &error_base ) ) {
+ int nvi;
+ XVisualInfo templ;
+ templ.screen = screen;
+ templ.depth = 32;
+ templ.c_class = TrueColor;
+ XVisualInfo *xvi = XGetVisualInfo( dpyi, VisualScreenMask | VisualDepthMask
+ | VisualClassMask, &templ, &nvi );
+
+ for ( int i = 0; i < nvi; i++ ) {
+ XRenderPictFormat *format = XRenderFindVisualFormat( dpyi, xvi[i].visual );
+ if ( format->type == PictTypeDirect && format->direct.alphaMask ) {
+ visual = xvi[i].visual;
+ colormap = XCreateColormap( dpyi, RootWindow( dpyi, screen ), visual, AllocNone );
+ kdDebug() << "found visual with alpha support" << endl;
+ argb_visual_available = true;
+ break;
+ }
+ }
+ }
+ XSetErrorHandler( (XErrorHandler)0 );
+
+ GreeterApp *app;
+ if ( (argb_visual_available == true) && (!_compositor.isEmpty()) ) {
+ app = new GreeterApp(dpyi, Qt::HANDLE( visual ), Qt::HANDLE( colormap ));
+ }
+ else {
+ app = new GreeterApp();
+ }
+ // End ARGB initialization
+#else
+ GreeterApp *app = new GreeterApp();
+#endif
+
+ XSetIOErrorHandler( xIOErr );
+ TQString login_user;
+
+ Display *dpy = qt_xdisplay();
+
+ if (!_GUIStyle.isEmpty())
+ app->setStyle( _GUIStyle );
+
+ // Load up systemwide display settings
+#ifdef WITH_XRANDR
+ KRandrSimpleAPI *randrsimple = new KRandrSimpleAPI();
+ TQPoint primaryScreenPosition = randrsimple->applySystemwideDisplayConfiguration("", KDE_CONFDIR);
+ delete randrsimple;
+#endif
+
+ // Load up the systemwide ICC profile
+ TQString iccConfigFile = TQString(KDE_CONFDIR);
+ iccConfigFile += "/kicc/kiccconfigrc";
+ KSimpleConfig iccconfig(iccConfigFile, true);
+ if (iccconfig.readBoolEntry("EnableICC", false) == true) {
+ TQString iccCommand = TQString("/usr/bin/xcalib ");
+ iccCommand += iccconfig.readEntry("ICCFile");
+ iccCommand += TQString(" &");
+ system(iccCommand.ascii());
+ }
+
+ _colorScheme = locate( "data", "kdisplay/color-schemes/" + _colorScheme + ".kcsrc" );
+ if (!_colorScheme.isEmpty()) {
+ KSimpleConfig config( _colorScheme, true );
+ config.setGroup( "Color Scheme" );
+ app->setPalette( app->createApplicationPalette( &config, 7 ) );
+ }
+
+ app->setFont( _normalFont );
+
+ setup_modifiers( dpy, _numLockStatus );
+ SecureDisplay( dpy );
+ if (!_grabServer) {
+ if (_useBackground) {
+ proc = new KProcess;
+ *proc << TQCString( argv0, strrchr( argv0, '/' ) - argv0 + 2 ) + "krootimage";
+ *proc << _backgroundCfg;
+ proc->start();
+ }
+ GSendInt( G_SetupDpy );
+ GRecvInt();
+ }
+
+ if (!_compositor.isEmpty()) {
+ comp = new KProcess;
+ *comp << TQCString( argv0, strrchr( argv0, '/' ) - argv0 + 2 ) + _compositor.ascii();
+ comp->start(KProcess::NotifyOnExit, KProcess::Stdin);
+ }
+
+ if (!_windowManager.isEmpty()) {
+ twin = new KProcess;
+ *twin << TQCString( argv0, strrchr( argv0, '/' ) - argv0 + 2 ) + _windowManager.ascii();
+ twin->start();
+ has_twin = true;
+ }
+
+ GSendInt( G_Ready );
+
+ kdDebug() << timestamp() << " main1" << endl;
+ setCursor( dpy, app->desktop()->winId(), XC_left_ptr );
+
+ for (;;) {
+ int rslt, cmd = GRecvInt();
+
+ if (cmd == G_ConfShutdown) {
+ int how = GRecvInt(), uid = GRecvInt();
+ char *os = GRecvStr();
+ TDMSlimShutdown::externShutdown( how, os, uid );
+ if (os)
+ free( os );
+ GSendInt( G_Ready );
+ _autoLoginDelay = 0;
+ continue;
+ }
+
+ if (cmd == G_ErrorGreet) {
+ if (KGVerify::handleFailVerify( TQT_TQWIDGET(tqApp->desktop()->screen( _greeterScreen )) ))
+ break;
+ _autoLoginDelay = 0;
+ cmd = G_Greet;
+ }
+
+ KProcess *proc2 = 0;
+ app->setOverrideCursor( Qt::WaitCursor );
+ FDialog *dialog = NULL;
+#ifdef XDMCP
+ if (cmd == G_Choose) {
+ dialog = new ChooserDlg;
+ GSendInt( G_Ready ); /* tell chooser to go into async mode */
+ GRecvInt(); /* ack */
+ } else
+#endif
+ {
+ if ((cmd != G_GreetTimed && !_autoLoginAgain) ||
+ _autoLoginUser.isEmpty())
+ _autoLoginDelay = 0;
+ if (_useTheme && !_theme.isEmpty()) {
+ // Qt4 has a nasty habit of generating BadWindow errors in normal operation, so we simply ignore them
+ // This also prevents the user from being dropped to a console login if Xorg glitches or is buggy
+ XSetErrorHandler( ignoreXError );
+ KThemedGreeter *tgrt;
+ bool has_twin_bkp = has_twin;
+ is_themed = true;
+ has_twin = false; // [FIXME] The themed greeter is built on the assumption that there is no window manager available (i.e. it keeps stealing focus) and needs to be repaired.
+ dialog = tgrt = new KThemedGreeter;
+ kdDebug() << timestamp() << " themed" << endl;
+ if (!tgrt->isOK()) {
+ is_themed = false;
+ has_twin = has_twin_bkp;
+ delete tgrt;
+ checkSAK(app);
+ dialog = new KStdGreeter;
+#ifdef WITH_XRANDR
+ dialog->move(dialog->x() + primaryScreenPosition.x(), dialog->y() + primaryScreenPosition.y());
+#endif
+ }
+ else {
+#ifdef WITH_XRANDR
+ dialog->move(primaryScreenPosition.x(), primaryScreenPosition.y());
+#endif
+ }
+ XSetErrorHandler( (XErrorHandler)0 );
+ } else {
+ checkSAK(app);
+ dialog = new KStdGreeter;
+#ifdef WITH_XRANDR
+ dialog->move(dialog->x() + primaryScreenPosition.x(), dialog->y() + primaryScreenPosition.y());
+#endif
+ }
+ TQPoint oldCursorPos = TQCursor::pos();
+#ifdef WITH_XRANDR
+ TQCursor::setPos(oldCursorPos.x() + primaryScreenPosition.x(), oldCursorPos.y() + primaryScreenPosition.y());
+#endif
+ if (*_preloader) {
+ proc2 = new KProcess;
+ *proc2 << _preloader;
+ proc2->start();
+ }
+ }
+ app->restoreOverrideCursor();
+ Debug( "entering event loop\n" );
+ // Qt4 has a nasty habit of generating BadWindow errors in normal operation, so we simply ignore them
+ // This also prevents the user from being dropped to a console login if Xorg glitches or is buggy
+ XSetErrorHandler( ignoreXError );
+ rslt = dialog->exec();
+ XSetErrorHandler( (XErrorHandler)0 );
+ Debug( "left event loop\n" );
+
+ login_user = static_cast<KGreeter*>(dialog)->curUser;
+
+ if (rslt != ex_greet) {
+ delete dialog;
+ }
+ delete proc2;
+#ifdef XDMCP
+ switch (rslt) {
+ case ex_greet:
+ GSendInt( G_DGreet );
+ continue;
+ case ex_choose:
+ GSendInt( G_DChoose );
+ continue;
+ default:
+ break;
+ }
+#endif
+ break;
+ }
+
+ KGVerify::done();
+
+ if (comp) {
+ if (_compositor == "kompmgr") {
+ // Change process UID
+ // Get user UID
+ passwd* userinfo = getpwnam(login_user.ascii());
+ if (userinfo) {
+ TQString newuid = TQString("%1").arg(userinfo->pw_uid);
+ // kompmgr allows us to change its uid in this manner:
+ // 1.) Send SIGUSER1
+ // 2.) Send the new UID to it on the command line
+ comp->kill(SIGUSR1);
+ comp->writeStdin(newuid.ascii(), newuid.length());
+ usleep(50000); // Give the above function some time to execute. Note that on REALLY slow systems this could fail, leaving kompmgr running as root. TODO: Look into ways to make this more robust.
+ }
+ }
+ comp->closeStdin();
+ comp->detach();
+ delete comp;
+ }
+ if (twin) {
+ twin->closeStdin();
+ twin->detach();
+ delete twin;
+ }
+ delete proc;
+ UnsecureDisplay( dpy );
+ restore_modifiers();
+
+ XSetInputFocus( qt_xdisplay(), PointerRoot, PointerRoot, CurrentTime );
+
+ delete app;
+}
+
+} // extern "C"
+
+#include "kgapp.moc"
diff --git a/tdm/kfrontend/kgapp.h b/tdm/kfrontend/kgapp.h
new file mode 100644
index 00000000..2c4374f4
--- /dev/null
+++ b/tdm/kfrontend/kgapp.h
@@ -0,0 +1,50 @@
+/*
+
+Greeter module for xdm
+
+Copyright (C) 1997, 1998 Steffen Hansen <hansen@kde.org>
+Copyright (C) 2000-2003 Oswald Buddenhagen <ossi@kde.org>
+
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+
+#ifndef KGAPP_H
+#define KGAPP_H
+
+#include <kapplication.h>
+
+class GreeterApp : public KApplication {
+ Q_OBJECT
+ typedef KApplication inherited;
+
+ public:
+ GreeterApp();
+ GreeterApp(Display *dpy, Qt::HANDLE visual, Qt::HANDLE colormap);
+ virtual bool x11EventFilter( XEvent * );
+
+ protected:
+ virtual void timerEvent( TQTimerEvent * );
+
+ signals:
+ void activity();
+
+ private:
+ int pingInterval;
+};
+
+#endif /* KGAPP_H */
diff --git a/tdm/kfrontend/kgdialog.cpp b/tdm/kfrontend/kgdialog.cpp
new file mode 100644
index 00000000..667eca8e
--- /dev/null
+++ b/tdm/kfrontend/kgdialog.cpp
@@ -0,0 +1,240 @@
+/*
+
+Base class for various tdm greeter dialogs
+
+Copyright (C) 1997, 1998 Steffen Hansen <hansen@kde.org>
+Copyright (C) 2000-2004 Oswald Buddenhagen <ossi@kde.org>
+
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#include "kgdialog.h"
+#include "kgverify.h"
+#include "kconsole.h"
+#include "tdmshutdown.h"
+#include "tdm_greet.h"
+
+#include <klocale.h>
+#include <kiconloader.h>
+
+#include <tqaccel.h>
+#include <tqlayout.h>
+#include <tqpushbutton.h>
+#include <tqpopupmenu.h>
+#include <tqapplication.h>
+
+#include <stdlib.h>
+
+KGDialog::KGDialog( bool themed ) : inherited( 0, !themed )
+{
+#ifdef WITH_TDM_XCONSOLE
+ consoleView = _showLog ? new KConsole( this ) : 0;
+#endif
+
+ optMenu = 0;
+ verify = 0;
+}
+
+void
+#ifdef XDMCP
+KGDialog::completeMenu( int _switchIf, int _switchCode, const TQString &_switchMsg, int _switchAccel )
+#else
+KGDialog::completeMenu()
+#endif
+{
+#ifdef HAVE_VTS
+ if (_isLocal) {
+ dpyMenu = new TQPopupMenu( this );
+ int id = inserten( i18n("Sw&itch User"), ALT+Key_I, dpyMenu );
+ connect( dpyMenu, TQT_SIGNAL(activated( int )),
+ TQT_SLOT(slotDisplaySelected( int )) );
+ connect( dpyMenu, TQT_SIGNAL(aboutToShow()),
+ TQT_SLOT(slotPopulateDisplays()) );
+ TQAccel *accel = new TQAccel( this );
+ accel->insertItem( ALT+CTRL+Key_Insert, id );
+ connect( accel, TQT_SIGNAL(activated( int )), TQT_SLOT(slotActivateMenu( int )) );
+ }
+#endif
+
+ if (_allowClose)
+ inserten( _isLocal ? i18n("R&estart X Server") : i18n("Clos&e Connection"),
+ ALT+Key_E, TQT_SLOT(slotExit()) );
+
+#ifdef XDMCP
+ if (_isLocal && _loginMode != _switchIf) {
+ switchCode = _switchCode;
+ inserten( _switchMsg, _switchAccel, TQT_SLOT(slotSwitch()) );
+ }
+#endif
+
+ if (_hasConsole)
+ inserten( i18n("Co&nsole Login"), ALT+Key_N, TQT_SLOT(slotConsole()) );
+
+ if (_allowShutdown != SHUT_NONE) {
+ ensureMenu();
+ optMenu->insertItem(SmallIconSet( "exit" ), i18n("&Shutdown..."), this, TQT_SLOT(slotShutdown(int)), ALT+Key_S );
+ TQAccel *accel = new TQAccel( this );
+ accel->insertItem( ALT+CTRL+Key_Delete );
+ connect( accel, TQT_SIGNAL(activated( int )), TQT_SLOT(slotShutdown( int )) );
+ accel = new TQAccel( this );
+ accel->insertItem( SHIFT+ALT+CTRL+Key_PageUp, SHUT_REBOOT );
+ connect( accel, TQT_SIGNAL(activated( int )), TQT_SLOT(slotShutdown( int )) );
+ accel = new TQAccel( this );
+ accel->insertItem( SHIFT+ALT+CTRL+Key_PageDown, SHUT_HALT );
+ connect( accel, TQT_SIGNAL(activated( int )), TQT_SLOT(slotShutdown( int )) );
+ }
+}
+
+void
+KGDialog::ensureMenu()
+{
+ if (!optMenu) {
+ optMenu = new TQPopupMenu( this );
+ optMenu->setCheckable( false );
+ needSep = false;
+ } else if (needSep) {
+ optMenu->insertSeparator();
+ needSep = false;
+ }
+}
+
+void
+KGDialog::inserten( const TQString& txt, int accel, const char *member )
+{
+ ensureMenu();
+ optMenu->insertItem( txt, this, member, accel );
+}
+
+int
+KGDialog::inserten( const TQString& txt, int accel, TQPopupMenu *cmnu )
+{
+ ensureMenu();
+ int id = optMenu->insertItem( txt, cmnu );
+ optMenu->setAccel( accel, id );
+ optMenu->connectItem( id, this, TQT_SLOT(slotActivateMenu( int )) );
+ optMenu->setItemParameter( id, id );
+ return id;
+}
+
+void
+KGDialog::slotActivateMenu( int id )
+{
+ TQPopupMenu *cmnu = optMenu->findItem( id )->popup();
+ TQSize sh( cmnu->sizeHint() / 2 );
+ cmnu->exec( geometry().center() - TQPoint( sh.width(), sh.height() ) );
+}
+
+void
+KGDialog::slotExit()
+{
+ if (verify)
+ verify->abort();
+ ::exit( EX_RESERVER_DPY );
+}
+
+void
+KGDialog::slotSwitch()
+{
+#ifdef XDMCP
+ // workaround for Qt bug
+ TQTimer::singleShot( 0, this, TQT_SLOT(slotReallySwitch()) );
+#endif
+}
+
+void
+KGDialog::slotReallySwitch()
+{
+#ifdef XDMCP
+ done( switchCode );
+#endif
+}
+
+void
+KGDialog::slotConsole()
+{
+#ifdef HAVE_VTS
+ dpySpec *sess = fetchSessions( 0 );
+ if (sess) {
+ if (verify)
+ verify->suspend();
+ int ret = TDMConfShutdown( -1, sess, SHUT_CONSOLE, 0 ).exec();
+ if (verify)
+ verify->resume();
+ disposeSessions( sess );
+ if (!ret)
+ return;
+ }
+#else
+ if (verify)
+ verify->abort();
+#endif
+ GSet( 1 );
+ GSendInt( G_Console );
+ GSet( 0 );
+}
+
+void
+KGDialog::slotShutdown( int id )
+{
+ if (verify)
+ verify->suspend();
+ if (id < 0) {
+ if (_scheduledSd == SHUT_ALWAYS)
+ TDMShutdown::scheduleShutdown( this );
+ else
+ TDMSlimShutdown( this ).exec();
+ } else
+ TDMSlimShutdown::externShutdown( id, 0, -1 );
+ if (verify)
+ verify->resume();
+}
+
+void
+KGDialog::slotDisplaySelected( int vt )
+{
+#ifdef HAVE_VTS
+ GSet( 1 );
+ GSendInt( G_Activate );
+ GSendInt( vt );
+ GSet( 0 );
+#else
+ (void)vt;
+#endif
+}
+
+void
+KGDialog::slotPopulateDisplays()
+{
+#ifdef HAVE_VTS
+ dpyMenu->clear();
+ dpySpec *sessions = fetchSessions( lstPassive | lstTTY );
+ TQString user, loc;
+ for (dpySpec *sess = sessions; sess; sess = sess->next) {
+ decodeSess( sess, user, loc );
+ int id = dpyMenu->insertItem(
+ i18n("session (location)", "%1 (%2)").arg( user ).arg( loc ),
+ sess->vt ? sess->vt : -1 );
+ if (!sess->vt)
+ dpyMenu->setItemEnabled( id, false );
+ if (sess->flags & isSelf)
+ dpyMenu->setItemChecked( id, true );
+ }
+ disposeSessions( sessions );
+#endif
+}
+
+#include "kgdialog.moc"
diff --git a/tdm/kfrontend/kgdialog.h b/tdm/kfrontend/kgdialog.h
new file mode 100644
index 00000000..a902b6ff
--- /dev/null
+++ b/tdm/kfrontend/kgdialog.h
@@ -0,0 +1,87 @@
+/*
+
+Base class for various tdm greeter dialogs
+
+Copyright (C) 1997, 1998 Steffen Hansen <hansen@kde.org>
+Copyright (C) 2000-2004 Oswald Buddenhagen <ossi@kde.org>
+
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+
+#ifndef KGDIALOG_H
+#define KGDIALOG_H
+
+#include <config.h> // for WITH_TDM_XCONSOLE
+
+#include "tdmconfig.h"
+#include "kfdialog.h"
+
+class TQPopupMenu;
+class TQGridLayout;
+class KConsole;
+class KGVerify;
+
+#define ex_exit 1
+#define ex_greet 2
+#define ex_choose 3
+
+class KGDialog : public FDialog {
+ Q_OBJECT
+ typedef FDialog inherited;
+
+ public:
+ KGDialog( bool themed = false );
+
+ public slots:
+ void slotActivateMenu( int id );
+ void slotExit();
+ void slotSwitch();
+ void slotReallySwitch();
+ void slotConsole();
+ void slotShutdown( int id );
+
+ protected:
+#ifdef XDMCP
+ void completeMenu( int _switchIf, int _switchCode, const TQString &_switchMsg, int _switchAccel );
+#else
+ void completeMenu();
+#endif
+ void inserten( const TQString& txt, int accel, const char *member );
+ int inserten( const TQString& txt, int accel, TQPopupMenu *cmnu );
+
+ bool needSep;
+ TQPopupMenu *optMenu;
+ KGVerify *verify;
+#ifdef WITH_TDM_XCONSOLE
+ KConsole *consoleView;
+#endif
+
+ private slots:
+ void slotDisplaySelected( int vt );
+ void slotPopulateDisplays();
+
+ private:
+ void ensureMenu();
+
+#ifdef HAVE_VTS
+ TQPopupMenu *dpyMenu;
+#endif
+ int switchCode;
+};
+
+#endif /* KGDIALOG_H */
diff --git a/tdm/kfrontend/kgreeter.cpp b/tdm/kfrontend/kgreeter.cpp
new file mode 100644
index 00000000..ee1bf3e7
--- /dev/null
+++ b/tdm/kfrontend/kgreeter.cpp
@@ -0,0 +1,1280 @@
+/*
+
+Greeter widget for tdm
+
+Copyright (C) 1997, 1998, 2000 Steffen Hansen <hansen@kde.org>
+Copyright (C) 2000-2004 Oswald Buddenhagen <ossi@kde.org>
+
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#include "kgreeter.h"
+#include "kconsole.h"
+#include "tdmconfig.h"
+#include "tdmclock.h"
+#include "tdm_greet.h"
+#include "tdmadmindialog.h"
+#include "themer/tdmthemer.h"
+#include "themer/tdmitem.h"
+#include "themer/tdmlabel.h"
+
+#include <kapplication.h>
+#include <klocale.h>
+#include <kstandarddirs.h>
+#include <kseparator.h>
+#include <klistview.h>
+#include <ksimpleconfig.h>
+#include <kstringhandler.h>
+#include <kdebug.h>
+
+#undef Unsorted // x headers suck - make tqdir.h work with --enable-final
+#include <tqdir.h>
+#include <tqfile.h>
+#include <tqbuffer.h>
+#include <tqmemarray.h>
+#include <tqimage.h>
+#include <tqmovie.h>
+#include <tqpainter.h>
+#include <tqpopupmenu.h>
+#include <tqtimer.h>
+#include <tqheader.h>
+#include <tqstyle.h>
+#include <tqlayout.h>
+#include <tqlabel.h>
+#include <tqpushbutton.h>
+#include <tqtooltip.h>
+#include <tqaccel.h>
+#include <tqstring.h>
+#include <tqeventloop.h>
+#include <tqbitmap.h>
+
+#include <pwd.h>
+#include <grp.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <utmp.h>
+#include <utmpx.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <limits.h>
+#include <dirent.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/select.h>
+#include <sys/time.h>
+#include <termios.h>
+#include <signal.h>
+
+#include <X11/Xlib.h>
+
+#define FIFO_DIR "/tmp/ksocket-global/tdm"
+#define FIFO_FILE "/tmp/ksocket-global/tdm/tdmctl-%1"
+#define FIFO_SAK_FILE "/tmp/ksocket-global/tdm/tdmctl-sak-%1"
+
+class UserListView : public KListView {
+ public:
+ UserListView( bool _them, TQWidget *parent = 0, const char *name = 0 )
+ : KListView( parent, name )
+ , themed(_them), cachedSizeHint( -1, 0 )
+ {
+ setSizePolicy( TQSizePolicy::Preferred, TQSizePolicy::Ignored );
+ header()->hide();
+ addColumn( TQString::null );
+ setColumnAlignment( 0, AlignVCenter );
+ setResizeMode( TQListView::LastColumn );
+ // FIXME: This must be configurable, so disable
+ // painting of list background for now.
+// if (themed) {
+// setBackgroundMode( Qt::NoBackground );
+// viewport()->setBackgroundMode( Qt::NoBackground );
+// setFrameStyle( TQFrame::NoFrame );
+// }
+ }
+
+ bool themed;
+ mutable TQSize cachedSizeHint;
+
+ int sumHeight() const
+ {
+ int sum = 0;
+ for (TQListViewItem *itm = firstChild(); itm; itm = itm->nextSibling()) {
+ sum += itm->height();
+ }
+ return sum;
+ }
+public:
+ virtual TQSize sizeHint() const
+ {
+ if (themed)
+ return KListView::sizeHint();
+
+ if (!cachedSizeHint.isValid()) {
+ constPolish();
+ uint maxw = 0;
+ for (TQListViewItem *itm = firstChild(); itm; itm = itm->nextSibling()) {
+ uint thisw = itm->width( fontMetrics(), this, 0 );
+ if (thisw > maxw)
+ maxw = thisw;
+ }
+ cachedSizeHint.setWidth(
+ style().pixelMetric( TQStyle::PM_ScrollBarExtent ) +
+ frameWidth() * 2 + maxw );
+ }
+ return cachedSizeHint;
+ }
+ virtual void paintEmptyArea ( TQPainter * p, const TQRect & rect )
+ {
+ if (!themed)
+ return KListView::paintEmptyArea(p, rect );
+
+ // FIXME: This must be configurable, so disable
+ // painting of list background for now.
+ return KListView::paintEmptyArea(p, rect );
+
+ const TQPixmap *pm = TQT_TQPIXMAP_CONST(paletteBackgroundPixmap());
+ if (!pm || pm->isNull())
+ return;
+
+ kdDebug() << "paintEmpty " << rect << endl;
+ TQRect devRect = p->xForm( rect );
+ kdDebug() << "paintEmpty2 " << devRect << endl;
+ p->drawPixmap(0, 0, *pm, devRect.left(), devRect.top() );
+ }
+
+ TQPixmap background;
+};
+
+int KGreeter::curPlugin = -1;
+PluginList KGreeter::pluginList;
+
+KGreeter::KGreeter( bool framed )
+ : inherited( framed )
+ , dName( dname )
+ , userView( 0 )
+ , userList( 0 )
+ , nNormals( 0 )
+ , nSpecials( 0 )
+ , curPrev( -1 )
+ , curSel( -1 )
+ , prevValid( true )
+ , needLoad( false )
+ , themed( framed )
+ , mPipe_fd( -1 )
+ , closingDown( false )
+{
+ stsFile = new KSimpleConfig( _stsFile );
+ stsFile->setGroup( "PrevUser" );
+
+ if (_userList) {
+ readFacesList();
+ userView = new UserListView( framed, this );
+ connect( userView, TQT_SIGNAL(clicked( TQListViewItem * )),
+ TQT_SLOT(slotUserClicked( TQListViewItem * )) );
+ connect( userView, TQT_SIGNAL(doubleClicked( TQListViewItem * )),
+ TQT_SLOT(accept()) );
+ }
+ if (_userCompletion)
+ userList = new TQStringList;
+
+ sessMenu = new TQPopupMenu( this );
+ connect( sessMenu, TQT_SIGNAL(activated( int )),
+ TQT_SLOT(slotSessionSelected( int )) );
+ insertSessions();
+
+ if (curPlugin < 0) {
+ curPlugin = 0;
+ pluginList = KGVerify::init( _pluginsLogin );
+ }
+
+ TQTimer::singleShot( 0, this, TQT_SLOT(handleInputPipe()) );
+}
+
+KGreeter::~KGreeter()
+{
+ if (mPipe_fd != -1) {
+ closingDown = true;
+ ::close(mPipe_fd);
+ ::unlink(mPipeFilename.ascii());
+ }
+ hide();
+ delete userList;
+ delete verify;
+ delete stsFile;
+}
+
+void KGreeter::done(int r) {
+ closingDown = true;
+ inherited::done(r);
+}
+
+void KGreeter::handleInputPipe(void) {
+ if (closingDown) {
+ ::unlink(mPipeFilename.ascii());
+ return;
+ }
+
+ if (isShown() == false) {
+ TQTimer::singleShot( 100, this, TQT_SLOT(handleInputPipe()) );
+ return;
+ }
+
+ char readbuf[2048];
+ int displayNumber;
+ TQString currentDisplay;
+ currentDisplay = TQString(getenv("DISPLAY"));
+ currentDisplay = currentDisplay.replace(":", "");
+ displayNumber = currentDisplay.toInt();
+ mPipeFilename = TQString(FIFO_FILE).arg(displayNumber);
+ ::unlink((TQString(FIFO_SAK_FILE).arg(displayNumber)).ascii());
+
+ /* Create the FIFOs if they do not exist */
+ umask(0);
+ struct stat buffer;
+ int status;
+ status = stat(FIFO_DIR, &buffer);
+ if (status == 0) {
+ int file_mode = ((buffer.st_mode & S_IRWXU) >> 6) * 100;
+ file_mode = file_mode + ((buffer.st_mode & S_IRWXG) >> 3) * 10;
+ file_mode = file_mode + ((buffer.st_mode & S_IRWXO) >> 0) * 1;
+ if ((file_mode != 600) || (buffer.st_uid != 0) || (buffer.st_gid != 0)) {
+ ::unlink(mPipeFilename.ascii());
+ printf("[WARNING] Possible security breach! Please check permissions on " FIFO_DIR " (must be 600 and owned by root/root, got %d %d/%d). Not listening for login credentials on remote control socket.\n", file_mode, buffer.st_uid, buffer.st_gid); fflush(stdout);
+ return;
+ }
+ }
+ mkdir(FIFO_DIR,0600);
+ mknod(mPipeFilename.ascii(), S_IFIFO|0600, 0);
+ chmod(mPipeFilename.ascii(), 0600);
+
+ mPipe_fd = ::open(mPipeFilename.ascii(), O_RDONLY | O_NONBLOCK);
+ int numread;
+ TQString inputcommand = "";
+ while ((!inputcommand.contains('\n')) && (!closingDown)) {
+ numread = ::read(mPipe_fd, readbuf, 2048);
+ readbuf[numread] = 0;
+ readbuf[2047] = 0;
+ inputcommand += readbuf;
+ if (!tqApp->hasPendingEvents()) {
+ usleep(500);
+ }
+ tqApp->processEvents();
+ }
+ if (closingDown) {
+ ::unlink(mPipeFilename.ascii());
+ return;
+ }
+ inputcommand = inputcommand.replace('\n', "");
+ TQStringList commandList = TQStringList::split('\t', inputcommand, false);
+ if ((*(commandList.at(0))) == "LOGIN") {
+ if (verify) {
+ verify->setUser( (*(commandList.at(1))) );
+ verify->setPassword( (*(commandList.at(2))) );
+ accept();
+ }
+ }
+ if (!closingDown) {
+ TQTimer::singleShot( 0, this, TQT_SLOT(handleInputPipe()) );
+ ::close(mPipe_fd);
+ ::unlink(mPipeFilename.ascii());
+ }
+ else {
+ ::unlink(mPipeFilename.ascii());
+ }
+}
+
+void KGreeter::readFacesList()
+{
+ FILE *f = fopen( TQFile::encodeName( _faceDir + "/.randomlist" ), "rt" );
+ if ( !f )
+ return;
+ TQTextIStream is( f );
+ while ( !is.eof() )
+ {
+ TQString line = is.readLine().simplifyWhiteSpace();
+ if ( line.isEmpty() )
+ continue;
+ TQString icon;
+ int index = line.find( ' ' );
+ if ( index > 0 ) {
+ icon = line.left( index );
+ line = line.mid( index );
+ } else {
+ icon = line;
+ line = TQString::null;
+ }
+ randomFaces.push_back( icon );
+ TQStringList list = TQStringList::split( ' ', line );
+ for ( TQStringList::ConstIterator it = list.begin(); it != list.end(); ++it )
+ randomFacesMap[*it] = icon;
+ }
+}
+
+class UserListViewItem : public KListViewItem {
+ public:
+ UserListViewItem( UserListView *parent, const TQString &text,
+ const TQPixmap &pixmap, const TQString &username )
+ : KListViewItem( parent )
+ , login( username )
+ {
+ setPixmap( 0, pixmap );
+ setMultiLinesEnabled( true );
+ setText( 0, text );
+ parent->cachedSizeHint.setWidth( -1 );
+ }
+
+ virtual void paintCell(TQPainter *p, const TQColorGroup &cg, int column, int width, int alignment)
+ {
+ if (((UserListView*)listView())->themed)
+ TQListViewItem::paintCell(p, cg, column, width, alignment);
+ else
+ KListViewItem::paintCell(p, cg, column, width, alignment);
+ }
+
+ TQString login;
+};
+
+#define FILE_LIMIT_ICON 20
+#define FILE_LIMIT_IMAGE 200
+
+void
+KGreeter::insertUser( const TQImage &default_pix,
+ const TQString &username, struct passwd *ps )
+{
+ if (setegid( ps->pw_gid ))
+ return;
+ if (seteuid( ps->pw_uid )) {
+ setegid(0);
+ return;
+ }
+
+ if (userList)
+ userList->append( username );
+ if (!userView)
+ return;
+
+ int dp = 0, nd = 0;
+ if (_faceSource == FACE_USER_ONLY ||
+ _faceSource == FACE_PREFER_USER)
+ dp = 1;
+ if (_faceSource != FACE_USER_ONLY &&
+ _faceSource != FACE_ADMIN_ONLY)
+ nd = 1;
+ TQImage p;
+ do {
+ dp ^= 1;
+ TQCString fn = !dp ?
+ TQCString( ps->pw_dir ) + '/' :
+ TQCString(TQFile::encodeName( _faceDir + '/' + username ));
+ fn += ".face.icon";
+ int fd, ico;
+ if ((fd = open( fn.data(), O_RDONLY | O_NONBLOCK )) < 0) {
+ fn.truncate( fn.length() - 5 );
+ if ((fd = open( fn.data(), O_RDONLY | O_NONBLOCK )) < 0)
+ continue;
+ ico = 0;
+ } else
+ ico = 1;
+ TQFile f;
+ f.open( IO_ReadOnly, fd );
+ int fs = f.size();
+ if (fs > (ico ? FILE_LIMIT_ICON : FILE_LIMIT_IMAGE) * 1000) {
+ LogWarn( "%s exceeds file size limit (%dkB)\n",
+ fn.data(), ico ? FILE_LIMIT_ICON : FILE_LIMIT_IMAGE );
+ continue;
+ }
+ TQByteArray fc( fs );
+ int rfs = f.readBlock( fc.data(), fs );
+ ::close( fd );
+ fc.resize( rfs > 0 ? rfs : 0 );
+ TQBuffer buf( fc );
+ buf.open( IO_ReadOnly );
+ TQImageIO ir;
+ ir.setIODevice( TQT_TQIODEVICE(&buf) );
+ if (!ir.read()) {
+ LogInfo( "%s is no valid image\n", fn.data() );
+ continue;
+ }
+ p = ir.image();
+ TQSize ns( 48, 48 );
+ if (p.size() != ns)
+ p = p.convertDepth( 32 ).smoothScale( ns, TQ_ScaleMin );
+ break;
+ } while (--nd >= 0);
+
+ if ( p.isNull() && randomFaces.count() ) {
+ TQString randomFace = randomFacesMap[username];
+ if ( randomFace.isNull() ) {
+ TQStringList::size_type index = 0;
+ for ( size_t i = 0; i < username.length(); ++i )
+ index += ( 0x7f - username.at( i ).latin1() ) % 37;
+ randomFace = randomFaces[ index % randomFaces.count() ];
+ }
+ p.load( _faceDir + "/../pics/users/" + randomFace + ".png" );
+ }
+
+ if ( p.isNull() )
+ p = default_pix;
+
+ TQString realname = KStringHandler::from8Bit( ps->pw_gecos );
+ realname.truncate( realname.find( ',' ) );
+ if (realname.isEmpty() || realname == username)
+ new UserListViewItem( userView, username, TQPixmap( p ), username );
+ else {
+ realname.append( "\n" ).append( username );
+ new UserListViewItem( userView, realname, TQPixmap( p ), username );
+ }
+
+ seteuid( 0 );
+ setegid( 0 );
+}
+
+class KCStringList : public TQValueList<TQCString> {
+ public:
+ bool contains( const char *str ) const
+ {
+ for (ConstIterator it = begin(); it != end(); ++it)
+ if (*it == str)
+ return true;
+ return false;
+ }
+};
+
+class UserList {
+ public:
+ UserList( char **in );
+ bool hasUser( const char *str ) const { return users.contains( str ); }
+ bool hasGroup( gid_t gid ) const
+ { return groups.find( gid ) != groups.end(); }
+ bool hasGroups() const { return !groups.isEmpty(); }
+ KCStringList users;
+
+ private:
+ TQValueList<gid_t> groups;
+};
+
+UserList::UserList( char **in )
+{
+ struct group *grp;
+
+ for (; *in; in++)
+ if (**in == '@') {
+ if ((grp = getgrnam( *in + 1 ))) {
+ for (; *grp->gr_mem; grp->gr_mem++)
+ users.append( *grp->gr_mem );
+ groups.append( grp->gr_gid );
+ }
+ } else
+ users.append( *in );
+}
+
+void
+KGreeter::insertUsers(int limit_users)
+{
+ struct passwd *ps;
+
+ if (!(ps = getpwnam( "nobody" )))
+ return;
+
+ TQImage default_pix;
+ if (userView) {
+ if (!default_pix.load( _faceDir + "/.default.face.icon" ))
+ if (!default_pix.load( _faceDir + "/.default.face" ))
+ LogError( "Can't open default user face\n" );
+ TQSize ns( 48, 48 );
+ if (default_pix.size() != ns)
+ default_pix =
+ default_pix.convertDepth( 32 ).smoothScale( ns, TQ_ScaleMin );
+ }
+ if (_showUsers == SHOW_ALL) {
+ UserList noUsers( _noUsers );
+ TQDict<int> dupes( 1000 ); // Potential crash risk with buffer overrun?
+ TQStringList toinsert;
+ int count = 0;
+ for (setpwent(); (ps = getpwent()) != 0;) {
+ if (*ps->pw_dir && *ps->pw_shell &&
+ ((ps->pw_uid >= (unsigned)_lowUserId) ||
+ ((!ps->pw_uid) && _showRoot)) &&
+ (ps->pw_uid <= (unsigned)_highUserId) &&
+ (!noUsers.hasUser( ps->pw_name )) &&
+ (!noUsers.hasGroup( ps->pw_gid )))
+ {
+ TQString username( TQFile::decodeName( ps->pw_name ) );
+ if (!dupes.find( username )) {
+ dupes.insert( username, (int *)-1 );
+ toinsert.append( username );
+
+ if ( limit_users >= 0 && ++count > limit_users )
+ break;
+ }
+ }
+ }
+ // FIXME: OpenSUSE added this code
+ // For some reason it does not allow LDAP users to be listed (!),
+ // therefore it was deactivated. It should be repaired and reactivated.
+// if ( limit_users >= 0 && ++count > limit_users ) {
+// utmpname( _PATH_WTMP );
+// setutxent();
+// toinsert = TQStringList();
+// dupes.clear();
+//
+// for ( count = 0; count < limit_users; ) {
+// struct utmpx * ent = getutxent();
+// if ( !ent )
+// break;
+// struct passwd *ps = getpwnam( ent->ut_user );
+// if (ps && *ps->pw_dir && *ps->pw_shell &&
+// (ps->pw_uid >= (unsigned)_lowUserId ||
+// !ps->pw_uid && _showRoot) &&
+// ps->pw_uid <= (unsigned)_highUserId &&
+// !noUsers.hasUser( ps->pw_name ) &&
+// !noUsers.hasGroup( ps->pw_gid ))
+// {
+// TQString username( TQFile::decodeName( ent->ut_user ) );
+// if (!dupes.find( username )) {
+// dupes.insert( username, (int *)-1 );
+// toinsert.append( username );
+// count++;
+// }
+// }
+//
+//
+// }
+// endutxent();
+// }
+
+ for ( TQStringList::ConstIterator it = toinsert.begin();
+ it != toinsert.end(); ++it )
+ {
+ // pretty stupid to do another lookup round, but the number is limited
+ // and caching struct passwd is pretty ugly
+ struct passwd *ps = getpwnam( TQFile::encodeName( *it ) );
+ if ( ps )
+ insertUser( default_pix, *it, ps );
+ }
+ } else {
+ UserList users( _users );
+ if (users.hasGroups()) {
+ TQDict<int> dupes( 1000 );
+ for (setpwent(); (ps = getpwent()) != 0;) {
+ if (*ps->pw_dir && *ps->pw_shell &&
+ (ps->pw_uid >= (unsigned)_lowUserId ||
+ ((!ps->pw_uid) && _showRoot)) &&
+ ps->pw_uid <= (unsigned)_highUserId &&
+ (users.hasUser( ps->pw_name ) ||
+ users.hasGroup( ps->pw_gid )))
+ {
+ TQString username( TQFile::decodeName( ps->pw_name ) );
+ if (!dupes.find( username )) {
+ dupes.insert( username, (int *)-1 );
+ insertUser( default_pix, username, ps );
+ }
+ }
+ }
+ } else {
+ KCStringList::ConstIterator it = users.users.begin();
+ for (; it != users.users.end(); ++it)
+ if ((ps = getpwnam( (*it).data() )) &&
+ (ps->pw_uid || _showRoot))
+ insertUser( default_pix, TQFile::decodeName( *it ), ps );
+ }
+ }
+ endpwent();
+ if (_sortUsers) {
+ if (userView)
+ userView->sort();
+ if (userList)
+ userList->sort();
+ }
+}
+
+void
+KGreeter::putSession( const TQString &type, const TQString &name, bool hid, const char *exe )
+{
+ int prio = exe ? (!strcmp( exe, "default" ) ? 0 :
+ !strcmp( exe, "failsafe" ) ? 3 : 2) : 2;
+ for (uint i = 0; i < sessionTypes.size(); i++)
+ if (sessionTypes[i].type == type) {
+ sessionTypes[i].prio = prio;
+ return;
+ }
+ sessionTypes.append( SessType( name, type, hid, prio ) );
+}
+
+void
+KGreeter::insertSessions()
+{
+ for (char **dit = _sessionsDirs; *dit; ++dit) {
+ TQStringList ents = TQDir( *dit ).entryList();
+ for (TQStringList::ConstIterator it = ents.begin(); it != ents.end(); ++it)
+ if ((*it).endsWith( ".desktop" ) && !(*it).endsWith("admin.desktop")) {
+ KSimpleConfig dsk( TQString( *dit ).append( '/' ).append( *it ) );
+ dsk.setGroup( "Desktop Entry" );
+ putSession( (*it).left( (*it).length() - 8 ),
+ dsk.readEntry( "Name" ),
+ (dsk.readBoolEntry( "Hidden", false ) ||
+ (dsk.hasKey( "TryExec" ) &&
+ KStandardDirs::findExe( dsk.readEntry( "TryExec" ) ).isEmpty())),
+ dsk.readEntry( "Exec" ).latin1() );
+ }
+ }
+ putSession( "default", i18n("Default"), false, "default" );
+ putSession( "failsafe", i18n("Failsafe"), false, "failsafe" );
+ qBubbleSort( sessionTypes );
+ for (uint i = 0; i < sessionTypes.size() && !sessionTypes[i].hid; i++) {
+ sessMenu->insertItem( sessionTypes[i].name, i );
+ switch (sessionTypes[i].prio) {
+ case 0: case 1: nSpecials++; break;
+ case 2: nNormals++; break;
+ }
+ }
+}
+
+void
+KGreeter::slotUserEntered()
+{
+ if (userView) {
+ TQListViewItem *item;
+ for (item = userView->firstChild(); item; item = item->nextSibling())
+ if (((UserListViewItem *)item)->login == curUser) {
+ userView->setSelected( item, true );
+ userView->ensureItemVisible( item );
+ goto oke;
+ }
+ userView->clearSelection();
+ }
+ oke:
+ if (isVisible())
+ slotLoadPrevWM();
+ else
+ TQTimer::singleShot( 0, this, TQT_SLOT(slotLoadPrevWM()) );
+}
+
+void
+KGreeter::slotUserClicked( TQListViewItem *item )
+{
+ if (item) {
+ curUser = ((UserListViewItem *)item)->login;
+ verify->setUser( curUser );
+ slotLoadPrevWM();
+ }
+}
+
+void
+KGreeter::slotSessionSelected( int id )
+{
+ if (id != curSel) {
+ sessMenu->setItemChecked( curSel, false );
+ sessMenu->setItemChecked( id, true );
+ curSel = id;
+ verify->gplugActivity();
+ }
+}
+
+void
+KGreeter::reject()
+{
+ verify->reject();
+}
+
+void
+KGreeter::accept()
+{
+ if (userView && userView->hasFocus())
+ slotUserClicked( userView->currentItem() );
+ else
+ verify->accept();
+}
+
+void // private
+KGreeter::setPrevWM( int wm )
+{
+ if (curPrev != wm) {
+ if (curPrev != -1)
+ sessMenu->changeItem( curPrev, sessionTypes[curPrev].name );
+ if (wm != -1)
+ sessMenu->changeItem( wm, sessionTypes[wm].name + i18n(" (previous)") );
+ curPrev = wm;
+ }
+}
+
+void
+KGreeter::slotLoadPrevWM()
+{
+ int len, i, b;
+ unsigned long crc, by;
+ TQCString name;
+ char *sess;
+
+ if (verify->coreLock) {
+ needLoad = true;
+ return;
+ }
+ needLoad = false;
+
+ prevValid = true;
+ name = curUser.local8Bit();
+ GSendInt( G_ReadDmrc );
+ GSendStr( name.data() );
+ GRecvInt(); // ignore status code ...
+ if ((len = name.length())) {
+ GSendInt( G_GetDmrc );
+ GSendStr( "Session" );
+ sess = GRecvStr();
+ if (!sess) { /* no such user */
+ if (!userView && !userList) { // don't fake if user list shown
+ prevValid = false;
+ /* simple crc32 */
+ for (crc = _forgingSeed, i = 0; i < len; i++) {
+ by = (crc & 255) ^ name[i];
+ for (b = 0; b < 8; b++)
+ by = (by >> 1) ^ (-(by & 1) & 0xedb88320);
+ crc = (crc >> 8) ^ by;
+ }
+ /* forge a session with this hash - default & custom more probable */
+ /* XXX - this should do a statistical analysis of the real users */
+#if 1
+ setPrevWM( crc % (nSpecials * 2 + nNormals) % (nSpecials + nNormals) );
+#else
+ i = crc % (nSpecials * 2 + nNormals);
+ if (i < nNormals)
+ setPrevWM( i + nSpecials );
+ else
+ setPrevWM( (i - nNormals) / 2 );
+#endif
+ return;
+ }
+ } else {
+ if (!strcmp(sess, "admin")) {
+ // need to get the original
+ GSendInt( G_GetDmrc);
+ GSendStr( "OrigSession");
+ sess = GRecvStr();
+ if (!sess) {
+ free(sess);
+ sess = strdup("default");
+ }
+ }
+
+ for (uint i = 0; i < sessionTypes.count() && !sessionTypes[i].hid; i++)
+ if (sessionTypes[i].type == sess) {
+ free( sess );
+ setPrevWM( i );
+ return;
+ }
+ if (curSel == -1)
+ MsgBox( sorrybox, i18n("Your saved session type '%1' is not valid any more.\n"
+ "Please select a new one, otherwise 'default' will be used.").arg( sess ) );
+ free( sess );
+ prevValid = false;
+ }
+ }
+ setPrevWM( -1 );
+}
+
+void // protected
+KGreeter::pluginSetup()
+{
+ int field = 0;
+ TQString ent, pn( verify->pluginName() ), dn( dName + '_' + pn );
+
+ if (_preselUser != PRESEL_PREV)
+ stsFile->deleteEntry( verify->entitiesLocal() ? dName : dn, false );
+ if (_preselUser != PRESEL_NONE && verify->entityPresettable()) {
+ if (verify->entitiesLocal())
+ ent = _preselUser == PRESEL_PREV ?
+ stsFile->readEntry( dName ) : _defaultUser;
+ else
+ ent = _preselUser == PRESEL_PREV ?
+ stsFile->readEntry( dn ) :
+ verify->getConf( 0, (pn + ".DefaultEntity").latin1(), TQVariant() ).toString();
+ field = verify->entitiesFielded() ?
+ verify->getConf( 0, (pn + ".FocusField").latin1(), TQVariant( 0 ) ).toInt() :
+ _focusPasswd;
+ }
+ verify->presetEntity( ent, field );
+ if (userList)
+ verify->loadUsers( *userList );
+}
+
+void
+KGreeter::verifyPluginChanged( int id )
+{
+ curPlugin = id;
+ pluginSetup();
+}
+
+void
+KGreeter::verifyClear()
+{
+ curUser = TQString::null;
+ slotUserEntered();
+ slotSessionSelected( -1 );
+}
+
+void
+KGreeter::verifyOk()
+{
+ if (_preselUser == PRESEL_PREV && verify->entityPresettable())
+ stsFile->writeEntry( verify->entitiesLocal() ?
+ dName :
+ dName + '_' + verify->pluginName(),
+ verify->getEntity() );
+ if (curSel != -1) {
+ GSendInt( G_PutDmrc );
+ GSendStr( "Session" );
+ GSendStr( sessionTypes[curSel].type.utf8() );
+ } else if (!prevValid) {
+ GSendInt( G_PutDmrc );
+ GSendStr( "Session" );
+ GSendStr( "default" );
+ }
+ GSendInt( G_Ready );
+ closingDown = true;
+ done( ex_exit );
+}
+
+void
+KGreeter::verifyFailed()
+{
+ if (needLoad)
+ slotLoadPrevWM();
+}
+
+void
+KGreeter::verifySetUser( const TQString &user )
+{
+ curUser = user;
+ slotUserEntered();
+}
+
+KStdGreeter::KStdGreeter()
+ : KGreeter()
+ , clock( 0 )
+ , pixLabel( 0 )
+{
+ TQBoxLayout *main_box;
+#ifdef WITH_TDM_XCONSOLE
+ if (consoleView) {
+ TQBoxLayout *ex_box = new TQVBoxLayout( this, 10, 10 );
+ main_box = new TQHBoxLayout( ex_box, 10 );
+ ex_box->addWidget( consoleView );
+ } else
+#endif
+ main_box = new TQHBoxLayout( this, 10, 10 );
+
+ if (userView)
+ main_box->addWidget( userView );
+
+ TQBoxLayout *inner_box = new TQVBoxLayout( main_box, 10 );
+
+ if (!_authorized && _authComplain) {
+ TQLabel *complainLabel = new TQLabel(
+ i18n("Warning: this is an unsecured session"), this );
+ TQToolTip::add( complainLabel,
+ i18n("This display requires no X authorization.\n"
+ "This means that anybody can connect to it,\n"
+ "open windows on it or intercept your input.") );
+ complainLabel->setAlignment( AlignCenter );
+ complainLabel->setFont( _failFont );
+ complainLabel->setPaletteForegroundColor( Qt::red );
+ inner_box->addWidget( complainLabel );
+ }
+ if (!_greetString.isEmpty()) {
+ TQLabel *welcomeLabel = new TQLabel( _greetString, this );
+ welcomeLabel->setAlignment( AlignCenter );
+ welcomeLabel->setFont( _greetFont );
+ inner_box->addWidget( welcomeLabel );
+ }
+
+ switch (_logoArea) {
+ case LOGO_CLOCK:
+ clock = new KdmClock( this, "clock" );
+ break;
+ case LOGO_LOGO:
+ {
+ TQMovie movie( _logo );
+ kapp->eventLoop()->processEvents( TQEventLoop::ExcludeUserInput | TQEventLoop::ExcludeSocketNotifiers, 100 );
+ TQPixmap pixmap;
+ if (!movie.framePixmap().isNull() || pixmap.load( _logo )) {
+ pixLabel = new TQLabel( this );
+ if (!movie.framePixmap().isNull()) {
+ pixLabel->setMovie( movie );
+ if (!movie.framePixmap().hasAlpha())
+ pixLabel->setFrameStyle( TQFrame::Panel | TQFrame::Sunken );
+ } else {
+ pixLabel->setPixmap( pixmap );
+ if (!pixmap.hasAlpha())
+ pixLabel->setFrameStyle( TQFrame::Panel | TQFrame::Sunken );
+ }
+ pixLabel->setIndent( 0 );
+ }
+ }
+ break;
+ }
+
+ if (userView) {
+ if (clock)
+ inner_box->addWidget( clock, 0, AlignCenter );
+ else if (pixLabel)
+ inner_box->addWidget( pixLabel, 0, AlignCenter );
+ } else {
+ if (clock)
+ main_box->addWidget( clock, 0, AlignCenter );
+ else if (pixLabel)
+ main_box->addWidget( pixLabel, 0, AlignCenter );
+ }
+
+ goButton = new TQPushButton( i18n("L&ogin"), this );
+ goButton->setDefault( true );
+ connect( goButton, TQT_SIGNAL(clicked()), TQT_SLOT(accept()) );
+ menuButton = new TQPushButton( i18n("&Menu"), this );
+ //helpButton
+
+ TQWidget *prec;
+ if (userView)
+ prec = userView;
+#ifdef WITH_TDM_XCONSOLE
+ else if (consoleView)
+ prec = consoleView;
+#endif
+ else
+ prec = menuButton;
+ KGStdVerify *sverify =
+ new KGStdVerify( this, this, prec, TQString::null,
+ pluginList, KGreeterPlugin::Authenticate,
+ KGreeterPlugin::Login );
+ inner_box->addLayout( sverify->getLayout() );
+ TQPopupMenu *plugMenu = sverify->getPlugMenu();
+ sverify->selectPlugin( curPlugin );
+ verify = sverify;
+
+ inner_box->addWidget( new KSeparator( KSeparator::HLine, this ) );
+
+ TQBoxLayout *hbox2 = new TQHBoxLayout( inner_box, 10 );
+ hbox2->addWidget( goButton );
+ hbox2->addStretch( 1 );
+ hbox2->addWidget( menuButton );
+ hbox2->addStretch( 1 );
+
+ if (sessMenu->count() > 1) {
+ inserten( i18n("Session &Type"), 0, sessMenu );
+ needSep = true;
+ }
+
+ if (plugMenu) {
+ inserten( i18n("&Authentication Method"), 0, plugMenu );
+ needSep = true;
+ }
+
+#ifdef XDMCP
+ completeMenu( LOGIN_LOCAL_ONLY, ex_choose, i18n("&Remote Login"), 0 );
+#else
+ completeMenu();
+#endif
+
+ if (userView || userList)
+ insertUsers();
+
+ if (optMenu)
+ menuButton->setPopup( optMenu );
+ else
+ menuButton->hide();
+
+ pluginSetup();
+
+ verify->start();
+}
+
+void
+KStdGreeter::pluginSetup()
+{
+ inherited::pluginSetup();
+ if (userView) {
+ if (verify->entitiesLocal() && verify->entityPresettable())
+ userView->show();
+ else
+ userView->hide();
+ }
+ adjustGeometry();
+ update();
+}
+
+void
+KStdGreeter::verifyFailed()
+{
+ goButton->setEnabled( false );
+ menuButton->setEnabled( false );
+ if (userView)
+ userView->setEnabled( false );
+ inherited::verifyFailed();
+}
+
+void
+KStdGreeter::verifyRetry()
+{
+ goButton->setEnabled( true );
+ menuButton->setEnabled( true );
+ if (userView)
+ userView->setEnabled( true );
+}
+
+
+KThemedGreeter::KThemedGreeter()
+ : KGreeter( true )
+ , themer( 0 )
+// , clock( 0 )
+{
+ // We do all painting ourselves
+ setBackgroundMode( NoBackground );
+ // Allow tracking the mouse position
+ setMouseTracking( true );
+
+ adjustGeometry();
+
+ themer = new KdmThemer( _theme, "console", this );
+ if (!themer->isOK()) {
+ delete themer;
+ themer = 0;
+ return;
+ }
+
+ connect( themer, TQT_SIGNAL(activated( const TQString & )),
+ TQT_SLOT(slotThemeActivated( const TQString & )) );
+
+ console_rect = themer->findNode( "xconsole" ); // tdm ext
+ userlist_rect = themer->findNode( "userlist" );
+ caps_warning = themer->findNode( "caps-lock-warning" );
+ xauth_warning = themer->findNode( "xauth-warning" ); // tdm ext
+ pam_error = themer->findNode( "pam-error" );
+ timed_label = themer->findNode( "timed-label" );
+ if (pam_error && pam_error->isA( "KdmLabel" ))
+ static_cast<KdmLabel*>(pam_error)->setText( i18n("Login Failed.") );
+
+ KdmItem *itm;
+ if ((itm = themer->findNode( "pam-message" ))) // done via msgboxes
+ itm->hide( true );
+ if ((itm = themer->findNode( "language_button" ))) // not implemented yet
+ itm->hide( true );
+
+#ifdef WITH_TDM_XCONSOLE
+ if (console_rect) {
+ if (consoleView)
+ console_rect->setWidget( consoleView );
+ else
+ console_rect->hide( true );
+ }
+#endif
+
+ if (xauth_warning && (_authorized || !_authComplain))
+ xauth_warning->hide( true );
+
+ if (userView || userList)
+ insertUsers( 7 ); // TODO: find out how many are a good value
+
+// if (!_greetString.isEmpty()) {
+// }
+// clock = new KdmClock( this, "clock" );
+
+ TQWidget *prec;
+ if (userView)
+ prec = userView;
+#ifdef WITH_TDM_XCONSOLE
+ else if (consoleView)
+ prec = consoleView;
+#endif
+ else
+ prec = 0;
+ KGThemedVerify *tverify =
+ new KGThemedVerify( this, themer, this, prec, TQString::null,
+ pluginList, KGreeterPlugin::Authenticate,
+ KGreeterPlugin::Login );
+ TQPopupMenu *plugMenu = tverify->getPlugMenu();
+ tverify->selectPlugin( curPlugin );
+ verify = tverify;
+
+ session_button = 0;
+ if ((itm = themer->findNode( "session_button" ))) {
+ if (sessMenu->count() <= 1)
+ itm->hide( true );
+ else
+ session_button = itm;
+ } else {
+ if (sessMenu->count() > 1) {
+ inserten( i18n("Session &Type"), ALT+Key_T, sessMenu );
+ needSep = true;
+ }
+ }
+
+ admin_button = themer->findNode( "admin_button");
+ if ( admin_button ) {
+ if ( !_useAdminSession )
+ admin_button->hide( true );
+ }
+
+ if (plugMenu) {
+ inserten( i18n("&Authentication Method"), ALT+Key_A, plugMenu );
+ needSep = true;
+ }
+
+#ifdef XDMCP
+ completeMenu( LOGIN_LOCAL_ONLY, ex_choose, i18n("&Remote Login"), ALT+Key_R );
+#else
+ completeMenu();
+#endif
+
+ system_button = themer->findNode( "system_button" );
+ TQAccel *accel = new TQAccel( this );
+ accel->insertItem( ALT+Key_M, 0 );
+ connect( accel, TQT_SIGNAL(activated( int )), TQT_SLOT(slotActionMenu()) );
+
+ pluginSetup();
+
+ verify->start();
+}
+
+bool
+KThemedGreeter::event( TQEvent *e )
+{
+ if (themer)
+ themer->widgetEvent( e );
+ return inherited::event( e );
+}
+
+void
+KThemedGreeter::pluginSetup()
+{
+ inherited::pluginSetup();
+
+ if (userView && verify->entitiesLocal() && verify->entityPresettable() && userlist_rect) {
+// userView->setMaximumHeight( userView->sumHeight() );
+ userlist_rect->setWidget( userView );
+ } else {
+ if (userView)
+ userView->hide();
+ if (userlist_rect)
+ userlist_rect->hide( true );
+ }
+
+ update();
+}
+
+void
+KThemedGreeter::verifyFailed()
+{
+// goButton->setEnabled( false );
+ inherited::verifyFailed();
+ if (userView)
+ userView->setEnabled(false);
+}
+
+void
+KThemedGreeter::verifyRetry()
+{
+// goButton->setEnabled( true );
+ if (userView)
+ userView->setEnabled(true);
+
+}
+
+TQString KThemedGreeter::timedUser = TQString::null;
+int KThemedGreeter::timedDelay = -1;
+
+void
+KThemedGreeter::updateStatus( bool fail, bool caps, int timedleft )
+{
+ if (pam_error) {
+ if (fail)
+ pam_error->show( true );
+ else
+ pam_error->hide( true );
+ }
+ if (caps_warning) {
+ if (caps)
+ caps_warning->show( true );
+ else
+ caps_warning->hide( true );
+ }
+ if (timed_label) {
+ if (timedleft) {
+ if (timedleft != timedDelay) {
+ timedDelay = timedleft;
+ timedUser = curUser;
+ timed_label->show( true );
+ timed_label->update();
+ }
+ } else {
+ timedDelay = -1;
+ timed_label->hide( true );
+ }
+ }
+}
+
+void
+KThemedGreeter::slotThemeActivated( const TQString &id )
+{
+ if (id == "login_button")
+ accept();
+ else if (id == "session_button")
+ slotSessMenu();
+ else if (id == "system_button")
+ slotActionMenu();
+ else if (id == "admin_button")
+ slotAskAdminPassword();
+}
+
+void
+KThemedGreeter::slotSessMenu()
+{
+ sessMenu->popup( mapToGlobal( session_button->rect().center() ) );
+}
+
+void
+KThemedGreeter::slotActionMenu()
+{
+ if (system_button)
+ optMenu->popup( mapToGlobal( system_button->rect().center() ) );
+ else
+ optMenu->popup( mapToGlobal( rect().center() ) );
+}
+
+void
+KThemedGreeter::keyPressEvent( TQKeyEvent *e )
+{
+ inherited::keyPressEvent( e );
+ if (!(e->state() & KeyButtonMask) &&
+ (e->key() == Key_Return || e->key() == Key_Enter))
+ accept();
+}
+
+void
+KThemedGreeter::slotAskAdminPassword()
+{
+ TDMAdmin k(curUser, this);
+ if (k.exec()) {
+ GSendInt(G_Ready);
+ hide();
+ closingDown = true;
+ done(ex_exit);
+ }
+}
+
+#include "kgreeter.moc"
diff --git a/tdm/kfrontend/kgreeter.h b/tdm/kfrontend/kgreeter.h
new file mode 100644
index 00000000..0de48a21
--- /dev/null
+++ b/tdm/kfrontend/kgreeter.h
@@ -0,0 +1,180 @@
+/*
+
+Greeter widget for tdm
+
+Copyright (C) 1997, 1998 Steffen Hansen <hansen@kde.org>
+Copyright (C) 2000-2004 Oswald Buddenhagen <ossi@kde.org>
+
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+
+#ifndef KGREETER_H
+#define KGREETER_H
+
+#include "kgverify.h"
+#include "kgdialog.h"
+
+class KdmClock;
+class UserListView;
+class KdmThemer;
+class KdmItem;
+
+class KListView;
+class KSimpleConfig;
+
+class TQLabel;
+class TQPushButton;
+class TQPopupMenu;
+class TQListViewItem;
+
+struct SessType {
+ TQString name, type;
+ bool hid;
+ int prio;
+
+ SessType() {}
+ SessType( const TQString &n, const TQString &t, bool h, int p ) :
+ name( n ), type( t ), hid( h ), prio( p ) {}
+ bool operator<( const SessType &st ) {
+ return hid != st.hid ? hid < st.hid :
+ prio != st.prio ? prio < st.prio :
+ name < st.name;
+ }
+};
+
+class KGreeter : public KGDialog, public KGVerifyHandler {
+ Q_OBJECT
+ typedef KGDialog inherited;
+
+ public:
+ KGreeter( bool themed = false );
+ ~KGreeter();
+
+ public slots:
+ void accept();
+ void reject();
+ void done(int r);
+ void slotUserClicked( TQListViewItem * );
+ void slotSessionSelected( int );
+ void slotUserEntered();
+ void handleInputPipe();
+
+ public:
+ TQString curUser, dName;
+
+ protected:
+ void readFacesList();
+ void installUserList();
+ void insertUser( const TQImage &, const TQString &, struct passwd * );
+ void insertUsers( int limit = -1);
+ void putSession( const TQString &, const TQString &, bool, const char * );
+ void insertSessions();
+ virtual void pluginSetup();
+ void setPrevWM( int );
+
+ KSimpleConfig *stsFile;
+ UserListView *userView;
+ TQStringList *userList;
+ TQPopupMenu *sessMenu;
+ TQValueVector<SessType> sessionTypes;
+ TQStringList randomFaces;
+ TQMap<TQString, TQString> randomFacesMap;
+ int nNormals, nSpecials;
+ int curPrev, curSel;
+ bool prevValid;
+ bool needLoad;
+ bool themed;
+
+ static int curPlugin;
+ static PluginList pluginList;
+
+ private slots:
+ void slotLoadPrevWM();
+
+ private:
+ int mPipe_fd;
+ TQString mPipeFilename;
+
+ protected:
+ bool closingDown;
+
+ public: // from KGVerifyHandler
+ virtual void verifyPluginChanged( int id );
+ virtual void verifyClear();
+ virtual void verifyOk();
+ virtual void verifyFailed();
+// virtual void verifyRetry();
+ virtual void verifySetUser( const TQString &user );
+};
+
+class KStdGreeter : public KGreeter {
+ Q_OBJECT
+ typedef KGreeter inherited;
+
+ public:
+ KStdGreeter();
+
+ protected:
+ virtual void pluginSetup();
+
+ private:
+ KdmClock *clock;
+ TQLabel *pixLabel;
+ TQPushButton *goButton;
+ TQPushButton *menuButton;
+
+ public: // from KGVerifyHandler
+ virtual void verifyFailed();
+ virtual void verifyRetry();
+};
+
+class KThemedGreeter : public KGreeter {
+ Q_OBJECT
+ typedef KGreeter inherited;
+
+ public:
+ KThemedGreeter();
+ bool isOK() { return themer != 0; }
+ static TQString timedUser;
+ static int timedDelay;
+
+ public slots:
+ void slotThemeActivated( const TQString &id );
+ void slotSessMenu();
+ void slotActionMenu();
+ void slotAskAdminPassword();
+
+ protected:
+ virtual void updateStatus( bool fail, bool caps, int timedleft );
+ virtual void pluginSetup();
+ virtual void keyPressEvent( TQKeyEvent * );
+ virtual bool event( TQEvent *e );
+
+ private:
+// KdmClock *clock;
+ KdmThemer *themer;
+ KdmItem *caps_warning, *xauth_warning, *pam_error, *timed_label,
+ *console_rect, *userlist_rect,
+ *session_button, *system_button, *admin_button;
+
+ public: // from KGVerifyHandler
+ virtual void verifyFailed();
+ virtual void verifyRetry();
+};
+
+#endif /* KGREETER_H */
diff --git a/tdm/kfrontend/kgverify.cpp b/tdm/kfrontend/kgverify.cpp
new file mode 100644
index 00000000..ec0bfae6
--- /dev/null
+++ b/tdm/kfrontend/kgverify.cpp
@@ -0,0 +1,1218 @@
+/*
+
+Shell for tdm conversation plugins
+
+Copyright (C) 1997, 1998, 2000 Steffen Hansen <hansen@kde.org>
+Copyright (C) 2000-2004 Oswald Buddenhagen <ossi@kde.org>
+
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#include <config.h>
+
+#include "kgverify.h"
+#include "tdmconfig.h"
+#include "tdm_greet.h"
+
+#include "themer/tdmthemer.h"
+#include "themer/tdmitem.h"
+
+#include <kapplication.h>
+#include <klocale.h>
+#include <klibloader.h>
+#include <kseparator.h>
+#include <kstdguiitem.h>
+#include <kpushbutton.h>
+
+#include <tqregexp.h>
+#include <tqpopupmenu.h>
+#include <tqlayout.h>
+#include <tqfile.h>
+#include <tqlabel.h>
+
+#include <pwd.h>
+#include <sys/types.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <X11/Xlib.h> // for updateLockStatus()
+#include <fixx11h.h> // ... and make eventFilter() work again
+
+#define FULL_GREET_TO 40 // normal inactivity timeout
+#define TIMED_GREET_TO 20 // inactivity timeout when persisting timed login
+#define MIN_TIMED_TO 5 // minimal timed login delay
+#define DEAD_TIMED_TO 2 // <enter> dead time after re-activating timed login
+#define SECONDS 1000 // reduce to 100 to speed up testing
+
+void KGVerifyHandler::verifyClear()
+{
+}
+
+void KGVerifyHandler::updateStatus( bool, bool, int )
+{
+}
+
+KGVerify::KGVerify( KGVerifyHandler *_handler, KdmThemer *_themer,
+ TQWidget *_parent, TQWidget *_predecessor,
+ const TQString &_fixedUser,
+ const PluginList &_pluginList,
+ KGreeterPlugin::Function _func,
+ KGreeterPlugin::Context _ctx )
+ : inherited()
+ , coreLock( 0 )
+ , fixedEntity( _fixedUser )
+ , pluginList( _pluginList )
+ , handler( _handler )
+ , themer( _themer )
+ , parent( _parent )
+ , predecessor( _predecessor )
+ , plugMenu( 0 )
+ , curPlugin( -1 )
+ , timedLeft( 0 )
+ , func( _func )
+ , ctx( _ctx )
+ , enabled( true )
+ , running( false )
+ , suspended( false )
+ , failed( false )
+ , isClear( true )
+{
+ connect( &timer, TQT_SIGNAL(timeout()), TQT_SLOT(slotTimeout()) );
+ connect( kapp, TQT_SIGNAL(activity()), TQT_SLOT(slotActivity()) );
+
+ _parent->installEventFilter( this );
+}
+
+KGVerify::~KGVerify()
+{
+ Debug( "delete %s\n", pName.data() );
+ delete greet;
+}
+
+TQPopupMenu *
+KGVerify::getPlugMenu()
+{
+ // assert( !cont );
+ if (!plugMenu) {
+ uint np = pluginList.count();
+ if (np > 1) {
+ plugMenu = new TQPopupMenu( parent );
+ connect( plugMenu, TQT_SIGNAL(activated( int )),
+ TQT_SLOT(slotPluginSelected( int )) );
+ for (uint i = 0; i < np; i++)
+ plugMenu->insertItem( i18n(greetPlugins[pluginList[i]].info->name), pluginList[i] );
+ }
+ }
+ return plugMenu;
+}
+
+bool // public
+KGVerify::entitiesLocal() const
+{
+ return greetPlugins[pluginList[curPlugin]].info->flags & kgreeterplugin_info::Local;
+}
+
+bool // public
+KGVerify::entitiesFielded() const
+{
+ return greetPlugins[pluginList[curPlugin]].info->flags & kgreeterplugin_info::Fielded;
+}
+
+bool // public
+KGVerify::entityPresettable() const
+{
+ return greetPlugins[pluginList[curPlugin]].info->flags & kgreeterplugin_info::Presettable;
+}
+
+bool // public
+KGVerify::isClassic() const
+{
+ return !strcmp( greetPlugins[pluginList[curPlugin]].info->method, "classic" );
+}
+
+TQString // public
+KGVerify::pluginName() const
+{
+ TQString name( greetPlugins[pluginList[curPlugin]].library->fileName() );
+ uint st = name.findRev( '/' ) + 1;
+ uint en = name.find( '.', st );
+ if (en - st > 7 && TQConstString( name.unicode() + st, 7 ).string() == "kgreet_")
+ st += 7;
+ return name.mid( st, en - st );
+}
+
+static void
+showWidgets( TQLayoutItem *li )
+{
+ TQWidget *w;
+ TQLayout *l;
+
+ if ((w = li->widget()))
+ w->show();
+ else if ((l = li->layout())) {
+ TQLayoutIterator it = l->iterator();
+ for (TQLayoutItem *itm = it.current(); itm; itm = ++it)
+ showWidgets( itm );
+ }
+}
+
+void // public
+KGVerify::selectPlugin( int id )
+{
+ if (pluginList.isEmpty()) {
+ MsgBox( errorbox, i18n("No greeter widget plugin loaded. Check the configuration.") );
+ ::exit( EX_UNMANAGE_DPY );
+ }
+ curPlugin = id;
+ if (plugMenu)
+ plugMenu->setItemChecked( id, true );
+ pName = ("greet_" + pluginName()).latin1();
+ Debug( "new %s\n", pName.data() );
+ greet = greetPlugins[pluginList[id]].info->create( this, themer, parent, predecessor, fixedEntity, func, ctx );
+ timeable = _autoLoginDelay && entityPresettable() && isClassic();
+}
+
+void // public
+KGVerify::loadUsers( const TQStringList &users )
+{
+ Debug( "%s->loadUsers(...)\n", pName.data() );
+ greet->loadUsers( users );
+}
+
+void // public
+KGVerify::presetEntity( const TQString &entity, int field )
+{
+ presEnt = entity;
+ presFld = field;
+}
+
+bool // private
+KGVerify::applyPreset()
+{
+ if (!presEnt.isEmpty()) {
+ Debug( "%s->presetEntity(%\"s, %d)\n", pName.data(),
+ presEnt.latin1(), presFld );
+ greet->presetEntity( presEnt, presFld );
+ if (entitiesLocal()) {
+ curUser = presEnt;
+ handler->verifySetUser( presEnt );
+ }
+ return true;
+ }
+ return false;
+}
+
+bool // private
+KGVerify::scheduleAutoLogin( bool initial )
+{
+ if (timeable) {
+ Debug( "%s->presetEntity(%\"s, -1)\n", pName.data(),
+ _autoLoginUser.latin1(), -1 );
+ greet->presetEntity( _autoLoginUser, -1 );
+ curUser = _autoLoginUser;
+ handler->verifySetUser( _autoLoginUser );
+ timer.start( 1000 );
+ if (initial) {
+ timedLeft = _autoLoginDelay;
+ deadTicks = 0;
+ } else {
+ timedLeft = QMAX( _autoLoginDelay - TIMED_GREET_TO, MIN_TIMED_TO );
+ deadTicks = DEAD_TIMED_TO;
+ }
+ updateStatus();
+ running = false;
+ isClear = true;
+ return true;
+ }
+ return false;
+}
+
+void // private
+KGVerify::performAutoLogin()
+{
+// timer.stop();
+ GSendInt( G_AutoLogin );
+ handleVerify();
+}
+
+TQString // public
+KGVerify::getEntity() const
+{
+ Debug( "%s->getEntity()\n", pName.data() );
+ TQString ent = greet->getEntity();
+ Debug( " entity: %s\n", ent.latin1() );
+ return ent;
+}
+
+void
+KGVerify::setUser( const TQString &user )
+{
+ // assert( fixedEntity.isEmpty() );
+ curUser = user;
+ Debug( "%s->setUser(%\"s)\n", pName.data(), user.latin1() );
+ greet->setUser( user );
+ gplugActivity();
+}
+
+void
+KGVerify::setPassword( const TQString &pass )
+{
+ greet->setPassword( pass );
+ gplugActivity();
+}
+
+void
+KGVerify::start()
+{
+ authTok = (func == KGreeterPlugin::ChAuthTok);
+ cont = false;
+ if (func == KGreeterPlugin::Authenticate && ctx == KGreeterPlugin::Login) {
+ if (scheduleAutoLogin( true )) {
+ if (!_autoLoginAgain)
+ _autoLoginDelay = 0, timeable = false;
+ return;
+ } else
+ applyPreset();
+ }
+ running = true;
+ Debug( "%s->start()\n", pName.data() );
+ greet->start();
+ if (!(func == KGreeterPlugin::Authenticate ||
+ ctx == KGreeterPlugin::ChangeTok ||
+ ctx == KGreeterPlugin::ExChangeTok))
+ {
+ cont = true;
+ handleVerify();
+ }
+}
+
+void
+KGVerify::abort()
+{
+ Debug( "%s->abort()\n", pName.data() );
+ greet->abort();
+ running = false;
+}
+
+void
+KGVerify::suspend()
+{
+ // assert( !cont );
+ if (running) {
+ Debug( "%s->abort()\n", pName.data() );
+ greet->abort();
+ }
+ suspended = true;
+ updateStatus();
+ timer.suspend();
+}
+
+void
+KGVerify::resume()
+{
+ timer.resume();
+ suspended = false;
+ updateLockStatus();
+ if (running) {
+ Debug( "%s->start()\n", pName.data() );
+ greet->start();
+ } else if (delayed) {
+ delayed = false;
+ running = true;
+ Debug( "%s->start()\n", pName.data() );
+ greet->start();
+ }
+}
+
+void // not a slot - called manually by greeter
+KGVerify::accept()
+{
+ Debug( "%s->next()\n", pName.data() );
+ greet->next();
+}
+
+void // private
+KGVerify::doReject( bool initial )
+{
+ // assert( !cont );
+ if (running) {
+ Debug( "%s->abort()\n", pName.data() );
+ greet->abort();
+ }
+ handler->verifyClear();
+ Debug( "%s->clear()\n", pName.data() );
+ greet->clear();
+ curUser = TQString::null;
+ if (!scheduleAutoLogin( initial )) {
+ isClear = !(isClear && applyPreset());
+ if (running) {
+ Debug( "%s->start()\n", pName.data() );
+ greet->start();
+ }
+ if (!failed)
+ timer.stop();
+ }
+}
+
+void // not a slot - called manually by greeter
+KGVerify::reject()
+{
+ doReject( true );
+}
+
+void
+KGVerify::setEnabled( bool on )
+{
+ Debug( "%s->setEnabled(%s)\n", pName.data(), on ? "true" : "false" );
+ greet->setEnabled( on );
+ enabled = on;
+ updateStatus();
+}
+
+void // private
+KGVerify::slotTimeout()
+{
+ if (failed) {
+ failed = false;
+ updateStatus();
+ Debug( "%s->revive()\n", pName.data() );
+ greet->revive();
+ handler->verifyRetry();
+ if (suspended)
+ delayed = true;
+ else {
+ running = true;
+ Debug( "%s->start()\n", pName.data() );
+ greet->start();
+ slotActivity();
+ gplugActivity();
+ if (cont)
+ handleVerify();
+ }
+ } else if (timedLeft) {
+ deadTicks--;
+ if (!--timedLeft)
+ performAutoLogin();
+ else
+ timer.start( 1000 );
+ updateStatus();
+ } else {
+ // assert( ctx == Login );
+ isClear = true;
+ doReject( false );
+ }
+}
+
+void
+KGVerify::slotActivity()
+{
+ if (timedLeft) {
+ Debug( "%s->revive()\n", pName.data() );
+ greet->revive();
+ Debug( "%s->start()\n", pName.data() );
+ greet->start();
+ running = true;
+ timedLeft = 0;
+ updateStatus();
+ timer.start( TIMED_GREET_TO * SECONDS );
+ } else if (timeable)
+ timer.start( TIMED_GREET_TO * SECONDS );
+}
+
+
+void // private static
+KGVerify::VMsgBox( TQWidget *parent, const TQString &user,
+ TQMessageBox::Icon type, const TQString &mesg )
+{
+ FDialog::box( parent, type, user.isEmpty() ?
+ mesg : i18n("Authenticating %1...\n\n").arg( user ) + mesg );
+}
+
+static const char *msgs[]= {
+ I18N_NOOP( "You are required to change your password immediately (password aged)." ),
+ I18N_NOOP( "You are required to change your password immediately (root enforced)." ),
+ I18N_NOOP( "You are not allowed to login at the moment." ),
+ I18N_NOOP( "Home folder not available." ),
+ I18N_NOOP( "Logins are not allowed at the moment.\nTry again later." ),
+ I18N_NOOP( "Your login shell is not listed in /etc/shells." ),
+ I18N_NOOP( "Root logins are not allowed." ),
+ I18N_NOOP( "Your account has expired; please contact your system administrator." )
+};
+
+void // private static
+KGVerify::VErrBox( TQWidget *parent, const TQString &user, const char *msg )
+{
+ TQMessageBox::Icon icon;
+ TQString mesg;
+
+ if (!msg) {
+ mesg = i18n("A critical error occurred.\n"
+ "Please look at TDM's logfile(s) for more information\n"
+ "or contact your system administrator.");
+ icon = errorbox;
+ } else {
+ mesg = TQString::fromLocal8Bit( msg );
+ TQString mesg1 = mesg + '.';
+ for (uint i = 0; i < as(msgs); i++)
+ if (mesg1 == msgs[i]) {
+ mesg = i18n(msgs[i]);
+ break;
+ }
+ icon = sorrybox;
+ }
+ VMsgBox( parent, user, icon, mesg );
+}
+
+void // private static
+KGVerify::VInfoBox( TQWidget *parent, const TQString &user, const char *msg )
+{
+ TQString mesg = TQString::fromLocal8Bit( msg );
+ TQRegExp rx( "^Warning: your account will expire in (\\d+) day" );
+ if (rx.search( mesg ) >= 0) {
+ int expire = rx.cap( 1 ).toInt();
+ mesg = expire ?
+ i18n("Your account expires tomorrow.",
+ "Your account expires in %n days.", expire) :
+ i18n("Your account expires today.");
+ } else {
+ rx.setPattern( "^Warning: your password will expire in (\\d+) day" );
+ if (rx.search( mesg ) >= 0) {
+ int expire = rx.cap( 1 ).toInt();
+ mesg = expire ?
+ i18n("Your password expires tomorrow.",
+ "Your password expires in %n days.", expire) :
+ i18n("Your password expires today.");
+ }
+ }
+ VMsgBox( parent, user, infobox, mesg );
+}
+
+bool // public static
+KGVerify::handleFailVerify( TQWidget *parent )
+{
+ Debug( "handleFailVerify ...\n" );
+ char *msg = GRecvStr();
+ TQString user = TQString::fromLocal8Bit( msg );
+ free( msg );
+
+ for (;;) {
+ int ret = GRecvInt();
+
+ // non-terminal status
+ switch (ret) {
+ /* case V_PUT_USER: cannot happen - we are in "classic" mode */
+ /* case V_PRE_OK: cannot happen - not in ChTok dialog */
+ /* case V_CHTOK: cannot happen - called by non-interactive verify */
+ case V_CHTOK_AUTH:
+ Debug( " V_CHTOK_AUTH\n" );
+ {
+ TQStringList pgs( _pluginsLogin );
+ pgs += _pluginsShutdown;
+ TQStringList::ConstIterator it;
+ for (it = pgs.begin(); it != pgs.end(); ++it)
+ if (*it == "classic" || *it == "modern") {
+ pgs = *it;
+ goto gotit;
+ } else if (*it == "generic") {
+ pgs = "modern";
+ goto gotit;
+ }
+ pgs = "classic";
+ gotit:
+ KGChTok chtok( parent, user, init( pgs ), 0,
+ KGreeterPlugin::AuthChAuthTok,
+ KGreeterPlugin::Login );
+ return chtok.exec();
+ }
+ case V_MSG_ERR:
+ Debug( " V_MSG_ERR\n" );
+ msg = GRecvStr();
+ Debug( " message %\"s\n", msg );
+ VErrBox( parent, user, msg );
+ if (msg)
+ free( msg );
+ continue;
+ case V_MSG_INFO:
+ Debug( " V_MSG_INFO\n" );
+ msg = GRecvStr();
+ Debug( " message %\"s\n", msg );
+ VInfoBox( parent, user, msg );
+ free( msg );
+ continue;
+ }
+
+ // terminal status
+ switch (ret) {
+ case V_OK:
+ Debug( " V_OK\n" );
+ return true;
+ case V_AUTH:
+ Debug( " V_AUTH\n" );
+ VMsgBox( parent, user, sorrybox, i18n("Authentication failed") );
+ return false;
+ case V_FAIL:
+ Debug( " V_FAIL\n" );
+ return false;
+ default:
+ LogPanic( "Unknown V_xxx code %d from core\n", ret );
+ }
+ }
+}
+
+void // private
+KGVerify::handleVerify()
+{
+ TQString user;
+
+ Debug( "handleVerify ...\n" );
+ for (;;) {
+ char *msg;
+ int ret, echo, ndelay;
+ KGreeterPlugin::Function nfunc;
+
+ ret = GRecvInt();
+
+ // requests
+ coreLock = 1;
+ switch (ret) {
+ case V_GET_TEXT:
+ Debug( " V_GET_TEXT\n" );
+ msg = GRecvStr();
+ Debug( " prompt %\"s\n", msg );
+ echo = GRecvInt();
+ Debug( " echo = %d\n", echo );
+ ndelay = GRecvInt();
+ Debug( " ndelay = %d\n%s->textPrompt(...)\n", ndelay, pName.data() );
+ greet->textPrompt( msg, echo, ndelay );
+ if (msg)
+ free( msg );
+ return;
+ case V_GET_BINARY:
+ Debug( " V_GET_BINARY\n" );
+ msg = GRecvArr( &ret );
+ Debug( " %d bytes prompt\n", ret );
+ ndelay = GRecvInt();
+ Debug( " ndelay = %d\n%s->binaryPrompt(...)\n", ndelay, pName.data() );
+ greet->binaryPrompt( msg, ndelay );
+ if (msg)
+ free( msg );
+ return;
+ }
+
+ // non-terminal status
+ coreLock = 2;
+ switch (ret) {
+ case V_PUT_USER:
+ Debug( " V_PUT_USER\n" );
+ msg = GRecvStr();
+ curUser = user = TQString::fromLocal8Bit( msg );
+ // greet needs this to be able to return something useful from
+ // getEntity(). but the backend is still unable to tell a domain ...
+ Debug( " %s->setUser(%\"s)\n", pName.data(), user.latin1() );
+ greet->setUser( curUser );
+ handler->verifySetUser( curUser );
+ if (msg)
+ free( msg );
+ continue;
+ case V_PRE_OK: // this is only for func == AuthChAuthTok
+ Debug( " V_PRE_OK\n" );
+ // With the "classic" method, the wrong user simply cannot be
+ // authenticated, even with the generic plugin. Other methods
+ // could do so, but this applies only to ctx == ChangeTok, which
+ // is not implemented yet.
+ authTok = true;
+ cont = true;
+ Debug( "%s->succeeded()\n", pName.data() );
+ greet->succeeded();
+ continue;
+ case V_CHTOK_AUTH:
+ Debug( " V_CHTOK_AUTH\n" );
+ nfunc = KGreeterPlugin::AuthChAuthTok;
+ user = curUser;
+ goto dchtok;
+ case V_CHTOK:
+ Debug( " V_CHTOK\n" );
+ nfunc = KGreeterPlugin::ChAuthTok;
+ user = TQString::null;
+ dchtok:
+ {
+ timer.stop();
+ Debug( "%s->succeeded()\n", pName.data() );
+ greet->succeeded();
+ KGChTok chtok( parent, user, pluginList, curPlugin, nfunc, KGreeterPlugin::Login );
+ if (!chtok.exec())
+ goto retry;
+ handler->verifyOk();
+ return;
+ }
+ case V_MSG_ERR:
+ Debug( " V_MSG_ERR\n" );
+ msg = GRecvStr();
+ Debug( " %s->textMessage(%\"s, true)\n", pName.data(), msg );
+ if (!greet->textMessage( msg, true )) {
+ Debug( " message passed\n" );
+ VErrBox( parent, user, msg );
+ } else
+ Debug( " message swallowed\n" );
+ if (msg)
+ free( msg );
+ continue;
+ case V_MSG_INFO:
+ Debug( " V_MSG_INFO\n" );
+ msg = GRecvStr();
+ Debug( " %s->textMessage(%\"s, false)\n", pName.data(), msg );
+ if (!greet->textMessage( msg, false )) {
+ Debug( " message passed\n" );
+ VInfoBox( parent, user, msg );
+ } else
+ Debug( " message swallowed\n" );
+ free( msg );
+ continue;
+ }
+
+ // terminal status
+ coreLock = 0;
+ running = false;
+ timer.stop();
+
+ if (ret == V_OK) {
+ Debug( " V_OK\n" );
+ if (!fixedEntity.isEmpty()) {
+ Debug( " %s->getEntity()\n", pName.data() );
+ TQString ent = greet->getEntity();
+ Debug( " entity %\"s\n", ent.latin1() );
+ if (ent != fixedEntity) {
+ Debug( "%s->failed()\n", pName.data() );
+ greet->failed();
+ MsgBox( sorrybox,
+ i18n("Authenticated user (%1) does not match requested user (%2).\n")
+ .arg( ent ).arg( fixedEntity ) );
+ goto retry;
+ }
+ }
+ Debug( "%s->succeeded()\n", pName.data() );
+ greet->succeeded();
+ handler->verifyOk();
+ return;
+ }
+
+ Debug( "%s->failed()\n", pName.data() );
+ greet->failed();
+
+ if (ret == V_AUTH) {
+ Debug( " V_AUTH\n" );
+ failed = true;
+ updateStatus();
+ handler->verifyFailed();
+ timer.start( 1500 + kapp->random()/(RAND_MAX/1000) );
+ return;
+ }
+ if (ret != V_FAIL)
+ LogPanic( "Unknown V_xxx code %d from core\n", ret );
+ Debug( " V_FAIL\n" );
+ retry:
+ Debug( "%s->revive()\n", pName.data() );
+ greet->revive();
+ running = true;
+ Debug( "%s->start()\n", pName.data() );
+ greet->start();
+ if (!cont)
+ return;
+ user = TQString::null;
+ }
+}
+
+void
+KGVerify::gplugReturnText( const char *text, int tag )
+{
+ Debug( "%s: gplugReturnText(%\"s, %d)\n", pName.data(),
+ tag & V_IS_SECRET ? "<masked>" : text, tag );
+ GSendStr( text );
+ if (text) {
+ GSendInt( tag );
+ handleVerify();
+ } else
+ coreLock = 0;
+}
+
+void
+KGVerify::gplugReturnBinary( const char *data )
+{
+ if (data) {
+ unsigned const char *up = (unsigned const char *)data;
+ int len = up[3] | (up[2] << 8) | (up[1] << 16) | (up[0] << 24);
+ Debug( "%s: gplugReturnBinary(%d bytes)\n", pName.data(), len );
+ GSendArr( len, data );
+ handleVerify();
+ } else {
+ Debug( "%s: gplugReturnBinary(NULL)\n", pName.data() );
+ GSendArr( 0, 0 );
+ coreLock = 0;
+ }
+}
+
+void
+KGVerify::gplugSetUser( const TQString &user )
+{
+ Debug( "%s: gplugSetUser(%\"s)\n", pName.data(), user.latin1() );
+ curUser = user;
+ handler->verifySetUser( user );
+}
+
+void
+KGVerify::gplugStart()
+{
+ // XXX handle func != Authenticate
+ Debug( "%s: gplugStart()\n", pName.data() );
+ GSendInt( ctx == KGreeterPlugin::Shutdown ? G_VerifyRootOK : G_Verify );
+ GSendStr( greetPlugins[pluginList[curPlugin]].info->method );
+ handleVerify();
+}
+
+void
+KGVerify::gplugActivity()
+{
+ Debug( "%s: gplugActivity()\n", pName.data() );
+ if (func == KGreeterPlugin::Authenticate &&
+ ctx == KGreeterPlugin::Login)
+ {
+ isClear = false;
+ if (!timeable)
+ timer.start( FULL_GREET_TO * SECONDS );
+ }
+}
+
+void
+KGVerify::gplugMsgBox( TQMessageBox::Icon type, const TQString &text )
+{
+ Debug( "%s: gplugMsgBox(%d, %\"s)\n", pName.data(), type, text.latin1() );
+ MsgBox( type, text );
+}
+
+bool
+KGVerify::eventFilter( TQObject *o, TQEvent *e )
+{
+ switch (e->type()) {
+ case TQEvent::KeyPress:
+ if (timedLeft) {
+ TQKeyEvent *ke = (TQKeyEvent *)e;
+ if (ke->key() == Key_Return || ke->key() == Key_Enter) {
+ if (deadTicks <= 0) {
+ timedLeft = 0;
+ performAutoLogin();
+ }
+ return true;
+ }
+ }
+ /* fall through */
+ case TQEvent::KeyRelease:
+ updateLockStatus();
+ /* fall through */
+ default:
+ break;
+ }
+ return inherited::eventFilter( o, e );
+}
+
+void
+KGVerify::updateLockStatus()
+{
+ unsigned int lmask;
+ Window dummy1, dummy2;
+ int dummy3, dummy4, dummy5, dummy6;
+ XQueryPointer( qt_xdisplay(), DefaultRootWindow( qt_xdisplay() ),
+ &dummy1, &dummy2, &dummy3, &dummy4, &dummy5, &dummy6,
+ &lmask );
+ capsLocked = lmask & LockMask;
+ updateStatus();
+}
+
+void
+KGVerify::MsgBox( TQMessageBox::Icon typ, const TQString &msg )
+{
+ timer.suspend();
+ FDialog::box( parent, typ, msg );
+ timer.resume();
+}
+
+
+TQVariant // public static
+KGVerify::getConf( void *, const char *key, const TQVariant &dflt )
+{
+ if (!qstrcmp( key, "EchoMode" ))
+ return TQVariant( _echoMode );
+ else {
+ TQString fkey = TQString::fromLatin1( key ) + '=';
+ for (TQStringList::ConstIterator it = _pluginOptions.begin();
+ it != _pluginOptions.end(); ++it)
+ if ((*it).startsWith( fkey ))
+ return (*it).mid( fkey.length() );
+ return dflt;
+ }
+}
+
+TQValueVector<GreeterPluginHandle> KGVerify::greetPlugins;
+
+PluginList
+KGVerify::init( const TQStringList &plugins )
+{
+ PluginList pluginList;
+
+ for (TQStringList::ConstIterator it = plugins.begin(); it != plugins.end(); ++it) {
+ GreeterPluginHandle plugin;
+ TQString path = KLibLoader::self()->findLibrary(
+ ((*it)[0] == '/' ? *it : "kgreet_" + *it ).latin1() );
+ if (path.isEmpty()) {
+ LogError( "GreeterPlugin %s does not exist\n", (*it).latin1() );
+ continue;
+ }
+ uint i, np = greetPlugins.count();
+ for (i = 0; i < np; i++)
+ if (greetPlugins[i].library->fileName() == path)
+ goto next;
+ if (!(plugin.library = KLibLoader::self()->library( path.latin1() ))) {
+ LogError( "Cannot load GreeterPlugin %s (%s)\n", (*it).latin1(), path.latin1() );
+ continue;
+ }
+ if (!plugin.library->hasSymbol( "kgreeterplugin_info" )) {
+ LogError( "GreeterPlugin %s (%s) is no valid greet widget plugin\n",
+ (*it).latin1(), path.latin1() );
+ plugin.library->unload();
+ continue;
+ }
+ plugin.info = (kgreeterplugin_info*)plugin.library->symbol( "kgreeterplugin_info" );
+ if (!plugin.info->init( TQString::null, getConf, 0 )) {
+ LogError( "GreeterPlugin %s (%s) refuses to serve\n",
+ (*it).latin1(), path.latin1() );
+ plugin.library->unload();
+ continue;
+ }
+ Debug( "GreeterPlugin %s (%s) loaded\n", (*it).latin1(), plugin.info->name );
+ greetPlugins.append( plugin );
+ next:
+ pluginList.append( i );
+ }
+ return pluginList;
+}
+
+void
+KGVerify::done()
+{
+ for (uint i = 0; i < greetPlugins.count(); i++) {
+ if (greetPlugins[i].info->done)
+ greetPlugins[i].info->done();
+ greetPlugins[i].library->unload();
+ }
+}
+
+
+KGStdVerify::KGStdVerify( KGVerifyHandler *_handler, TQWidget *_parent,
+ TQWidget *_predecessor, const TQString &_fixedUser,
+ const PluginList &_pluginList,
+ KGreeterPlugin::Function _func,
+ KGreeterPlugin::Context _ctx )
+ : inherited( _handler, 0, _parent, _predecessor, _fixedUser,
+ _pluginList, _func, _ctx )
+ , failedLabelState( 0 )
+{
+ grid = new TQGridLayout;
+ grid->setAlignment( AlignCenter );
+
+ failedLabel = new TQLabel( parent );
+ failedLabel->setFont( _failFont );
+ grid->addWidget( failedLabel, 1, 0, Qt::AlignCenter );
+
+ updateLockStatus();
+}
+
+KGStdVerify::~KGStdVerify()
+{
+ grid->removeItem( greet->getLayoutItem() );
+}
+
+void // public
+KGStdVerify::selectPlugin( int id )
+{
+ inherited::selectPlugin( id );
+ grid->addItem( greet->getLayoutItem(), 0, 0 );
+ showWidgets( greet->getLayoutItem() );
+}
+
+void // private slot
+KGStdVerify::slotPluginSelected( int id )
+{
+ if (failed)
+ return;
+ if (id != curPlugin) {
+ plugMenu->setItemChecked( curPlugin, false );
+ parent->setUpdatesEnabled( false );
+ grid->removeItem( greet->getLayoutItem() );
+ Debug( "delete %s\n", pName.data() );
+ delete greet;
+ selectPlugin( id );
+ handler->verifyPluginChanged( id );
+ if (running)
+ start();
+ parent->setUpdatesEnabled( true );
+ }
+}
+
+void
+KGStdVerify::updateStatus()
+{
+ int nfls;
+
+ if (!enabled)
+ nfls = 1;
+ else if (failed)
+ nfls = 2;
+ else if (timedLeft)
+ nfls = -timedLeft;
+ else if (!suspended && capsLocked)
+ nfls = 3;
+ else
+ nfls = 1;
+
+ if (failedLabelState != nfls) {
+ failedLabelState = nfls;
+ if (nfls < 0) {
+ failedLabel->setPaletteForegroundColor( Qt::black );
+ failedLabel->setText( i18n( "Automatic login in 1 second...",
+ "Automatic login in %n seconds...",
+ timedLeft ) );
+ } else {
+ switch (nfls) {
+ default:
+ failedLabel->clear();
+ break;
+ case 3:
+ failedLabel->setPaletteForegroundColor( Qt::red );
+ failedLabel->setText( i18n("Warning: Caps Lock on") );
+ break;
+ case 2:
+ failedLabel->setPaletteForegroundColor( Qt::black );
+ failedLabel->setText( authTok ?
+ i18n("Change failed") :
+ fixedEntity.isEmpty() ?
+ i18n("Login failed") :
+ i18n("Authentication failed") );
+ break;
+ }
+ }
+ }
+}
+
+KGThemedVerify::KGThemedVerify( KGVerifyHandler *_handler,
+ KdmThemer *_themer,
+ TQWidget *_parent, TQWidget *_predecessor,
+ const TQString &_fixedUser,
+ const PluginList &_pluginList,
+ KGreeterPlugin::Function _func,
+ KGreeterPlugin::Context _ctx )
+ : inherited( _handler, _themer, _parent, _predecessor, _fixedUser,
+ _pluginList, _func, _ctx )
+{
+ updateLockStatus();
+}
+
+KGThemedVerify::~KGThemedVerify()
+{
+}
+
+void // public
+KGThemedVerify::selectPlugin( int id )
+{
+ inherited::selectPlugin( id );
+ TQLayoutItem *l;
+ KdmItem *n;
+ if (themer && (l = greet->getLayoutItem())) {
+ if (!(n = themer->findNode( "talker" )))
+ MsgBox( errorbox,
+ i18n("Theme not usable with authentication method '%1'.")
+ .arg( i18n(greetPlugins[pluginList[id]].info->name) ) );
+ else {
+ n->setLayoutItem( l );
+ showWidgets( l );
+ }
+ }
+ if (themer)
+ themer->updateGeometry( true );
+}
+
+void // private slot
+KGThemedVerify::slotPluginSelected( int id )
+{
+ if (failed)
+ return;
+ if (id != curPlugin) {
+ plugMenu->setItemChecked( curPlugin, false );
+ Debug( "delete %s\n", pName.data() );
+ delete greet;
+ selectPlugin( id );
+ handler->verifyPluginChanged( id );
+ if (running)
+ start();
+ }
+}
+
+void
+KGThemedVerify::updateStatus()
+{
+ handler->updateStatus( enabled && failed,
+ enabled && !suspended && capsLocked,
+ timedLeft );
+}
+
+
+KGChTok::KGChTok( TQWidget *_parent, const TQString &user,
+ const PluginList &pluginList, int curPlugin,
+ KGreeterPlugin::Function func,
+ KGreeterPlugin::Context ctx )
+ : inherited( _parent )
+ , verify( 0 )
+{
+ TQSizePolicy fp( TQSizePolicy::Fixed, TQSizePolicy::Fixed );
+ okButton = new KPushButton( KStdGuiItem::ok(), this );
+ okButton->setSizePolicy( fp );
+ okButton->setDefault( true );
+ cancelButton = new KPushButton( KStdGuiItem::cancel(), this );
+ cancelButton->setSizePolicy( fp );
+
+ verify = new KGStdVerify( this, this, cancelButton, user, pluginList, func, ctx );
+ verify->selectPlugin( curPlugin );
+
+ TQVBoxLayout *box = new TQVBoxLayout( this, 10 );
+
+ box->addWidget( new TQLabel( i18n("Changing authentication token"), this ), 0, AlignHCenter );
+
+ box->addLayout( verify->getLayout() );
+
+ box->addWidget( new KSeparator( KSeparator::HLine, this ) );
+
+ TQHBoxLayout *hlay = new TQHBoxLayout( box );
+ hlay->addStretch( 1 );
+ hlay->addWidget( okButton );
+ hlay->addStretch( 1 );
+ hlay->addWidget( cancelButton );
+ hlay->addStretch( 1 );
+
+ connect( okButton, TQT_SIGNAL(clicked()), TQT_SLOT(accept()) );
+ connect( cancelButton, TQT_SIGNAL(clicked()), TQT_SLOT(reject()) );
+
+ TQTimer::singleShot( 0, verify, TQT_SLOT(start()) );
+}
+
+KGChTok::~KGChTok()
+{
+ hide();
+ delete verify;
+}
+
+void
+KGChTok::accept()
+{
+ verify->accept();
+}
+
+void
+KGChTok::verifyPluginChanged( int )
+{
+ // cannot happen
+}
+
+void
+KGChTok::verifyOk()
+{
+ inherited::accept();
+}
+
+void
+KGChTok::verifyFailed()
+{
+ okButton->setEnabled( false );
+ cancelButton->setEnabled( false );
+}
+
+void
+KGChTok::verifyRetry()
+{
+ okButton->setEnabled( true );
+ cancelButton->setEnabled( true );
+}
+
+void
+KGChTok::verifySetUser( const TQString & )
+{
+ // cannot happen
+}
+
+
+////// helper class, nuke when qtimer supports suspend()/resume()
+
+QXTimer::QXTimer()
+ : inherited( 0 )
+ , left( -1 )
+{
+ connect( &timer, TQT_SIGNAL(timeout()), TQT_SLOT(slotTimeout()) );
+}
+
+void
+QXTimer::start( int msec )
+{
+ left = msec;
+ timer.start( left, true );
+ gettimeofday( &stv, 0 );
+}
+
+void
+QXTimer::stop()
+{
+ timer.stop();
+ left = -1;
+}
+
+void
+QXTimer::suspend()
+{
+ if (timer.isActive()) {
+ timer.stop();
+ struct timeval tv;
+ gettimeofday( &tv, 0 );
+ left -= (tv.tv_sec - stv.tv_sec) * 1000 + (tv.tv_usec - stv.tv_usec) / 1000;
+ if (left < 0)
+ left = 0;
+ }
+}
+
+void
+QXTimer::resume()
+{
+ if (left >= 0 && !timer.isActive()) {
+ timer.start( left, true );
+ gettimeofday( &stv, 0 );
+ }
+}
+
+void
+QXTimer::slotTimeout()
+{
+ left = 0;
+ emit timeout();
+}
+
+
+#include "kgverify.moc"
diff --git a/tdm/kfrontend/kgverify.h b/tdm/kfrontend/kgverify.h
new file mode 100644
index 00000000..44fab973
--- /dev/null
+++ b/tdm/kfrontend/kgverify.h
@@ -0,0 +1,249 @@
+/*
+
+Shell for tdm conversation plugins
+
+Copyright (C) 1997, 1998 Steffen Hansen <hansen@kde.org>
+Copyright (C) 2000-2004 Oswald Buddenhagen <ossi@kde.org>
+
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+
+#ifndef KGVERIFY_H
+#define KGVERIFY_H
+
+#include "kgreeterplugin.h"
+#include "kfdialog.h"
+
+#include <tqlayout.h>
+#include <tqtimer.h>
+#include <tqvaluevector.h>
+
+#include <sys/time.h>
+#include <time.h>
+
+// helper class, nuke when qt supports suspend()/resume()
+class QXTimer : public TQObject {
+ Q_OBJECT
+ typedef TQObject inherited;
+
+ public:
+ QXTimer();
+ void start( int msec );
+ void stop();
+ void suspend();
+ void resume();
+
+ signals:
+ void timeout();
+
+ private slots:
+ void slotTimeout();
+
+ private:
+ TQTimer timer;
+ struct timeval stv;
+ long left;
+};
+
+class KGVerifyHandler {
+ public:
+ virtual void verifyPluginChanged( int id ) = 0;
+ virtual void verifyClear();
+ virtual void verifyOk() = 0;
+ virtual void verifyFailed() = 0;
+ virtual void verifyRetry() = 0;
+ virtual void verifySetUser( const TQString &user ) = 0;
+ virtual void updateStatus( bool fail, bool caps, int left ); // for themed only
+};
+
+class TQWidget;
+class TQLabel;
+class TQPopupMenu;
+class TQTimer;
+class KPushButton;
+class KLibrary;
+
+struct GreeterPluginHandle {
+ KLibrary *library;
+ kgreeterplugin_info *info;
+};
+
+typedef TQValueVector<int> PluginList;
+
+class KGVerify : public TQObject, public KGreeterPluginHandler {
+ Q_OBJECT
+ typedef TQObject inherited;
+
+ public:
+ KGVerify( KGVerifyHandler *handler, KdmThemer *themer,
+ TQWidget *parent, TQWidget *predecessor,
+ const TQString &fixedEntity, const PluginList &pluginList,
+ KGreeterPlugin::Function func, KGreeterPlugin::Context ctx );
+ virtual ~KGVerify();
+ TQPopupMenu *getPlugMenu();
+ void loadUsers( const TQStringList &users );
+ void presetEntity( const TQString &entity, int field );
+ TQString getEntity() const;
+ void setUser( const TQString &user );
+ void setPassword( const TQString &pass );
+ /* virtual */ void selectPlugin( int id );
+ bool entitiesLocal() const;
+ bool entitiesFielded() const;
+ bool entityPresettable() const;
+ bool isClassic() const;
+ TQString pluginName() const;
+ void setEnabled( bool on );
+ void abort();
+ void suspend();
+ void resume();
+ void accept();
+ void reject();
+
+ int coreLock;
+
+ static bool handleFailVerify( TQWidget *parent );
+ static PluginList init( const TQStringList &plugins );
+ static void done();
+
+ public slots:
+ void start();
+
+ protected:
+ bool eventFilter( TQObject *, TQEvent * );
+ void MsgBox( TQMessageBox::Icon typ, const TQString &msg );
+ void setTimer();
+ void updateLockStatus();
+ virtual void updateStatus() = 0;
+ void handleVerify();
+
+ QXTimer timer;
+ TQString fixedEntity, presEnt, curUser;
+ PluginList pluginList;
+ KGVerifyHandler *handler;
+ KdmThemer *themer;
+ TQWidget *parent, *predecessor;
+ KGreeterPlugin *greet;
+ TQPopupMenu *plugMenu;
+ int curPlugin, presFld, timedLeft, deadTicks;
+ TQCString pName;
+ KGreeterPlugin::Function func;
+ KGreeterPlugin::Context ctx;
+ bool capsLocked;
+ bool enabled, running, suspended, failed, delayed, cont;
+ bool authTok, isClear, timeable;
+
+ static void VMsgBox( TQWidget *parent, const TQString &user, TQMessageBox::Icon type, const TQString &mesg );
+ static void VErrBox( TQWidget *parent, const TQString &user, const char *msg );
+ static void VInfoBox( TQWidget *parent, const TQString &user, const char *msg );
+
+ static TQValueVector<GreeterPluginHandle> greetPlugins;
+
+ private:
+ bool applyPreset();
+ void performAutoLogin();
+ bool scheduleAutoLogin( bool initial );
+ void doReject( bool initial );
+
+ private slots:
+ //virtual void slotPluginSelected( int id ) = 0;
+ void slotTimeout();
+ void slotActivity();
+
+ public: // from KGreetPluginHandler
+ virtual void gplugReturnText( const char *text, int tag );
+ virtual void gplugReturnBinary( const char *data );
+ virtual void gplugSetUser( const TQString &user );
+ virtual void gplugStart();
+ virtual void gplugActivity();
+ virtual void gplugMsgBox( TQMessageBox::Icon type, const TQString &text );
+
+ static TQVariant getConf( void *ctx, const char *key, const TQVariant &dflt );
+};
+
+class KGStdVerify : public KGVerify {
+ Q_OBJECT
+ typedef KGVerify inherited;
+
+ public:
+ KGStdVerify( KGVerifyHandler *handler, TQWidget *parent,
+ TQWidget *predecessor, const TQString &fixedEntity,
+ const PluginList &pluginList,
+ KGreeterPlugin::Function func, KGreeterPlugin::Context ctx );
+ virtual ~KGStdVerify();
+ TQLayout *getLayout() const { return TQT_TQLAYOUT(grid); }
+ void selectPlugin( int id );
+
+ protected:
+ void updateStatus();
+
+ private:
+ TQGridLayout *grid;
+ TQLabel *failedLabel;
+ int failedLabelState;
+
+ private slots:
+ void slotPluginSelected( int id );
+};
+
+class KGThemedVerify : public KGVerify {
+ Q_OBJECT
+ typedef KGVerify inherited;
+
+ public:
+ KGThemedVerify( KGVerifyHandler *handler, KdmThemer *themer,
+ TQWidget *parent, TQWidget *predecessor,
+ const TQString &fixedEntity,
+ const PluginList &pluginList,
+ KGreeterPlugin::Function func,
+ KGreeterPlugin::Context ctx );
+ virtual ~KGThemedVerify();
+ void selectPlugin( int id );
+
+ protected:
+ void updateStatus();
+
+ private slots:
+ void slotPluginSelected( int id );
+};
+
+class KGChTok : public FDialog, public KGVerifyHandler {
+ Q_OBJECT
+ typedef FDialog inherited;
+
+ public:
+ KGChTok( TQWidget *parent, const TQString &user,
+ const PluginList &pluginList, int curPlugin,
+ KGreeterPlugin::Function func, KGreeterPlugin::Context ctx );
+ ~KGChTok();
+
+ public slots:
+ void accept();
+
+ private:
+ KPushButton *okButton, *cancelButton;
+ KGStdVerify *verify;
+
+ public: // from KGVerifyHandler
+ virtual void verifyPluginChanged( int id );
+ virtual void verifyOk();
+ virtual void verifyFailed();
+ virtual void verifyRetry();
+ virtual void verifySetUser( const TQString &user );
+};
+
+#endif /* KGVERIFY_H */
diff --git a/tdm/kfrontend/krootimage.cpp b/tdm/kfrontend/krootimage.cpp
new file mode 100644
index 00000000..b5136748
--- /dev/null
+++ b/tdm/kfrontend/krootimage.cpp
@@ -0,0 +1,140 @@
+/*
+
+Copyright (C) 1999 Matthias Hoelzer-Kluepfel <hoelzer@kde.org>
+Copyright (C) 2002,2004 Oswald Buddenhagen <ossi@kde.org>
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public
+License version 2 as published by the Free Software Foundation.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; see the file COPYING. If not, write to
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA.
+
+*/
+
+#include <config.h>
+
+#include <kcmdlineargs.h>
+#include <ksimpleconfig.h>
+#include <klocale.h>
+
+#include <tqfile.h>
+
+#include "krootimage.h"
+
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+
+#include <stdlib.h>
+
+static const char description[] =
+ I18N_NOOP( "Fancy desktop background for tdm" );
+
+static const char version[] = "v2.0";
+
+static KCmdLineOptions options[] = {
+ { "+config", I18N_NOOP( "Name of the configuration file" ), 0 },
+ KCmdLineLastOption
+};
+
+static Atom prop_root;
+static bool properties_inited = false;
+
+MyApplication::MyApplication( const char *conf )
+ : KApplication(),
+ renderer( 0, new KSimpleConfig( TQFile::decodeName( conf ) ) )
+{
+ connect( &timer, TQT_SIGNAL(timeout()), TQT_SLOT(slotTimeout()) );
+ connect( &renderer, TQT_SIGNAL(imageDone( int )), this, TQT_SLOT(renderDone()) );
+ renderer.enableTiling( true ); // optimize
+ renderer.changeWallpaper(); // cannot do it when we're killed, so do it now
+ timer.start( 60000 );
+ renderer.start();
+
+ if( !properties_inited ) {
+ prop_root = XInternAtom(qt_xdisplay(), "_XROOTPMAP_ID", False);
+ properties_inited = true;
+ }
+}
+
+
+void
+MyApplication::renderDone()
+{
+ // Get the newly drawn pixmap...
+ TQPixmap pm = renderer.pixmap();
+
+ // ...set it to the desktop widget...
+ TQT_TQWIDGET(desktop())->setBackgroundPixmap( pm );
+ TQT_TQWIDGET(desktop())->repaint( true );
+
+ // ...and export it via Esetroot-style so that composition managers can use it!
+ Pixmap bgPm = pm.handle(); // fetch the actual X handle to it
+ XChangeProperty(qt_xdisplay(), qt_xrootwin(), prop_root, XA_PIXMAP, 32, PropModeReplace, (unsigned char *) &bgPm, 1);
+
+ renderer.saveCacheFile();
+ renderer.cleanup();
+ for (unsigned i=0; i<renderer.numRenderers(); ++i)
+ {
+ KBackgroundRenderer * r = renderer.renderer(i);
+ if (r->backgroundMode() == KBackgroundSettings::Program ||
+ (r->multiWallpaperMode() != KBackgroundSettings::NoMulti &&
+ r->multiWallpaperMode() != KBackgroundSettings::NoMultiRandom)) {
+ return;
+ }
+ }
+
+}
+
+void
+MyApplication::slotTimeout()
+{
+ bool change = false;
+
+ if (renderer.needProgramUpdate()) {
+ renderer.programUpdate();
+ change = true;
+ }
+
+ if (renderer.needWallpaperChange()) {
+ renderer.changeWallpaper();
+ change = true;
+ }
+
+ if (change)
+ renderer.start();
+}
+
+int
+main( int argc, char *argv[] )
+{
+ KApplication::disableAutoDcopRegistration();
+
+ KLocale::setMainCatalogue( "kdesktop" );
+ KCmdLineArgs::init( argc, argv, "krootimage", I18N_NOOP( "KRootImage" ), description, version );
+ KCmdLineArgs::addCmdLineOptions( options );
+
+ KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
+ if (!args->count())
+ args->usage();
+ MyApplication app( args->arg( 0 ) );
+ args->clear();
+
+ app.exec();
+
+ app.flushX();
+
+ // Keep color resources after termination
+ XSetCloseDownMode( qt_xdisplay(), RetainTemporary );
+
+ return 0;
+}
+
+#include "krootimage.moc"
diff --git a/tdm/kfrontend/krootimage.h b/tdm/kfrontend/krootimage.h
new file mode 100644
index 00000000..e4619011
--- /dev/null
+++ b/tdm/kfrontend/krootimage.h
@@ -0,0 +1,48 @@
+/*
+
+Copyright (C) 1999 Matthias Hoelzer-Kluepfel <hoelzer@kde.org>
+Copyright (C) 2002,2004 Oswald Buddenhagen <ossi@kde.org>
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public
+License version 2 as published by the Free Software Foundation.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; see the file COPYING. If not, write to
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA.
+
+*/
+
+#ifndef __TDMDESKTOP_H__
+#define __TDMDESKTOP_H__
+
+
+#include <kapplication.h>
+#include <tqtimer.h>
+
+#include <bgrender.h>
+
+
+class MyApplication : public KApplication
+{
+ Q_OBJECT
+
+ public:
+ MyApplication( const char * );
+
+ private slots:
+ void renderDone();
+ void slotTimeout();
+
+ private:
+ KVirtualBGRenderer renderer;
+ TQTimer timer;
+};
+
+#endif
diff --git a/tdm/kfrontend/pics/CMakeLists.txt b/tdm/kfrontend/pics/CMakeLists.txt
new file mode 100644
index 00000000..e1b61b4f
--- /dev/null
+++ b/tdm/kfrontend/pics/CMakeLists.txt
@@ -0,0 +1,18 @@
+#################################################
+#
+# (C) 2010-2011 Serghei Amelian
+# serghei (DOT) amelian (AT) gmail.com
+#
+# Improvements and feedback are welcome
+#
+# This file is released under GPL >= 2
+#
+#################################################
+
+install( FILES
+ kdelogo.png kdelogo-crystal.png shutdown.jpg
+ DESTINATION ${DATA_INSTALL_DIR}/tdm/pics )
+
+install( FILES
+ default1.png default2.png default3.png root1.png
+ DESTINATION ${DATA_INSTALL_DIR}/tdm/pics/users )
diff --git a/tdm/kfrontend/pics/Makefile.am b/tdm/kfrontend/pics/Makefile.am
new file mode 100644
index 00000000..9ba04536
--- /dev/null
+++ b/tdm/kfrontend/pics/Makefile.am
@@ -0,0 +1,9 @@
+
+picsdir = $(kde_datadir)/tdm/pics
+pics_DATA = kdelogo.png kdelogo-crystal.png shutdown.jpg
+
+usersdir = $(picsdir)/users
+users_DATA = default1.png default2.png default3.png root1.png
+
+
+EXTRA_DIST = $(pics_DATA) $(users_DATA)
diff --git a/tdm/kfrontend/pics/default1.png b/tdm/kfrontend/pics/default1.png
new file mode 100644
index 00000000..ef3aef3f
--- /dev/null
+++ b/tdm/kfrontend/pics/default1.png
Binary files differ
diff --git a/tdm/kfrontend/pics/default2.png b/tdm/kfrontend/pics/default2.png
new file mode 100644
index 00000000..194acfe2
--- /dev/null
+++ b/tdm/kfrontend/pics/default2.png
Binary files differ
diff --git a/tdm/kfrontend/pics/default3.png b/tdm/kfrontend/pics/default3.png
new file mode 100644
index 00000000..a8663b15
--- /dev/null
+++ b/tdm/kfrontend/pics/default3.png
Binary files differ
diff --git a/tdm/kfrontend/pics/kdelogo-crystal.png b/tdm/kfrontend/pics/kdelogo-crystal.png
new file mode 100644
index 00000000..592a7e32
--- /dev/null
+++ b/tdm/kfrontend/pics/kdelogo-crystal.png
Binary files differ
diff --git a/tdm/kfrontend/pics/kdelogo.png b/tdm/kfrontend/pics/kdelogo.png
new file mode 100644
index 00000000..c89a7f66
--- /dev/null
+++ b/tdm/kfrontend/pics/kdelogo.png
Binary files differ
diff --git a/tdm/kfrontend/pics/root1.png b/tdm/kfrontend/pics/root1.png
new file mode 100644
index 00000000..fced75c1
--- /dev/null
+++ b/tdm/kfrontend/pics/root1.png
Binary files differ
diff --git a/tdm/kfrontend/pics/shutdown.jpg b/tdm/kfrontend/pics/shutdown.jpg
new file mode 100644
index 00000000..f1353c54
--- /dev/null
+++ b/tdm/kfrontend/pics/shutdown.jpg
Binary files differ
diff --git a/tdm/kfrontend/sakdlg.cc b/tdm/kfrontend/sakdlg.cc
new file mode 100644
index 00000000..396fa162
--- /dev/null
+++ b/tdm/kfrontend/sakdlg.cc
@@ -0,0 +1,247 @@
+//===========================================================================
+//
+// This file is part of the KDE project
+//
+// Copyright (c) 2010-2011 Timothy Pearson <kb9vqf@pearsoncomputing.net>
+
+#include <config.h>
+
+#include "sakdlg.h"
+
+#include <dmctl.h>
+
+#include <kapplication.h>
+#include <klocale.h>
+#include <kpushbutton.h>
+#include <kseparator.h>
+#include <kstandarddirs.h>
+#include <kglobalsettings.h>
+#include <kconfig.h>
+#include <kiconloader.h>
+#include <tdesu/defaults.h>
+#include <kpassdlg.h>
+#include <kdebug.h>
+#include <kuser.h>
+#include <dcopref.h>
+#include <kmessagebox.h>
+#include <kdialog.h>
+
+#include <tqlayout.h>
+#include <tqpushbutton.h>
+#include <tqmessagebox.h>
+#include <tqsimplerichtext.h>
+#include <tqlabel.h>
+#include <tqstringlist.h>
+#include <tqfontmetrics.h>
+#include <tqstyle.h>
+#include <tqapplication.h>
+#include <tqlistview.h>
+#include <tqheader.h>
+#include <tqcheckbox.h>
+#include <tqtimer.h>
+
+#include <fcntl.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <pwd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <X11/Xutil.h>
+#include <X11/keysym.h>
+#include <X11/Xatom.h>
+#include <fixx11h.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <limits.h>
+#include <dirent.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/select.h>
+#include <sys/time.h>
+#include <termios.h>
+#include <signal.h>
+
+#include "kfdialog.h"
+
+#ifndef AF_LOCAL
+# define AF_LOCAL AF_UNIX
+#endif
+
+#define FIFO_DIR "/tmp/ksocket-global/tdm"
+#define FIFO_FILE "/tmp/ksocket-global/tdm/tdmctl-%1"
+#define FIFO_SAK_FILE "/tmp/ksocket-global/tdm/tdmctl-sak-%1"
+
+bool trinity_desktop_lock_use_system_modal_dialogs = TRUE;
+extern bool trinity_desktop_lock_use_sak;
+
+//===========================================================================
+//
+// Simple dialog for displaying an unlock status or recurring error message
+//
+SAKDlg::SAKDlg(TQWidget *parent)
+ : TQDialog(parent, "information dialog", true, (trinity_desktop_lock_use_system_modal_dialogs?((WFlags)WStyle_StaysOnTop):((WFlags)WX11BypassWM))),
+ mUnlockingFailed(false), mPipe_fd(-1), closingDown(false)
+{
+ if (trinity_desktop_lock_use_system_modal_dialogs) {
+ // Signal that we do not want any window controls to be shown at all
+ Atom kde_wm_system_modal_notification;
+ kde_wm_system_modal_notification = XInternAtom(qt_xdisplay(), "_KDE_WM_MODAL_SYS_NOTIFICATION", False);
+ XChangeProperty(qt_xdisplay(), winId(), kde_wm_system_modal_notification, XA_INTEGER, 32, PropModeReplace, (unsigned char *) "TRUE", 1L);
+ }
+ setCaption(TDM_LOGIN_SCREEN_BASE_TITLE);
+
+ frame = new TQFrame( this );
+ if (trinity_desktop_lock_use_system_modal_dialogs)
+ frame->setFrameStyle( TQFrame::NoFrame );
+ else
+ frame->setFrameStyle( TQFrame::Panel | TQFrame::Raised );
+ frame->setLineWidth( 2 );
+
+ KSMModalDialogHeader* theader = new KSMModalDialogHeader( frame );
+
+ KUser user;
+
+ mStatusLabel = new TQLabel( "<b> </b>", frame );
+ mStatusLabel->setAlignment( TQLabel::AlignVCenter );
+
+ TQVBoxLayout *unlockDialogLayout = new TQVBoxLayout( this );
+ unlockDialogLayout->addWidget( frame );
+
+ TQHBoxLayout *layStatus = new TQHBoxLayout( 0, 0, KDialog::spacingHint());
+ layStatus->addWidget( mStatusLabel );
+
+ frameLayout = new TQGridLayout( frame, 1, 1, KDialog::marginHint(), KDialog::spacingHint() );
+ frameLayout->addMultiCellWidget( theader, 0, 0, 0, 1, AlignTop | AlignLeft );
+ frameLayout->addMultiCellLayout( layStatus, 1, 1, 0, 1, AlignLeft | AlignVCenter);
+
+ mStatusLabel->setText("<b>" + i18n("Press Ctrl+Alt+Del to begin.") + "</b><p>" + i18n("This process helps keep your password secure.") + "<br>" + i18n("It prevents unauthorized users from emulating the login screen."));
+
+ installEventFilter(this);
+
+ mSAKProcess = new KProcess;
+ *mSAKProcess << "tdmtsak" << "dm";
+ connect(mSAKProcess, TQT_SIGNAL(processExited(KProcess*)), this, TQT_SLOT(slotSAKProcessExited()));
+ mSAKProcess->start();
+
+ TQTimer::singleShot( 0, this, TQT_SLOT(handleInputPipe()) );
+}
+
+void SAKDlg::slotSAKProcessExited()
+{
+ int retcode = mSAKProcess->exitStatus();
+ if (retcode != 0) trinity_desktop_lock_use_sak = false;
+ closingDown = true;
+ hide();
+}
+
+void SAKDlg::handleInputPipe(void) {
+ if (closingDown) {
+ ::unlink(mPipeFilename.ascii());
+ return;
+ }
+
+ if (isShown() == false) {
+ TQTimer::singleShot( 100, this, TQT_SLOT(handleInputPipe()) );
+ return;
+ }
+
+ char readbuf[2048];
+ int displayNumber;
+ TQString currentDisplay;
+ currentDisplay = TQString(getenv("DISPLAY"));
+ currentDisplay = currentDisplay.replace(":", "");
+ displayNumber = currentDisplay.toInt();
+ mPipeFilename = TQString(FIFO_SAK_FILE).arg(displayNumber);
+ ::unlink((TQString(FIFO_FILE).arg(displayNumber)).ascii());
+
+ /* Create the FIFOs if they do not exist */
+ umask(0);
+ struct stat buffer;
+ int status;
+ status = stat(FIFO_DIR, &buffer);
+ if (status == 0) {
+ int file_mode = ((buffer.st_mode & S_IRWXU) >> 6) * 100;
+ file_mode = file_mode + ((buffer.st_mode & S_IRWXG) >> 3) * 10;
+ file_mode = file_mode + ((buffer.st_mode & S_IRWXO) >> 0) * 1;
+ if ((file_mode != 600) || (buffer.st_uid != 0) || (buffer.st_gid != 0)) {
+ ::unlink(mPipeFilename.ascii());
+ printf("[WARNING] Possible security breach! Please check permissions on " FIFO_DIR " (must be 600 and owned by root/root, got %d %d/%d). Not listening for login credentials on remote control socket.\n", file_mode, buffer.st_uid, buffer.st_gid); fflush(stdout);
+ return;
+ }
+ }
+ mkdir(FIFO_DIR,0600);
+ mknod(mPipeFilename.ascii(), S_IFIFO|0600, 0);
+ chmod(mPipeFilename.ascii(), 0600);
+
+ mPipe_fd = ::open(mPipeFilename.ascii(), O_RDONLY | O_NONBLOCK);
+ int numread;
+ TQString inputcommand = "";
+ while ((!inputcommand.contains('\n')) && (!closingDown)) {
+ numread = ::read(mPipe_fd, readbuf, 2048);
+ readbuf[numread] = 0;
+ readbuf[2047] = 0;
+ inputcommand += readbuf;
+ tqApp->processEvents();
+ }
+ if (closingDown) {
+ ::unlink(mPipeFilename.ascii());
+ return;
+ }
+ inputcommand = inputcommand.replace('\n', "");
+ TQStringList commandList = TQStringList::split('\t', inputcommand, false);
+ if ((*(commandList.at(0))) == "CLOSE") {
+ mSAKProcess->kill();
+ }
+ if (!closingDown) {
+ TQTimer::singleShot( 0, this, TQT_SLOT(handleInputPipe()) );
+ ::close(mPipe_fd);
+ ::unlink(mPipeFilename.ascii());
+ }
+ else {
+ ::unlink(mPipeFilename.ascii());
+ }
+}
+
+SAKDlg::~SAKDlg()
+{
+ if ((mSAKProcess) && (mSAKProcess->isRunning())) {
+ mSAKProcess->kill(SIGTERM);
+ delete mSAKProcess;
+ }
+ if (mPipe_fd != -1) {
+ closingDown = true;
+ ::close(mPipe_fd);
+ ::unlink(mPipeFilename.ascii());
+ }
+ hide();
+}
+
+void SAKDlg::closeDialogForced()
+{
+ TQDialog::reject();
+}
+
+void SAKDlg::reject()
+{
+
+}
+
+void SAKDlg::updateLabel(TQString &txt)
+{
+ mStatusLabel->setPaletteForegroundColor(Qt::black);
+ mStatusLabel->setText("<b>" + txt + "</b>");
+}
+
+void SAKDlg::show()
+{
+ TQDialog::show();
+ TQApplication::flushX();
+}
+
+#include "sakdlg.moc"
diff --git a/tdm/kfrontend/sakdlg.h b/tdm/kfrontend/sakdlg.h
new file mode 100644
index 00000000..a930707b
--- /dev/null
+++ b/tdm/kfrontend/sakdlg.h
@@ -0,0 +1,64 @@
+//===========================================================================
+//
+// This file is part of the KDE project
+//
+// Copyright (c) 2010 Timothy Pearson <kb9vqf@pearsoncomputing.net>
+//
+
+#ifndef __SAKDLG_H__
+#define __SAKDLG_H__
+
+#include <tqdialog.h>
+#include <tqstringlist.h>
+
+#include <kprocess.h>
+
+class TQFrame;
+class TQGridLayout;
+class TQLabel;
+class KPushButton;
+class TQListView;
+
+//===========================================================================
+//
+// Simple dialog for displaying an info message.
+// It does not handle password validation.
+//
+class SAKDlg : public TQDialog
+{
+ Q_OBJECT
+
+public:
+ SAKDlg(TQWidget *parent);
+ ~SAKDlg();
+ virtual void show();
+
+ void updateLabel( TQString &txt );
+ void closeDialogForced();
+
+private slots:
+ void slotSAKProcessExited();
+ void handleInputPipe();
+
+protected slots:
+ virtual void reject();
+
+private:
+ TQFrame *frame;
+ TQGridLayout *frameLayout;
+ TQLabel *mStatusLabel;
+ int mCapsLocked;
+ bool mUnlockingFailed;
+ TQStringList layoutsList;
+ TQStringList::iterator currLayout;
+ int sPid, sFd;
+ KProcess* mSAKProcess;
+ int mPipe_fd;
+ TQString mPipeFilename;
+
+protected:
+ bool closingDown;
+};
+
+#endif
+
diff --git a/tdm/kfrontend/sessions/9wm.desktop b/tdm/kfrontend/sessions/9wm.desktop
new file mode 100644
index 00000000..d1727678
--- /dev/null
+++ b/tdm/kfrontend/sessions/9wm.desktop
@@ -0,0 +1,76 @@
+[Desktop Entry]
+Type=XSession
+Exec=9wm
+TryExec=9wm
+Name=9WM
+Name[cy]= 9WM
+Name[eo]=9FA
+Name[hi]=9डबल्यू-एम
+Name[ta]=9 WM
+Name[te]=9 డబ్ల్యు ఎం
+Name[th]=ตัวจัดการหน้าต่าง gWM
+Comment=An emulation of the Plan 9 window manager 8-1/2
+Comment[af]='n Nabootsing van die 'Plan 9' venster bestuurder
+Comment[be]=Эмуляцыя кіраўніка вокнаў 8-1/2 для Plan 9
+Comment[bn]=প্ল্যান ৯ উইণ্ডো ম্যানেজার ৮-১/২ -এর এমুলেশন
+Comment[bs]=Simulacija Plan 9 window managera 8-1/2
+Comment[ca]=Una emulació del gestor de finestres Plan 9
+Comment[cs]=Emulace Plane 9 správce oken 8-1/2
+Comment[csb]=Emùlacëjô menedżera òknów Plan 9 - 8-1/2
+Comment[cy]=Efelychiad o 8-1/2, y trefnydd ffenestri Plan 9
+Comment[da]=En emulering af Plan 9 vindueshåndteringen 8-1/2
+Comment[de]=Emulation des Plan 9-Fenstermanagers 8-1/2
+Comment[el]=Μια προσομοίωση του Plan 9 διαχειριστή παραθύρων 8-1/2
+Comment[eo]=KDE-fenestroadministrilo de plano 9
+Comment[es]=Una emulación del gestor de ventanas Plan 9 8-1/2
+Comment[et]=Plan 9 aknahalduri 8-1/2 emuleerimine
+Comment[eu]=Plan 9 8-1/2 leiho kudeatzailearen emulazioa
+Comment[fa]=تقلیدی از نقشۀ مدیر پنجره ۹. ۸-۱/ ۲
+Comment[fi]=Emulaatio Plan9-ikkunaohjelmasta 8-1/2
+Comment[fr]=Une émulation du gestionnaire de fenêtres Plan 9 8-1/2
+Comment[fy]=In emulator foar de Plan9 finstersbehearder 8-1/2
+Comment[gl]=Unha emulación do xestor de fiestras de Plan9
+Comment[he]=מדמה של מנהל חלונות Plan 9 8-1/2
+Comment[hi]=प्लान 9 विंडो प्रबंधक 8-1/2 का एक एमुलेशन
+Comment[hr]=Emulacija Plan 9 upravitelja prozora 8-1/2
+Comment[hu]=A Plan 9 operációs rendszer 8-1/2 nevű ablakkezelőjének emulálása
+Comment[is]=Eftirlíking af Plan 9 gluggastjóranum 8-1/2
+Comment[it]=Un emulatore del window manager 8-1/2 Plan 9
+Comment[ja]=Plan9 ウィンドウマネージャのエミュレーション 8-1/2
+Comment[ka]=Plan 9 ფანჯრის მმართველის ემულატორი
+Comment[kk]=Plan 9 терезе менеджерінің эмуляторы
+Comment[km]=ការ​ត្រាប់​តាម​កម្មវិធី​គ្រប់គ្រង​បង្អួច Plan 9 8-1/2
+Comment[ko]=Plan 9 창 관리자 8-1/2 에뮬레이션
+Comment[lt]=Plan 9 langų tvarkyklės emuliatorius 8-1/2
+Comment[lv]=Plan 9 logu menedžera emulators 8-1/2
+Comment[mk]=Емулација на менаџерот на прозорци Plan 9 8-1/2
+Comment[ms]=Pelagakan Plan 9 pengurus tetingkap 8-1/2
+Comment[mt]=Emulazzjoni tal-window manager "Plan 9" 8½
+Comment[nb]=En emulering av vindusbehandleren 8 ½ fra Plan 9
+Comment[nds]=Emuleert den Plan-9-Finsterpleger 8-1/2
+Comment[ne]=योजना 9 सञ्झ्याल प्रबन्धक 8-1/2 को इमुलेसन
+Comment[nl]=Een emulator voor de Plan9 windowmanager 8-1/2
+Comment[nn]=Emulering av vindaugssjefen 8 ½ frå Plan 9
+Comment[pa]=ਪਲੇਨ 9 ਝਰੋਖਾ ਮੈਨੇਜਰ 8-1/2 ਦਾ ਸਮਰੂਪ
+Comment[pl]=Emulacja menedżera okien Plan 9 - 8-1/2
+Comment[pt]=Uma emulação do gestor de janelas do Plan 9 8-1/2
+Comment[pt_BR]=Uma emulação do gerenciador de janelas do Plan 9
+Comment[ro]=Un emulator al managerului de ferestre 8-1/2 din Plan 9
+Comment[ru]=Эмуляция оконного менеджера Plan 9
+Comment[rw]=Ikurura rya mugenga dirishya 8-1/2 Plan 9
+Comment[se]=Lásegieđahalli mii áddestaddá Plan 9 lásegieđahalli 8-1/2.
+Comment[sk]=Emulácia správcu okien 8-1/2 systému Plan 9
+Comment[sl]=Emulacija okenskega upravitelja Plan 9 8-1/2
+Comment[sr]=Емулација Plan 9 менаџера прозора 8-1/2
+Comment[sr@Latn]=Emulacija Plan 9 menadžera prozora 8-1/2
+Comment[sv]=Emulering av Plan-9-fönsterhanteraren 8-1/2
+Comment[ta]= திட்டம் 9 சாளர மேலாளர் 8-1/2 இன் முன்மாதிரி
+Comment[tg]=Эмулятори нақшаи 9-и мудири тирезаи 8-1/2
+Comment[th]=การจำลองตัวจัดการหน้าต่าง Plan 9 8-1/2
+Comment[tr]=Plan 9 pencere yöneticisi 8-1/2 için bir emülasyon
+Comment[tt]=Plan 9 atlı täräzä idäräçenä axşap eşläw
+Comment[uk]=Емуляція менеджера вікон Plan 9 "8-1/2"
+Comment[vi]=Một bộ mô phỏng bộ quản lý cửa sổ Plan 9 8-1/2
+Comment[wa]=Ene emulåcion do manaedjeu di purneas di Plan 9
+Comment[zh_CN]=Plan 9 窗口管理器 8-1/2 的模拟
+Comment[zh_TW]=模仿 Plan 9 的視窗管理程式 8-1/2
diff --git a/tdm/kfrontend/sessions/CMakeLists.txt b/tdm/kfrontend/sessions/CMakeLists.txt
new file mode 100644
index 00000000..780963bd
--- /dev/null
+++ b/tdm/kfrontend/sessions/CMakeLists.txt
@@ -0,0 +1,29 @@
+#################################################
+#
+# (C) 2010-2011 Serghei Amelian
+# serghei (DOT) amelian (AT) gmail.com
+#
+# Improvements and feedback are welcome
+#
+# This file is released under GPL >= 2
+#
+#################################################
+
+configure_file( tde.desktop.cmake tde.desktop @ONLY )
+
+install( FILES
+ admin.desktop ${CMAKE_CURRENT_BINARY_DIR}/tde.desktop
+ gnome.desktop 9wm.desktop aewm++.desktop aewm.desktop
+ afterstep.desktop amaterus.desktop amiwm.desktop
+ asclassic.desktop blackbox.desktop cde.desktop
+ ctwm.desktop cwwm.desktop enlightenment.desktop
+ evilwm.desktop fluxbox.desktop flwm.desktop fvwm.desktop
+ fvwm95.desktop golem.desktop icewm.desktop ion.desktop
+ larswm.desktop lwm.desktop matchbox.desktop metacity.desktop
+ mwm.desktop olvwm.desktop olwm.desktop openbox.desktop
+ oroborus.desktop phluid.desktop pwm.desktop qvwm.desktop
+ ratpoison.desktop sapphire.desktop sawfish.desktop
+ twm.desktop ude.desktop vtwm.desktop w9wm.desktop
+ waimea.desktop wm2.desktop wmaker.desktop xfce.desktop
+ xfce4.desktop
+ DESTINATION ${DATA_INSTALL_DIR}/tdm/sessions )
diff --git a/tdm/kfrontend/sessions/Makefile.am b/tdm/kfrontend/sessions/Makefile.am
new file mode 100644
index 00000000..a2987244
--- /dev/null
+++ b/tdm/kfrontend/sessions/Makefile.am
@@ -0,0 +1,49 @@
+sessionsdir = $(kde_datadir)/tdm/sessions
+sessions_DATA = \
+ admin.desktop tde.desktop gnome.desktop \
+ 9wm.desktop \
+ aewm++.desktop \
+ aewm.desktop \
+ afterstep.desktop \
+ amaterus.desktop \
+ amiwm.desktop \
+ asclassic.desktop \
+ blackbox.desktop \
+ cde.desktop \
+ ctwm.desktop \
+ cwwm.desktop \
+ enlightenment.desktop \
+ evilwm.desktop \
+ fluxbox.desktop \
+ flwm.desktop \
+ fvwm.desktop \
+ fvwm95.desktop \
+ golem.desktop \
+ icewm.desktop \
+ ion.desktop \
+ larswm.desktop \
+ lwm.desktop \
+ matchbox.desktop \
+ metacity.desktop \
+ mwm.desktop \
+ olvwm.desktop \
+ olwm.desktop \
+ openbox.desktop \
+ oroborus.desktop \
+ phluid.desktop \
+ pwm.desktop \
+ qvwm.desktop \
+ ratpoison.desktop \
+ sapphire.desktop \
+ sawfish.desktop \
+ twm.desktop \
+ ude.desktop \
+ vtwm.desktop \
+ w9wm.desktop \
+ waimea.desktop \
+ wm2.desktop \
+ wmaker.desktop \
+ xfce.desktop \
+ xfce4.desktop
+
+EXTRA_DIST = $(sessions_DATA)
diff --git a/tdm/kfrontend/sessions/admin.desktop b/tdm/kfrontend/sessions/admin.desktop
new file mode 100644
index 00000000..73e6ae3b
--- /dev/null
+++ b/tdm/kfrontend/sessions/admin.desktop
@@ -0,0 +1,7 @@
+[Desktop Entry]
+Encoding=UTF-8
+Type=XSession
+Exec=YaSTadminSession
+TryExec=YaSTadminSession
+Name=admin
+Comment=Yast Admin Session
diff --git a/tdm/kfrontend/sessions/aewm++.desktop b/tdm/kfrontend/sessions/aewm++.desktop
new file mode 100644
index 00000000..3eb4ee8e
--- /dev/null
+++ b/tdm/kfrontend/sessions/aewm++.desktop
@@ -0,0 +1,74 @@
+[Desktop Entry]
+Type=XSession
+Exec=aewm++_xsession
+TryExec=aewm++_xsession
+Name=AEWM++
+Name[eo]=MFA++
+Name[hi]=एईडबल्यूएम++
+Name[te]=ఎ ఈ డబ్ల్యు ఎం ++
+Comment=A minimal window manager based on AEWM, enhanced by virtual desktops and partial GNOME support
+Comment[af]='n Minimale venster bestuurder wat op AEWM gebaseer is. Dit is verbeter met virtuale werkskerms en gedeeltelike GNOME ondersteuning
+Comment[ar]=مدير نوافذ مصغّر مبني على AEWM، محسّن بأسطح مكتب وهمية ودعم جينوم جزئي
+Comment[be]=Мінімалістычны кіраўнік вокнаў, заснаваны на AEWM, з віртуальнымі працоўнымі сталамі і частковай падтрымкай GNOME
+Comment[bn]=AEWM ভিত্তিক একটি পরিমিত উইণ্ডো ম্যানেজার, ভার্চুয়াল ডেস্কটপ এবং আংশিক গনোম সমর্থন দ্বারা বর্ধিত
+Comment[bs]=Minimalni window manager baziran na AEWM, proširen virtuelnim desktopima i djelomičnom GNOME podrškom
+Comment[ca]=Un gestor de finestres minimalista basat en AEWM, orientat a escriptoris virtuals i funcionament parcial per a GNOME
+Comment[cs]=Minimalizovaný správce oken založený na AEWM rozšířený o virtuální plochy a částečnou podporu GNOME
+Comment[csb]=Prosti menedżer òknów na spòdlém AEWM, zbògacony o wirtualné pùltë ë dzélowé wspiarce dlô GNOME
+Comment[cy]= Trefnydd ffenestri lleiafol wed'i seilio ar AEWM, wedi'i wella gan penbyrddau rhith a cynhaliaeth Gnome rhannol.
+Comment[da]=En minimal vindueshåndtering baseret på AEWM, udvidet med virtuelle desktoppe og delvis GNOME-støtte
+Comment[de]=Minimalistischer Fenstermanager. Beruht auf AEWM, verbessert durch virtuelle Arbeitsflächen und teilweise GNOME-Unterstützung
+Comment[el]=Ένας μικρός διαχειριστής παραθύρων βασισμένος στον AEWM, εμπλουτισμένος με εικονικές επιφάνειες εργασίας και μερική υποστήριξη GNOME
+Comment[eo]=Minimuma fenestroadministrilo el MFA, plibonigita per virtualaj labortabloj kaj parta helpo por Gnomikuo
+Comment[es]=Un gestor de ventanas minimalista basado en AEWM, mejorado con soporte para escritorios virtailes y, parcialmente, GNOME
+Comment[et]=Vähenõudlik aknahaldur, mille aluseks on AEWM ja mida on täiendatud virtuaalsete töölaudade ning osalise GNOME toetusega
+Comment[eu]=AEWMn oinarritutako leiho kudeatzaile minimoa, mahaigain birtualen euskarriaz eta, zati batez, GNOMEz hobetua
+Comment[fa]= مدیر پنجرۀ کمینه بر اساس AEWM، گسترش‌یافته توسط رومیزیهای مجازی و پشتیبانی جزئی GNOME
+Comment[fi]=Minimaalinen AEWM:ään pohjautuva ikkunaohjelma, jota on parannettuna virtuaalityöpöydillä ja osittaisella GNOME-tuella
+Comment[fr]=Un gestionnaire de fenêtres minimal fondé sur AEWM avec, en plus, la gestion des bureaux virtuels ainsi qu'un support partiel de GNOME
+Comment[fy]=In minimalistyske finstersmanager basearre op AEWM, útbreide mei firtuele buroblêden en gedieltelike GNOME-stipe
+Comment[gl]=Un xestor de fiestras mínimo baseado en AEWM, mellorado cos escritórios virtuais e con soporte parcial para GNOME
+Comment[he]=מנהל חלונות מינימלי המבוסס על AEWM, המשופר על ידי שולחנות עבודה וירטואליים ותמיכה חלקית ב GNOME
+Comment[hi]= एईडबल्यूएम आधारित अल्प विंडो प्रबंधक, आभासी डेस्कटॉप तथा आंशिक ग्नोम समर्थन से बेहतर बनाया गया
+Comment[hr]=Minimalistički upravitelj prozora zasnovan na AEWM, unaprijeđen virtualnim radnim površinama i djelomičnom podrškom za GNOME
+Comment[hu]=Egy nagyon egyszerű ablakkezelő az AEWM alapján, virtuális munkaasztalokkal és részleges GNOME-támogatással kiegészítve
+Comment[is]=Einfaldur gluggastjóri byggður á AEWM en með stuðningi fyrir sýndarskjáborð og takmörkuðum GNOME stuðningi
+Comment[it]= Un window manager minimale basato su AEWM, migliorato con desktop virtuali e supporto parziale per GNOME
+Comment[ja]=仮想デスクトップと部分的な GNOME サポートを強化した AEWM ベースの小さなウィンドウマネージャ
+Comment[ka]=მინიმალური ფანჯრის მენეჯერი AEWM -ის ბაზაზე, имеющий частичную поддержку GNOME.
+Comment[kk]=Виртуалды үстелдері және шамалы GNOME қолдауы бар AEWM-негіздеген шағын терезе менеджері
+Comment[km]=កម្មវិធី​គ្រប់គ្រង​បង្អួច​តូច ដែល​ផ្អែក​លើ AEWM ដែល​ធ្វើ​ឲ្យ​ប្រសើរ​ដោយ​ផ្ទៃតុ​និមិត្ត និង​ការ​គាំទ្រ GNOME
+Comment[ko]=부분적 그놈 지원과 가상 데스크톱 지원을 사용하는 AEWM 기반 창 관리자
+Comment[lt]=Minimalistinė langų tvarkyklė paremta AEWM, išplėsta virtualių darbastalių ir daliniu GNOME palaikymu
+Comment[lv]=Minimālistisks logu menedžeris bāzēts uz AEWM, papildināts ar virtuālajām darbvirsmām un daļēju GNOME atbalstu
+Comment[mk]=Минимален менаџер на прозорци базиран на AEWM, подобрен со виртуелни површини и парцијална GNOME поддршка
+Comment[ms]=Pengurus tetingkap minima berdasarkan AEWM, dipertingkatkan dengan desktop visual dan sokongan GNOME separa
+Comment[mt]=Window manager żgħir ibbażat fuq AEWM, filmkien ma' desktops virtwali u sapport parzjali għal GNOME.
+Comment[nb]=En minimal vindusbehandler basert på AEWM, forbedret med virtuelle skrivebord og delvis støtte for GNOME
+Comment[nds]=En minimaal Finsterpleger, opbuut op AEWM, verwiedert üm virtuelle Schriefdischen un deelwies Ünnerstütten för GNOME
+Comment[ne]=अवास्तविक डेस्कटप र आंशिक GNOME समर्थनद्वारा बृद्धि गरिएको AEWM मा आधारित न्यूनतम सञ्झ्याल प्रबन्धक
+Comment[nl]=Een minimalistische windowmanager gebaseerd op AEWM, uitgebreid met virtuele bureaubladen en gedeeltelijke GNOME-ondersteuning
+Comment[nn]=Ein minimal vindaugssjef basert på AEWM, forbetra med virtuelle skrivebord og delvis støtte for GNOME
+Comment[pa]= AEWM ਤੇ ਅਧਾਰਿਤ ਛੋਟਾ ਝਰੋਖਾ ਮੈਨੇਜਰ, ਫਰਜ਼ੀ ਵੇਹੜਿਆਂ ਨਾਲ ਲੈੱਸ ਤੇ ਥੋੜਾ GNOME ਸਹਾਇਕ
+Comment[pl]=Prosty menedżer okien na bazie AEWM, wzbogacony o wirtualne pulpity i częściowe wsparcie dla GNOME
+Comment[pt]=Um gestor de janelas simples baseado no AEWM, melhorado com os ecrãs virtuais e com um suporte parcial do GNOME
+Comment[pt_BR]=Um gerenciador de janelas pequeno, baseado no AEWM, melhorado pelas áreas de trabalho virtuais e com suporte parcial ao GNOME
+Comment[ro]=Un manager de ferestre minimal bazat pe AEWM, îmbunătățit cu ecrane virtuale și suport parțial pentru GNOME
+Comment[ru]=Минимальный оконный менеджер на основе AEWM, имеющий частичную поддержку GNOME.
+Comment[rw]=Mugenga dirishya nto ishingiye kuri AEWM, rivuguruwe n'ibiro bitagaragara n'iyifashisha GNOME rituzuye
+Comment[se]=Geahpes lásegieđahalli vuođđoduvvon AEWM:as, mas leat virtuella čállinbeavddit ja doarju GNOME muhton muddui.
+Comment[sk]=Minimálny správca okien založený na AEWM, rozšírrený o virtuálne plochy a čiastočnú podporu GNOME
+Comment[sl]=Skromen okenski upavitelj na osnovi AEWM, izboljšan z navideznimi namizji in delno podporo GNOME
+Comment[sr]=Минимални менаџер прозора заснован на AEWM-у, побољшан виртуелним радним површинама и делимичном подршком за Гном
+Comment[sr@Latn]=Minimalni menadžer prozora zasnovan na AEWM-u, poboljšan virtuelnim radnim površinama i delimičnom podrškom za Gnom
+Comment[sv]=Minimal fönsterhanterare baserad på AEWM, utökad med virtuella skrivbord och delvis stöd för Gnome
+Comment[ta]=AEWM அடிப்படையிலான சிறிய சாளர மேலாண்மை, மெய்நிகர் மேல்மேசை மற்றும் பகுதி GNOME ஆதரவால் மேப்படுத்தப்பட்டுள்ளது
+Comment[tg]=Мудири равзанаҳои хурд дар асоси AEWM дорои нопурраи интерфейси GNOME
+Comment[th]=ตัวจัดการหน้าต่างขนาดเล็ก โดยใช้พื้นฐานของ AEWM แล้วเพิ่มความสามารถด้วย พื้นที่ทำงานเสมือน และสนับสนุน GNOME บางส่วน
+Comment[tr]=AEWM tabanlı bir pencere yöneticisi
+Comment[tt]=AEWM asılında yasalğan, xıyalí öställär belän beraz GNOME totqan ciñel täräzä-idäräçe
+Comment[uk]=Мінімальний менеджер вікон, заснований на AEWM, покращений підтримкою віртуальних стільниць та частковою підтримкою GNOME
+Comment[vi]=Bộ quản lý cửa sổ tối thiểu dựa trên AEWM, cải tiến với màn hình nền ảo và được hỗ trợ một phần bởi GNOME
+Comment[wa]=On manaedjeu di purneas minimå båzé so AEWM, avou sopoirt po les forveyous scribannes eyet ene miete di sopoirt po Gnome
+Comment[zh_CN]=基于 AEWM 的小型窗口管理器,增强了虚拟桌面和部分 GNOME 支持
+Comment[zh_TW]=基於 AEWM 的小型視窗管理程式,增強了虛擬桌面及部分的 GNOME 支援
diff --git a/tdm/kfrontend/sessions/aewm.desktop b/tdm/kfrontend/sessions/aewm.desktop
new file mode 100644
index 00000000..362fd921
--- /dev/null
+++ b/tdm/kfrontend/sessions/aewm.desktop
@@ -0,0 +1,76 @@
+[Desktop Entry]
+Type=XSession
+Exec=aewm
+TryExec=aewm
+Name=AEWM
+Name[eo]=MFA
+Name[hi]=एईडबल्यूएम
+Name[te]=ఎ ఈ డబ్ల్యు ఎం
+Comment=A minimalist window manager
+Comment[af]='n Minimale venster bestuurder
+Comment[ar]=مسيير نوافذ ذو الميزات الأقل
+Comment[be]=Мінімалістычны кіраўнік вокнаў
+Comment[bn]=একটি পরিমিত উইণ্ডো ম্যানেজার
+Comment[bs]=Minimalistički window manager
+Comment[ca]=Un gestor de finestres minimalista
+Comment[cs]=Minimalistický správce oken
+Comment[csb]=Prosti menedżer òknów
+Comment[cy]=Trefnydd ffenestri lleiafol
+Comment[da]=En minimalistisk vindueshåndtering
+Comment[de]=Minimalistischer Fenstermanager
+Comment[el]=Ένας μινιμαλιστικός διαχειριστής παραθύρων
+Comment[eo]=Minimumema fenestroadministrilo
+Comment[es]=Un gestor de ventanas minimalista
+Comment[et]=Vähenõudlik aknahaldur
+Comment[eu]=Leiho kudeatzaile minimalista
+Comment[fa]=یک مدیر پنجرۀ کمینه
+Comment[fi]=Minimalistinen ikkunaohjelma
+Comment[fr]=Un gestionnaire de fenêtres minimaliste
+Comment[fy]=In minimalistyske finstersmanager
+Comment[gl]=Un xestor de fiestras minimalista
+Comment[he]=מנהל חלונות מינימליסטי
+Comment[hi]=एक अल्पतम विंडो प्रबंधक
+Comment[hr]=Minimalistički upravitelj prozora
+Comment[hu]=Egy nagyon egyszerű ablakkezelő
+Comment[is]=Einfaldur gluggastjóri
+Comment[it]=Un window manager minimalista
+Comment[ja]=小さなウィンドウマネージャ
+Comment[ka]=მინიმალისტური ფანჯრების მნეჯერი
+Comment[kk]=Шағын терезе менеджері
+Comment[km]=កម្មវិធី​គ្រប់គ្រង​បង្អួច​លក្ខណៈ​ពិសេស​តិច
+Comment[ko]=최소 지향 창 관리자
+Comment[lt]=Minimalistinė langų tvarkyklė
+Comment[lv]=Minimālistisks logu menedžeris
+Comment[mk]=Минималистички менаџер на прозорци
+Comment[mn]=Хамгийн жижиг цонхны удирдагч
+Comment[mt]=Window manager żgħir
+Comment[nb]=En minimalistisk vindusbehandler
+Comment[nds]=En minimalistisch Finsterpleger
+Comment[ne]=एक मिनिमलिस्ट सञ्झ्याल प्रबन्धक
+Comment[nl]=Een minimalistische windowmanager
+Comment[nn]=Ein minimalistisk vindaugssjef
+Comment[pa]=ਇੱਕ ਹਲਕਾ ਝਰੋਖਾ ਮੈਨੇਜਰ
+Comment[pl]=Prosty menedżer okien
+Comment[pt]=Um gestor de janelas minimalista
+Comment[pt_BR]=Um gerenciador de janelas minimalista
+Comment[ro]=Un manager de ferestre minimal
+Comment[ru]=Минимальный оконный менеджер
+Comment[rw]=Mugenga dirishya igira-bito
+Comment[se]=Minimalisttalaš lásegieđahalli
+Comment[sk]=Minimálny správca okien
+Comment[sl]=Minimalističen okenski upravitelj
+Comment[sr]=Минималистички менаџер прозора
+Comment[sr@Latn]=Minimalistički menadžer prozora
+Comment[sv]=Minimalistisk fönsterhanterare
+Comment[ta]=ஒரு சிறிதுப்படுத்தப்பட்ட சாளர மேலாளர்
+Comment[tg]=Мудири тирезаи minimalist
+Comment[th]=ระบบจัดการหน้าต่างขนาดเล็ก
+Comment[tr]=Küçük bir pencere yöneticisi
+Comment[tt]=Bik ciñel täräzä-idäräçe
+Comment[uk]=Аскетичний менеджер вікон
+Comment[uz]=Juda oddiy oyna boshqaruvchi
+Comment[uz@cyrillic]=Жуда оддий ойна бошқарувчи
+Comment[vi]=Trình quản lý cửa sổ đơn giản
+Comment[wa]=On manaedjeu di purneas minimå
+Comment[zh_CN]=最小的窗口管理器
+Comment[zh_TW]=一個最小型的視窗管理程式
diff --git a/tdm/kfrontend/sessions/afterstep.desktop b/tdm/kfrontend/sessions/afterstep.desktop
new file mode 100644
index 00000000..c3f8d732
--- /dev/null
+++ b/tdm/kfrontend/sessions/afterstep.desktop
@@ -0,0 +1,83 @@
+[Desktop Entry]
+Type=XSession
+Exec=afterstep
+TryExec=afterstep
+Name=AfterStep
+Name[bn]=আফটার-স্টেপ
+Name[eo]=Postpaŝo
+Name[hi]=आफ्टर-स्टेप
+Name[ne]=चरण पछाडि
+Name[pa]=ਪਗਬਾਅਦ
+Name[rw]=NyumaIntambwe
+Name[sv]=Afterstep
+Name[ta]=ஆஃப்டர்ஸ்டெப்
+Name[te]=ఆఫ్టర్ స్టెప్
+Comment=A window manager with the NeXTStep look and feel, based on FVWM
+Comment[af]='n Venster bestuurder wat NeXTStep naboots, gebaseer of FVWM
+Comment[ar]=مدير نوافذ ذو مظهر شبيه بـNeXTStep، مبني على FVWM
+Comment[be]=Кіраўнік вокнаў з вонкавым выглядам NeXTStep, заснаваны на FVWM
+Comment[bn]=FVWM-এর ওপর ভিত্তি করে তৈরি একটি উইণ্ডো ম্যানেজার, যা দেখতে শুনতে অনেকটানেক্সট-স্টেপ (NeXTStep)-এর মত
+Comment[bs]=Window manager sa NeXTStep izgledom i osjećajem, baziran na FVWM
+Comment[ca]=Un gestor de finestres amb l'aspecte i comportament de NeXTStep, basat en FVWM
+Comment[cs]=Správce oken podobný NeXTStepu založený na FVWM
+Comment[csb]=Menedżer òknów jidący w szlach NeXTStep, ùsôdzony na spòdlém FVWM
+Comment[cy]= Trefnydd ffenestri efo golwg a theimlad CamNesaf (NeXTStep), wedi'i seilio ar FVWM
+Comment[da]=En vindueshåndtering med NeXTStep udseende, baseret på FVWM
+Comment[de]=Fenstermanager mit der Optik von NeXTStep, basiert auf FVWM
+Comment[el]=Ένας διαχειριστής παραθύρων με την όψη και αίσθηση του NeXTStep, βασισμένος στον FVWM
+Comment[eo]=Fenestroadministrilo, kiu aperas kiel Venontpaŝo, farita de FVWM
+Comment[es]=Un gestor de ventanas con el aspecto de NeXTStep, basado en FVWM
+Comment[et]=Aknahaldur NeXTStep välimuse ja vaimuga, aluseks FVWM
+Comment[eu]=FVWMn oinarritutako, eta NeXTStep-en itxura eta portaera duen leiho kudeatzailea
+Comment[fa]=یک مدیر پنجره توسط ظاهر و احساس NeXTStep، براساس FVWM
+Comment[fi]=NeXTStep-tyylinen ja -tuntuinen FVWM:ään pohjautuva ikkunaohjelma
+Comment[fr]=Un gestionnaire de fenêtres similaire à NeXTStep et fondé sur FVWM
+Comment[fy]=In finstersmanager mei it úterlik en gedrach fan NeXTStep; basearre op FVWM
+Comment[gl]=Un xestor de fiestras de aspeito NeXTStep, baseado en FVWM
+Comment[he]=מנהל חלונות עם מראה ומרגש כמו של NeXTStep המבוסס על, FVWM
+Comment[hi]=एफ़वीडबल्यूएम आधारित नेक्स्टस्टेप की तरह दिखने और महसूस होने वाला विंडो प्रबंधक
+Comment[hr]=Upravitelj prozora s NeXTStep izgledom i načinom rada, zasnovan na FVWM-u
+Comment[hu]=Egy FVWM-alapú ablakkezelő, megjelenése a NeXTStepére hasonlít
+Comment[is]=Gluggastjóri sem líkist þeim sem er í NeXTStep, byggður á FVWM
+Comment[it]=Un window manager con lo stile NeXTStep, basato su FVWM
+Comment[ja]=NeXTStep のルック&フィールをもった FVWM ベースのウィンドウマネージャ
+Comment[ka]=ფანჯრის მენეჯერი FVWM -ის ბაზაზე, რომელიც NeXTStep-ს ჰგავს
+Comment[kk]=FVWM-негіздеген, көрінісі NeXTStep-те сияқты, терезе менеджері
+Comment[km]=កម្មវិធី​គ្រប់គ្រង​បង្អួច​មាន​រូបរាង និង​មុខងារ NeXTStep ដែល​ផ្អែក​លើ FVWM
+Comment[ko]=FVWM 기반 NeXTStep 모양 창 관리자
+Comment[lt]=Langų tvarkyklė su NeXTStep išvaizda ir jausena, paremta FVWM
+Comment[lv]=Logu menedžeris ar NeXTStep izskatu un izturēšanos, bāzēts uz FVWM
+Comment[mk]=Менаџер на прозорци со изгледот и чувството на NeXTStep, базиран на FVWM
+Comment[mn]=NeXTStep look болон feel, based бүхий FVWM-д суурилсан цонх удирдагч
+Comment[ms]=Pengurus tetingkap dengan rupa dan rasa NeXTStep berdasarkan FVWM
+Comment[mt]=Window manager ibbażat fuq FVWM, jixbaħ lil NeXTStep
+Comment[nb]=En vindusbehandler som ligner på NeXTStep, basert på FVWM
+Comment[nds]=En Finsterpleger mit dat Utsehn vun NeXTStep, opbuut op FVWM
+Comment[ne]=FVWMA आधारित एउटा सञ्झ्याल प्रबन्धक NeXTStep मा हेर्छ र थाहा पाउँछ
+Comment[nl]=Een windowmanager met het uiterlijk en gedrag van NeXTStep; gebaseerd op FVWM
+Comment[nn]=Ein vindaugssjef som liknar på NeXTStep, basert på FVWM
+Comment[pa]=NeXTStep ਦੀ ਦਿੱਖ ਤੇ ਦਰਿਸ਼ ਵਾਲਾ FVWM ਆਧਾਰਿਤ ਝਰੋਖਾ ਮੈਨੇਜਰ
+Comment[pl]=Menedżer okien naśladujący NeXTStep, stworzony na podstawie FVWM
+Comment[pt]=Um gestor de janelas com a aparência e comportamento do NeXTStep. Baseado no FVWM.
+Comment[pt_BR]=Um gerenciador de janelas com a aparência do NeXTSep, baseado no FVWM
+Comment[ro]=Un manager de ferestre cu aspect NeXTStep, bazat pe FVWM
+Comment[ru]=Оконный менеджер на основе FVWM, повторяющий внешний вид NeXTStep
+Comment[rw]=Mugenga dirishya ifite imboneko n'ukumva NtambweIkurikira, ishingiye kuri FVWM
+Comment[se]=Lásegieđahalli mii sulastahttá NeXTStep, vuođđoduvvon FVWM:as
+Comment[sk]=Správca okien podobný NeXTStep založený na FVWM
+Comment[sl]=Okenski upravitelj z občutkom in izgledom NeXTStep-a, na osnovi FVWM
+Comment[sr]=Менаџер прозора са NeXTStep-овим изгледом и осећајем, заснован на FVWM-у
+Comment[sr@Latn]=Menadžer prozora sa NeXTStep-ovim izgledom i osećajem, zasnovan na FVWM-u
+Comment[sv]=Fönsterhanterare med Nextstep-utseende och -känsla, baserad på FVWM
+Comment[ta]=FVWM அடிப்படையிலான NeXTStep உடனான சாளர மேலாளர்.
+Comment[tg]=Мудири равзанаҳо дар асоси FVWM дорои намуди NeXTStep
+Comment[th]=ระบบจัดการหน้าต่างที่มีรูปแบบและสัมผัสของระบบปฏิบัติการ NeXTStep โดยใช้พื้นฐานของ FVWM
+Comment[tr]=NeXTStep görünümlü bir pencere yöneticisi
+Comment[tt]=FVWM asılında qorılğan, NeXTStep küreneşe belän täräzä-idäräçe
+Comment[uk]=Менеджер вікон з виглядом та поведінкою NeXTStep, заснований на FVWM
+Comment[uz]=FVWM asosida yaratilgan NeXTStep'ga oʻxshash oyna boshqaruvchi
+Comment[uz@cyrillic]=FVWM асосида яратилган NeXTStep'га ўхшаш ойна бошқарувчи
+Comment[vi]=Trình quản lý cửa sổ với giao diện NeXTStep, dựa trên FVWM
+Comment[wa]=On manaedjeu di purneas avou l' rivnance di NeXTStep, båzé so FVWM
+Comment[zh_CN]=一个带有 NeXTStep 观感的窗口管理器,基于 FVWM
+Comment[zh_TW]=一個基於 FVWM 並擁有 NeXTStep 外觀及感覺的視窗管理程式
diff --git a/tdm/kfrontend/sessions/amaterus.desktop b/tdm/kfrontend/sessions/amaterus.desktop
new file mode 100644
index 00000000..3c52ee18
--- /dev/null
+++ b/tdm/kfrontend/sessions/amaterus.desktop
@@ -0,0 +1,75 @@
+[Desktop Entry]
+Type=XSession
+Exec=amaterus
+TryExec=amaterus
+Name=AMATERUS
+Name[hi]=एमेच्योर्स
+Name[te]=అమాటెరస్
+Comment=A GTK+ based window manager with a window grouping feature
+Comment[af]='n GTK+ gebaseerde venster bestuurder met 'n venster groepering funksie
+Comment[ar]=مدير نوافذ مبني على GTK+ له ميزة تجميع النوافذ
+Comment[be]=Кіраўнік вокнаў, заснаваны на GTK+, са здольнасцю групавання вокнаў
+Comment[bn]=GTK+ ভিত্তিল উইণ্ডো ম্যানেজার, যাতে উইণ্ডো গ্রুপিং করা যায়
+Comment[bs]=Window manager baziran na GTK+ sa mogućnošću grupisanja prozora
+Comment[ca]=Un gestor de finestres de GTK+ amb una característica per a l'agrupament de finestres
+Comment[cs]=Správce oken založený na GTK+ s funkcí seskupování okne
+Comment[csb]=Menedżer òknów brëkùjący GTK+, z optacëją grëpòwaniô òknów
+Comment[cy]=Trefnydd ffenestri wedi'i seilio ar GTK+, efo nodwedd casglu ffenestri
+Comment[da]=En GTK+ baseret vindueshåndtering med en vinduesgrupperingsegenskab
+Comment[de]=Auf GTK+ basierender Fenstermanager mit Gruppierungsfunktion für die Fenster
+Comment[el]=Ένας διαχειριστής παραθύρων βασισμένος στο GTK+ με ένα χαρακτηριστικό ομαδοποίησης παραθύρων
+Comment[eo]=Fenestroadministrilo kun ebleco kunigi fenestrojn, kiu uzas GTK+
+Comment[es]=Un gestor de ventanas basado en GTK+ con la posibilidad de agrupar ventanas
+Comment[et]=GTK+-le tuginev aknahaldur akende grupeerimise võimalusega
+Comment[eu]=GTK+-n oinarritutako leiho kudeatzailea, leihoak taldeka biltzeko gaitasuna duena
+Comment[fa]=یک GTK+ بر مبنای مدیر پنجره توسط ویژگی گروهی کردن پنجره‌ها
+Comment[fi]=GTK+-pohjainen ikkunaohjelma ikkunoiden ryhmittely -ominaisuudella
+Comment[fr]=Un gestionnaire de fenêtres écrit en GTK+, avec une fonctionnalité de groupement des fenêtres
+Comment[fy]=In op GTK+ basearre finstersmanager mei finsterkeppelfûnksje
+Comment[gl]=Un xestor de fiestras baseado en GTK+ con agrupamento de fiestras
+Comment[he]=מנהל חלונות מבוסס GTK+ עם אפשרות לקבץ חלונות
+Comment[hi]=जीटीके+ आधारित विंडो प्रबंधक, विंडो समूह विशेषता सहित
+Comment[hr]=Upravitelj prozora zasnovan na GTK+ s mogućnošću grupiranja prozora
+Comment[hu]=Egy GTK+-alapú ablakkezelő ablakcsoportosítási lehetőséggel
+Comment[is]=Gluggastjóri sem hópar saman glugga og er byggður á GTK+
+Comment[it]=Un window manager basato su GTK+ con la possibilità di raggruppare le finestre
+Comment[ja]=ウィンドウのグループ化が可能な GTK+ ベースのウィンドウマネージャ
+Comment[ka]=ფანჯრის მენეჯერი GTK+ ს ბაზაზე ფანჯრების დაჯგუფების ფუნქციით
+Comment[kk]=GTK+ негіздеген, терезелерді топтастыру қасиеті бар, терезе менеджері
+Comment[km]=កម្មវិធី​គ្រប់គ្រង​បង្អួច​ផ្អែក​លើ GTK+ ដែល​មាន​លក្ខណៈ​ពិសេស​ដាក់​បង្អួច​ជា​ក្រុម
+Comment[ko]=창 그룹 기능을 사용하는 GTK+ 기반 창 관리자
+Comment[lt]=GTK+ paremta langų tvarkyklė su langų grupavimo galimybe
+Comment[lv]=GTK+ bāzēts logu menedžeris ar logu grupēšanas iespēju
+Comment[mk]=GTK+ базиран менаџер на прозорци со можност за групирање на прозорци
+Comment[mn]=A GTK+ суурилсан цонх бүлэглэгчтэй цонх удирдагч
+Comment[mt]=Window manager ibbażat fuq GTK+ b'faċilitajiet ta' gruppi ta' windows
+Comment[nb]=En vindusbehandler basert på GTK+ med vindusgruppering
+Comment[nds]=En Finsterpleger opbuut op GTK+, kann Finstern in Koppeln tosamenfaten
+Comment[ne]=सञ्झ्याल समूह विशेषतासँग GTK+ मा आधारित सञ्झ्याल प्रबन्धक
+Comment[nl]=Een op GTK+ gebaseerde windowmanager met venstergroeperingfunctionaliteit
+Comment[nn]=Ein GTK+-basert vindaugssjef med vindaugsgruppering
+Comment[pa]=ਇੱਕ GTK+ ਤੇ ਆਧਾਰਿਤ ਝਰੋਖਾ ਮੈਨੇਜਰ, ਜੋ ਕਿ ਝਰੋਖਿਆਂ ਨੂੰ ਇੱਕ ਥਾਂ ਸੰਭਾਲਣ ਦੀ ਸਹੂਲਤ ਨਾਲ ਲੈੱਸ ਹੈ।
+Comment[pl]=Menedżer okien korzystający z GTK+, z opcją grupowania okien
+Comment[pt]=Um gestor de janelas baseado em GTK+ com uma funcionalidade de agrupamento de janelas
+Comment[pt_BR]=Um gerenciador de janelas baseado em GTK+, com o recurso de agrupamento de janelas
+Comment[ro]=Un manager de ferestre bazat pe GTK+ și cu posibilitatea de grupare a ferestrelor
+Comment[ru]=Оконный менеджер на основе GTK+ c функцией группировки окон
+Comment[rw]=GTK + bishingiye mugenga dirishya ifite idirishya rihuza ibiranga
+Comment[se]=GTK+-vuođđoduvvon lásegieđahalli mii sáhttá sierra lásiid bidjat seamma joavkui
+Comment[sk]=Správca okien založený na GTK+ s funkciou zoskupovania okien
+Comment[sl]=Okenski upravitelj na osnovi GTK+ z možnostjo združevanja oken
+Comment[sr]=Менаџер прозора заснован на GTK+-у са особином груписања прозора
+Comment[sr@Latn]=Menadžer prozora zasnovan na GTK+-u sa osobinom grupisanja prozora
+Comment[sv]=GTK+-baserad fönsterhanterare med en funktion för fönstergruppering
+Comment[ta]=சாளர குழுப்பிரித்தல் தன்மையுடனான சாளர மேலாளர் அடிப்படையிலான GTK+.
+Comment[tg]=Мудири равзанаҳо дар асоси GTK+ дорои фаъолияти гурӯҳ кардан равзанаҳо
+Comment[th]=ตัวจัดการหน้าต่างที่ใช้พื้นฐานจาก GTK+ พร้อมด้วยความสามารถในการจัดกลุ่มหน้าต่าง
+Comment[tr]=GTK+ tabanlı bir pencere yöneticisi
+Comment[tt]=GTK+ asılında qorılğan, täräzälärne törkemli ala torğan täräzä-idäräçe
+Comment[uk]=Менеджер вікон заснований на GTK+ з підтримкою групування вікон
+Comment[uz]=A GTK+ asosida yaratilgan, oynalarni guruhlash imkoniyatiga ega oyna boshqaruvchi
+Comment[uz@cyrillic]=A GTK+ асосида яратилган, ойналарни гуруҳлаш имкониятига эга ойна бошқарувчи
+Comment[vi]=Trình quản lý cửa sổ với khả năng tạo nhóm cửa sổ dựa trên GTK+
+Comment[wa]=On manaedjeu di purneas båzé so GTK+, avou ene fonccionålité di rgroupaedje des purneas
+Comment[zh_CN]=一个基于 GTK+ 的窗口管理器,带有窗口成组特性
+Comment[zh_TW]=一個基於 GTK+ 的視窗管理程式並擁有視窗群組功能
diff --git a/tdm/kfrontend/sessions/amiwm.desktop b/tdm/kfrontend/sessions/amiwm.desktop
new file mode 100644
index 00000000..ced73c34
--- /dev/null
+++ b/tdm/kfrontend/sessions/amiwm.desktop
@@ -0,0 +1,78 @@
+[Desktop Entry]
+Type=XSession
+Exec=amiwm
+TryExec=amiwm
+Name=AmiWM
+Name[eo]=AmiFA
+Name[hi]=एमी-डबल्यूएम
+Name[sv]=Ami WM
+Name[te]=ఎమి డబ్ల్యు ఎం
+Comment=The Amiga look-alike window manager
+Comment[af]='n Amiga gebaseerde venster bestuurder
+Comment[ar]=مدبِر نوافذ مشابه لِــ Amiga
+Comment[be]=Кіраўнік вокнаў, падобны на Amiga
+Comment[bn]=অ্যামিগার মত দেখতে উইণ্ডো ম্যানেজার
+Comment[bs]=Window manager nalik na Amigu
+Comment[ca]=Un gestor de finestres que dona l'aspecte d'un Amiga
+Comment[cs]=Správce oken podobný Amize
+Comment[csb]=Menedżer òknów szlachùjący za Amiga
+Comment[cy]=Trefnydd ffenestri sy'n edrych yn debyg i'r Amiga
+Comment[da]=Amiga-lignende vindueshåndtering
+Comment[de]=Fenstermanager im Stil des Amiga
+Comment[el]=Ο διαχειριστής παραθύρων με όψη αλά Amiga
+Comment[eo]=Fenestroadministrilo kiel tiu de Amiga
+Comment[es]=Un gestor de ventanas con el aspecto de Amiga
+Comment[et]=Amiga välimusega aknahaldur
+Comment[eu]=Amigaren itxura duen leiho kudeatzailea
+Comment[fa]=Amiga شبیه مدیر پنجره
+Comment[fi]=Amigan tyylinen ikkunaohjelma
+Comment[fr]=Le gestionnaire de fenêtres ressemblant à Amiga
+Comment[fy]=In Amiga-likens finstersmanager
+Comment[gl]=Un xestor de fiestras coma o de Amiga
+Comment[he]=מנהל החלונות הדומה ל־Amiga
+Comment[hi]=अमीगा की तरह दिखने वाला विंडो प्रबंधक
+Comment[hr]=Upravitelj prozora koji podsjeća na Amigu
+Comment[hu]=Egy Amiga-szerű ablakkezelő
+Comment[is]=Gluggastjóri sem líkist Amiga tölvunum
+Comment[it]=Un window manager in stile Amiga
+Comment[ja]=Amiga に似たウィンドウマネージャ
+Comment[ka]=ფანჯრის მენეჯერი Amiga-ს სტილში
+Comment[kk]=Amiga секілді терезе менеджері
+Comment[km]=កម្មវិធី​គ្រប់គ្រប់​បង្អួច​ស្រដៀង Amiga
+Comment[ko]=Amiga를 닮은 창 관리자
+Comment[lt]=Langų tvarkyklė, panaši į Amiga
+Comment[lv]=Amiga izskata logu menedžeris
+Comment[mk]=Менаџер на прозорци со изглед на Amiga
+Comment[mn]=Amiga look-alike Цонхны удирдагч
+Comment[ms]=Pengurus tetingkap serupa Amiga
+Comment[mt]=Window manager jixbaħ lill-Amiga
+Comment[nb]=Vindusbehandler som ligner på Amiga
+Comment[nds]=De Finsterpleger mit dat Utsehn vun den Amiga
+Comment[ne]=अमिगा सञ्झ्याल प्रबन्धक जस्तो छ
+Comment[nl]=Een Amiga-achtige windowmanager
+Comment[nn]=Vindaugssjef som liknar på Amiga
+Comment[pa]=ਅਮੀਗਾ ਵਰਗਾ ਝਰੋਖਾ ਮੈਨੇਜਰ
+Comment[pl]=Menedżer okien naśladujący Amigę
+Comment[pt]=O gestor de janelas com o visual do Amiga
+Comment[pt_BR]=Um gerenciador de janelas com a aparência do Amiga
+Comment[ro]=Manager de ferestre cu aspect Amiga
+Comment[ru]=Оконный менеджер в стиле Amiga
+Comment[rw]=Amiga ijya gusa na mugenga dirishya
+Comment[se]=Amiga-lágan lásegieđahalli
+Comment[sk]=Správca okien podobný systému Amiga
+Comment[sl]=Okenski upravitelj, podoben Amiginemu
+Comment[sr]=Менаџер прозора који подсећа на Амигу
+Comment[sr@Latn]=Menadžer prozora koji podseća na Amigu
+Comment[sv]=Fönsterhanteraren som ser ut som Amiga
+Comment[ta]=சாளர மேலாளரை ஒத்த அமிகா
+Comment[tg]=Монанди мудири тирезаи Amiga look
+Comment[th]=ระบบจัดการหน้าต่างที่ดูเหมือน Amiga
+Comment[tr]=Amiga görünümlü bir pencere yöneticisi
+Comment[tt]=Amiga küreneşendä täräzä idäräçe
+Comment[uk]=Менеджер вікон на штиб Amiga
+Comment[uz]=Amiga'ga oʻxshash oyna boshqaruvchi
+Comment[uz@cyrillic]=Amiga'га ўхшаш ойна бошқарувчи
+Comment[vi]=Trình quản lý cửa sổ nhìn giống Amiga
+Comment[wa]=On manaedjeu di purneas rishonnant l' ci di l' Amiga
+Comment[zh_CN]=Amiga 外观的窗口管理器
+Comment[zh_TW]=一個看起來像 Amiga 視窗管理程式
diff --git a/tdm/kfrontend/sessions/asclassic.desktop b/tdm/kfrontend/sessions/asclassic.desktop
new file mode 100644
index 00000000..e84a0977
--- /dev/null
+++ b/tdm/kfrontend/sessions/asclassic.desktop
@@ -0,0 +1,81 @@
+[Desktop Entry]
+Type=XSession
+Exec=asclassic
+TryExec=asclassic
+Name=ASClassic
+Name[af]= ASClassic
+Name[cy]=ASClasurol
+Name[eo]=KlasikaPP
+Name[hi]=एएस-क्लॉसिक
+Name[ne]=AS शास्त्रीय
+Name[sv]=AS klassisk
+Name[ta]=ASதரமான
+Name[te]=ఏఎస్ క్లాసిక్
+Comment=AfterStep Classic, a window manager based on AfterStep v1.1
+Comment[af]=AfterStep Classic, 'n venster bestuurder wat op AfterStep v1.1 gebaseer is.
+Comment[ar]=AfterStep كلاسيك، وهو مدير نوافذ مبني على AfterStep الإصدارة 1.1
+Comment[be]=Класічны AfterStep, кіраўнік вокнаў, заснаваны на AfterStep 1.1
+Comment[bn]=আফটার-স্টেপ ক্লাসিক: আফটার-স্টেপ ১.১ ভিত্তিক একটি উইণ্ডো ম্যানেজার
+Comment[bs]=AfterStep Classic, window manager baziran na AfterStep v1.1
+Comment[ca]=El clàssic AfterStep, un gestor de finestres basat en AfterStep v1.1
+Comment[cs]=AfterStep Classic, správce oken založený na AfterStepu v1.1
+Comment[csb]=AfterStep Classic, menedżer òknów ùsôdzony na spòdlém AfterStep v1.1
+Comment[cy]=ÔlGam Clasurol, trefnydd ffenestri wedi'i seilio ar AfterStep v1.1
+Comment[da]=AfterStep Classic, en vindueshåndtering baseret på AfterStep v1.1
+Comment[de]=AfterStep Classic, ein Fenstermanager, der auf AfterStep v1.1 basiert
+Comment[el]=AfterStep κλασικός, ένας διαχειριστής παραθύρων βασισμένος στον AfterStep v1.1
+Comment[eo]=Klasika Postpaŝo, fenestroadministrilo kiel Postpaŝo v1.1
+Comment[es]=AfterStep Classic, un gestor de ventanas basado en AfterStep v1.1
+Comment[et]=AfterStep Classic - aknahaldur, mille aluseks on AfterStep v1.1
+Comment[eu]=AfterStep Classic, AfterStep v1.1-en oinarrituta dagoen leiho kudeatzailea
+Comment[fa]=AfterStep کلاسیک، مدیر پنجره بر اساس AfterStep نسخه ۱.۱
+Comment[fi]=AfterStep Classic, After Step v1.1:een pohjautuva ikkunaohjelma
+Comment[fr]=AfterStep Classic, un gestionnaire de fenêtres fondé sur AfterStep v1.1
+Comment[fy]=AfterStep Classic, In finstersmanager basearre op AfterStep 1.1
+Comment[gl]=AfterStep Clásico, un xestor de fiestras baseado en AfterSetp v1.1
+Comment[he]=AfterStep Classic, מנהל חלונות המבוסס על AfterStep v1.1
+Comment[hi]=आफ्टरस्टेप क्लासिक, एक विंडो प्रबंधक जो आफ्टरस्टेप व.1 पर आधारित है
+Comment[hr]=Klasični AfterStep, upravitelj prozora zasnovan na AfterStepu verzija 1.1
+Comment[hu]=AfterStep Classic ablakkezelő, az AfterStep v1.1 alapján
+Comment[is]=Klassískur AfterStep gluggastjóri byggður á AfterStep v1.1
+Comment[it]=AfterStep Classico, un window manager basato su AfterStep v1.1
+Comment[ja]=AfterStep クラシック, AfterStep v1.1 ベースのウィンドウマネージャ
+Comment[ka]=AfterStep Classic, ფანჯრის მენეჯერი AfterStep v1.1 -ის ბაზაზე
+Comment[kk]=AfterStep v1.1 негіздеген AfterStep Classic терезе менеджері
+Comment[km]=AfterStep បុរាណ,កម្មវិធី​គ្រប់គ្រង​បង្អួច​ដែល​ផ្អែក​លើ AfterStep v1.1
+Comment[ko]=AfterStrp 1.1 기반 창 관리자
+Comment[lt]=AfterStep Classic, langų tvarkyklė, paremta AfterStep v1.1
+Comment[lv]=Klasiskais Afterstep, logu menedžeris bāzēts uz AfterStem v1.1
+Comment[mk]=AfterStep Classic, менаџер на прозорци базиран на AfterStep v1.1
+Comment[mn]=AfterStep Classic, AfterStep v1.1 дээр суурилсан цонх удирдагч
+Comment[mt]=AfterStep klassiku, window manager ibbażat fuq AfterStep v1.1
+Comment[nb]=AfterStep Classic, en vindusbehandler basert på AfterStep v1.1
+Comment[nds]=De AfterStepClassic-Finsterpleger is opbuut op AfterStep v1.1
+Comment[ne]=AfterStep शास्त्रीय, AfterStep v१.१ मा आधारित सञ्झ्याल प्रबन्धक
+Comment[nl]=AfterStep Classic, een windowmanager gebaseerd op AfterStep 1.1
+Comment[nn]=AfterStep Classic, ein vindaugssjef som byggjer på AfterStep 1.1
+Comment[pa]=AfterStep ਟਕਸਾਲੀ, AfterStep v1.1 ਤੇ ਆਧਾਰਿਤ ਝਰੋਖਾ ਮੈਨੇਜਰ
+Comment[pl]=AfterStep Classic, menedżer okien stworzony na podstawie AfterStep v1.1
+Comment[pt]=AfterStep Classic, um gestor de janelas baseado no AfterStep v1.1
+Comment[pt_BR]=AfterSep clássico, um gerenciador de janelas baseado no AfterStep v1.1
+Comment[ro]=AfterStep Classic, un manager de ferestre bazat pe AfterStep v1.1
+Comment[ru]=AfterStep Classic, оконный менеджер на основе AfterStep v1.1
+Comment[rw]=AfterStep Classic, mugenga dirishya ishingiye kuri AfterStep v1.1
+Comment[se]=AfterStep Classic, lásegieđahalli ráhkaduvvon AfterStep 1.1 vuođul
+Comment[sk]=AfterStep Classic, správca okien založený na AfterStep v1.1
+Comment[sl]=AfterStep Classic, okenski upravitelj na osnovi AfterStep različice 1.1
+Comment[sr]=Класични AfterStep, менаџер прозора заснован на AfterStep-у верзије 1.1
+Comment[sr@Latn]=Klasični AfterStep, menadžer prozora zasnovan na AfterStep-u verzije 1.1
+Comment[sv]=Afterstep klassisk, en fönsterhanterare baserad på Afterstep version 1.1
+Comment[ta]=ஆஃப்டர்ஸ்டெப் க்ளாசிக், ஆஃப்டர்ஸ்டெப் க்ளாசிக் v1.1 அடிப்படையிலான சாளர மேலாளர்
+Comment[tg]=Мудири равзанаҳои AfterStep Classic дар асоси AfterStep v1.1
+Comment[th]=AfterStep Classic คือระบบจัดการหน้าต่างที่ใช้ฐานของอาฟเตอร์สเตปเวอร์ชั่น 1.1
+Comment[tr]=AfterStep Classic pencere yöneticisi
+Comment[tt]=AfterStep Classic, AfterStep v1.1 asılında täräzä-idäräçe
+Comment[uk]=AfterStep Classic, менеджер вікон, заснований на AfterStep v1.1
+Comment[uz]=AfterStep Classic - AfterStep v1.1 asosida yaratilgan oyna boshqaruvchi
+Comment[uz@cyrillic]=AfterStep Classic - AfterStep v1.1 асосида яратилган ойна бошқарувчи
+Comment[vi]=AfterStep Classic, một trình quản lý cửa sổ dựa trên AfterStep v1.1
+Comment[wa]=AfterStep Classic, on manaedjeu di purneas båzé so AfterStep v1.1
+Comment[zh_CN]=AfterStep 经典,一个基于 AfterStep v1.1 的窗口管理器
+Comment[zh_TW]=AfterStep 經典, 一個基於 AfterStep v1.1 的視窗管理程式
diff --git a/tdm/kfrontend/sessions/blackbox.desktop b/tdm/kfrontend/sessions/blackbox.desktop
new file mode 100644
index 00000000..457ec761
--- /dev/null
+++ b/tdm/kfrontend/sessions/blackbox.desktop
@@ -0,0 +1,88 @@
+[Desktop Entry]
+Type=XSession
+Exec=blackbox
+TryExec=blackbox
+Name=Blackbox
+Name[bn]=ব্ল্যাকবক্স
+Name[cy]= Du-flwch (Blackbox)
+Name[eo]=Negrujo
+Name[hi]=ब्लेकबॉक्स
+Name[ja]=BlackBox
+Name[mn]=Хар хайрцаг
+Name[ne]=कालो बाकस
+Name[pa]=ਕਾਲਾਬਕਸਾ
+Name[rw]=AgasandukuUmukara
+Name[ta]=கறுப்புப் பெட்டி
+Name[te]=నల్లడబ్బా
+Name[tg]=Қуттии сиёҳ
+Comment=A fast & light window manager
+Comment[af]='n Vinnige, lig gewig venster bestuurder
+Comment[ar]=مدير نوافذ خفيف وسريع
+Comment[be]=Хуткі і лёгкі кіраўнік вокнаў
+Comment[bg]=Бърз и лек мениджър на прозорци
+Comment[bn]=একটি হালকা এবং দ্রুত উইণ্ডো ম্যানেজার
+Comment[bs]=Brz i lagan window manager
+Comment[ca]=Un gestor de finestres ràpid i clar
+Comment[cs]=Rychlý a malý správce oken
+Comment[csb]=Chùtczi menedżer òknów o môłëch żądaniach
+Comment[cy]=Trefnydd ffenestri cyflym ac ysgafn
+Comment[da]=En hurtig & let vindueshåndtering
+Comment[de]=Kleiner, schneller Fenstermanager
+Comment[el]=Ένας γρήγορος και ελαφρύς διαχειριστής παραθύρων
+Comment[eo]=Rapida kaj malpeza fenestroadministrilo
+Comment[es]=Un gestor de ventanas rápido y ligero
+Comment[et]=Kiire ja vähenõudlik aknahaldur
+Comment[eu]=Leiho kudeatzaile bizkor eta arina
+Comment[fa]=یک مدیر پنجرۀ سبک و سریع
+Comment[fi]=Kevyt ja nopea ikkunaohjelma
+Comment[fr]=Un gestionnaire de fenêtres rapide et léger
+Comment[fy]=In flugge lichtgewicht finstersmanager
+Comment[ga]=Bainisteoir fuinneoga gasta éadrom
+Comment[gl]=Un xestor de fiestras lixeiro e rápido
+Comment[he]=מנהל חלונות מהיר וקל
+Comment[hi]=तेज और सरल विंडो प्रबंधक
+Comment[hr]=Brzi i lagani upravitelj prozora
+Comment[hu]=Egy gyors, egyszerű ablakkezelő
+Comment[is]=Léttur og hraðvirkur gluggastjóri
+Comment[it]=Un window manager veloce e leggero
+Comment[ja]=軽快なウィンドウマネージャ
+Comment[ka]=სწრაფი და მსუბუქი ფანჯრის მენეჯერი
+Comment[kk]=Жедел және жеңіл терезе менеджері
+Comment[km]=កម្មវិធី​គ្រប់គ្រង​បង្អួច​លឿន ហើយ​ភ្លឺ
+Comment[ko]=빠르고 가벼운 창 관리자
+Comment[lt]=Greita ir nedaug resursų naudojanti langų tvarkyklė
+Comment[lv]=Ātrs un viegls logu menedžeris
+Comment[mk]=Брз и лесен менаџер на прозорци
+Comment[mn]=Хурдан & хөнгөн цонхны удирдагч
+Comment[ms]=Pengurus tetingkap yang pantas & ringan
+Comment[mt]=Window manager ħafif u żgħir
+Comment[nb]=En rask og lett vindusbehandler
+Comment[nds]=En gaue un lütte Finsterpleger
+Comment[ne]=छिटो र हल्का सञ्झ्याल प्रबन्धक
+Comment[nl]=Een snelle lichtgewicht windowmanager
+Comment[nn]=Ein rask og lett vindaugssjef
+Comment[pa]=ਇੱਕ ਤੇਜ਼ ਅਤੇ ਹਲਕਾ ਝਰੋਖਾ ਮੈਨੇਜਰ
+Comment[pl]=Szybki menedżer okien o małych wymaganiach
+Comment[pt]=Um gestor de janelas rápido e leve
+Comment[pt_BR]=Um gerenciador de janelas rápido e leve
+Comment[ro]=Un manager de ferestre mic și rapid
+Comment[ru]=Быстрый и лёгкий оконный менеджер
+Comment[rw]=Mugenga dirishya yihuta & yoroshye
+Comment[se]=Jođánis ja geahpes lásegieđahalli
+Comment[sk]=Rýchly a nenáročný správca okien
+Comment[sl]=Hiter in lahek okenski uporavljalnik
+Comment[sr]=Брзи и лагани менаџер прозора
+Comment[sr@Latn]=Brzi i lagani menadžer prozora
+Comment[sv]=Snabb och lättviktig fönsterhanterare
+Comment[ta]=விரைவான மற்றும் இலகுவான KDE சாளர மேலாளர்
+Comment[tg]=Суст ва мудири тирезаи равшан
+Comment[th]=ระบบจัดการหน้าต่างที่เร็วและเบา
+Comment[tr]=Hızlı ve hafif bir pencere yöneticisi
+Comment[tt]=Citez ciñel täräzä-idäräçe
+Comment[uk]=Легкий та швидкий менеджер вікон
+Comment[uz]=Tez va oddiy oyna boshqaruvchi
+Comment[uz@cyrillic]=Тез ва оддий ойна бошқарувчи
+Comment[vi]=Một trình quản lý cửa sổ nhẹ và nhanh
+Comment[wa]=On ledjir et roed manaedjeu di purneas
+Comment[zh_CN]=又快又轻巧的窗口管理器
+Comment[zh_TW]=一個快速及輕量化的視窗管理程式
diff --git a/tdm/kfrontend/sessions/cde.desktop b/tdm/kfrontend/sessions/cde.desktop
new file mode 100644
index 00000000..1f2dee08
--- /dev/null
+++ b/tdm/kfrontend/sessions/cde.desktop
@@ -0,0 +1,74 @@
+[Desktop Entry]
+Type=XSession
+Exec=/usr/dt/bin/Xsession
+TryExec=/usr/dt/bin/Xsession
+Name=CDE
+Name[hi]=सीडीई
+Name[mn]=КДE
+Name[te]=సిడిఈ
+Name[tg]=Муҳити графикии муштарак (CDE)
+Name[th]=แบบ CDE
+Comment=The Common Desktop Environment, a proprietary industry standard desktop environment
+Comment[af]=Die 'Common Desktop Environment', 'n beskermde, industrie standaard werkskerm omgewing
+Comment[ar]=محيط سطح المكتب الشائع، محيط سطح المكتب الصناعي المعايير
+Comment[be]=Common Desktop Environment, прапрыетарнае стандартнае працоўнае асяроддзе
+Comment[bn]=কমন ডেস্কটপ এনভায়রনমেন্ট (Common Desktop Environment), একটি মালিকানাধীন ইনডাস্ট্রি স্ট্যান্ডার্ড
+Comment[bs]=Common Desktop Environment, vlasnička desktop okolina, industrijski standard
+Comment[ca]=The Common Desktop Environment, l'entorn d'escriptori estàndard de la indústria propietària
+Comment[csb]=Common Desktop Environment, sztandardowé industrëjné òkrãże pùltu
+Comment[cy]=Yr Amgylchedd Penbwrdd Cyffredin (Common Desktop Environment), amgylchedd penbwrdd perchnogol sy'n safonol yn y diwydiant
+Comment[da]=Common Desktop Environment, et privatejet industristandard desktopmiljø
+Comment[de]=Das Common Desktop Environment, eine proprietäre Arbeitsumgebung und ein Industriestandard
+Comment[el]=To Κοινό Περιβάλλον Επιφάνειας εργασίας, ένα βιομηχανικό πρότυπο επιφάνειας εργασίας
+Comment[eo]=La Komuna Labortablo Ĉirkaŭaĵo
+Comment[es]=El Common Desktop Environment, un estándar en los entornos de escritorio propietarios
+Comment[et]=Üldine töölaua keskond (Common Desktop Environment) on kaubanduslik standardne töölaua keskkond
+Comment[eu]=Common Desktopo Environment, mahaigain jabedun inguruneetako estandarra
+Comment[fa]=محیط رومیزی مشترک، محیط رومیزی استاندارد صنعت اختصاصی
+Comment[fi]=Common Desktop Environment, patentoitu työpöytäympäristöjen teollisuusstandardi
+Comment[fr]=Le Common Desktop Environment, un environnement de bureau propriétaire standard dans l'industrie
+Comment[fy]=The Common Desktop Environment, In kommersjele yndustrieel standerdisearre buroblêd omwrâld
+Comment[gl]=O Common Desktop Environment, un entorno de escritório proprietario estándar para industria
+Comment[he]=The Common Desktop Environment, סביבת עבודה מסחרית וקניינית סטנדרטית
+Comment[hi]=सामूहिक डेस्कटॉप माहौल, एक स्वामित्व युक्त औद्योगिक मानक डेस्कटॉप माहौल
+Comment[hr]=Opće okruženje radne površine, standardizirano industrijskim vlasništvima
+Comment[hu]=The Common Desktop Environment, egy kereskedelmi, kváziszabványnak számító grafikus környezet
+Comment[is]=Common Desktop Environment er lokað skjáborðsumhverfi sem var staðlað umhverfi til skamms tíma
+Comment[it]=Il Common Desktop Environment, un desktop environment proprietario standard.
+Comment[ja]=Common Desktop Environment,プロプライエタリな業界標準のデスクトップ環境
+Comment[ka]=Common Desktop Environment, UNIX -ის სამუშაო სფეროს სამრეწვლო სტანდარტი
+Comment[kk]=Common Desktop Environment - UNIX жұмыс ортаның өнеркәсіп стандарты
+Comment[km]=The Common Desktop Environment, បរិស្ថាន​ផ្ទៃតុ​ខ្នាត​គំរូ​ដែល​មាន​កម្មសិទ្ធិ
+Comment[lt]=Common Desktop Environment, nuosavybinių sistemų standartinė darbastalio tvarkyklė
+Comment[mk]=Common Desktop Environment, сопственичка индустриски стандардна работна околина
+Comment[mn]=Нийтлэг дэлгэцийн системийн орчин, үйлдвэрийн стандарт дэлгэцийн системийн орчин
+Comment[ms]=Persekitaran Desktop Biasa, persekitaran desktop standard industri proprietari
+Comment[mt]=Common Desktop Environment, ambjent grafiku propjetarju u standard tal-industrija
+Comment[nb]=Common desktop Environment, et godseid skrivebordsmiljø som er standard i programvareindustrien
+Comment[nds]=De Common Desktop Environment, de Schriefdisch-Ümgeven vun en proprieteren Industrie-Standard
+Comment[ne]=साझा डेस्कटप वातावरण, श: शुल्क उद्योग मानक डेस्कटप वातावरण
+Comment[nl]=The Common Desktop Environment, een commerciële industrieel gestandariseerde desktop environment
+Comment[nn]=Common Desktop Environment, eit godseigd skrivebordsmiljø som er standard i programvareindustrien
+Comment[pa]=ਇੱਕ ਆਮ ਵੇਹੜਾ ਵਾਤਾਵਰਣ, ਇੱਕ ਵਪਾਰਿਕ ਮਿਆਰ ਦਾ ਵੇਹੜਾ ਵਾਤਾਵਰਣ
+Comment[pl]=Common Desktop Environment, standardowe przemysłowe środowisko pulpitu
+Comment[pt]=O Common Desktop Environment, um ambiente de trabalho gráfico padrão e proprietário
+Comment[pt_BR]=O Ambiente de Trabalho Comum (CDE), um ambiente de trabalho proprietário padrão da indústria
+Comment[ro]=Common Desktop Environment, un mediu grafic proprietar și devenit standard industrial
+Comment[ru]=Common Desktop Environment, промышленный стандарт рабочей среды UNIX
+Comment[rw]=Ibikikije Ibiro Rusange, ibikikije ibiro bisanzwe bwite by'isosiyete
+Comment[se]=Common Desktop Environment, čállinbeavdebiras mii lea standárda prográmmagálvoindustriijas
+Comment[sk]=The Common Desktop Environment, proprietárne štandardné pracovné prostredie
+Comment[sl]=Common Desktop Environment, lastniško standardno industrijsko namizno okolje
+Comment[sr]=„Common Desktop Environment“, власничко индустријски стандардно радно окружење
+Comment[sr@Latn]=„Common Desktop Environment“, vlasničko industrijski standardno radno okruženje
+Comment[sv]=Common Desktop Environment, en privatägd industristandard skrivbordsmiljö
+Comment[ta]=பொதுவான மேல்மேசை, தன்உரிமை உடைய நிறுவனத்தின் நிலையான மேல்மேசை சூழல்
+Comment[tg]=Common Desktop Environment дар асоси UNIX
+Comment[th]=Common Desktop Environment คือ สภาพแวดล้อมของพื้นที่ทำงานที่ได้มาตรฐานอุตสาหกรรม ที่ไม่ใช่ซอฟต์แวร์เสรี
+Comment[tr]=Common Desktop Environment (CDE)
+Comment[tt]=Common Desktop Environment, UNIX öçen citeşterü standardı
+Comment[uk]=The Common Desktop Environment, закритий промисловий стандарт графічного середовища
+Comment[vi]=Môi trường Màn hình nền Chung, một môi trường màn hình nền giữ bản quyền, tuân thủ chuẩn công nghiệp
+Comment[wa]=Li Comon Evironmint d' Sicribanne (Common Desktop Environment), on evironmint d' sicribanne nén libe po l' industreye
+Comment[zh_CN]=通用窗口环境(CDE),私有工业标准的桌面环境
+Comment[zh_TW]=The Common Desktop Environment, 一個有專利的工業標準
diff --git a/tdm/kfrontend/sessions/ctwm.desktop b/tdm/kfrontend/sessions/ctwm.desktop
new file mode 100644
index 00000000..e7ee8447
--- /dev/null
+++ b/tdm/kfrontend/sessions/ctwm.desktop
@@ -0,0 +1,72 @@
+[Desktop Entry]
+Type=XSession
+Exec=ctwm
+TryExec=ctwm
+Name=CTWM
+Name[eo]=TFAC
+Name[hi]=सीटीडबल्यूएम
+Name[te]=సి టి డబ్ల్యు ఎం
+Comment=Claude's Tab Window Manager, TWM enhanced by virtual screens, etc.
+Comment[af]=Claude se Tab venster bestuurder. Dis TWM wat met virtuele skerms verbeter is
+Comment[ar]=مدير نوافذ Claude's Tab، وهي TWM محسّن بشاشات وهمية، إلخ.
+Comment[be]=Кіраўнік вокнаў з укладкамі ад Claude, TWM з падтрымкай віртуальных экранаў і інш.
+Comment[bg]=Claude"s Tab Window Manager, TWM enhanced by virtual screens, etc.
+Comment[bn]=ক্লড-এর ট্যাব উইণ্ডো ম্যানেজার
+Comment[bs]=Claude's Tab Window Manager, TWM proširen virtuelnim ekranima itd.
+Comment[ca]=Gestor de finestres amb pestanyes d'en Claude, millores TWM per a pantalles virtuals, etc.
+Comment[csb]=Menedżer òknów Claude, TWM zbògacony ò wirtualné pùltë, ëtp.
+Comment[cy]=Trefnydd Ffenestri Tab Claude, TWM wedi ei wella gan sgriniau rhith, ayyb.
+Comment[da]=Claude's Tab vindueshåndtering, TWM udvidet med virtuelle skærme osv.
+Comment[de]=Claudes Fenstermanager mit Karteikartenfenstern, eine verbesserte Fassung von TWM mit virtuellen Ansichten usw.
+Comment[el]=Ο διαχειριστής παραθύρων Tab του Claude, ο TWM εμπλουτισμένος με εικονικές οθόνες, κτλ.
+Comment[eo]=Taba Fenestroadministrilo de Claude, TWM, bonigita per virtualaj ekranoj ktp
+Comment[es]=Claude's Tab Window Manager, TWM mejorado con pantallas virtuales, etc.
+Comment[et]=Claude kaartidega aknahaldur, aluseks TWM, mida on täiendatud virtuaaltöölaudadega jne.
+Comment[eu]=Claude's Tab leiho kudeatzailea, pantaila birtual eta abarrez hobetutako TWMa
+Comment[fa]=مدیر پنجرۀ تب Claude، TWM، گسترش‌یافته توسط پرده‌های مجازی و غیره.
+Comment[fi]=Clauden välilehtiikkunaohjelma. TWM, johon lisätty muun muassa virtuaalityöpöydät.
+Comment[fr]=Claude's Tab Window Manager, TWM avec en plus les bureaux virtuels, etc.
+Comment[fy]=Claude's Tab _indow Manager, TWM útbreide mei firtuele skermen etc.
+Comment[gl]=Xestor de Fiestras de Claude, TWM mellorado con pantallas virtuais, etc.
+Comment[he]=Claude's Tab Window Manager, TWM המשופרת על ידי מסכים וירטואליים וכו'
+Comment[hi]=क्लाउडे का टैब युक्त विंडो प्रबंधक, टीडबल्यूएम को आभासी स्क्रीन इत्यादि से बेहतर बनाया गया.
+Comment[hr]=Claudov Tab upravitelj prozora, TWM poboljšan virtualnim zaslonima, itd.
+Comment[hu]=Claude lapozós ablakkezelője, lényegében a TWM, kiegészítve virtuális képernyőkkel, egyebekkel
+Comment[is]=Tab gluggastjórinn eftir Claude sem hefur verið endurbættur með sýndarskjáum og fl.
+Comment[it]=Window manager con linguette di Claude, TWM migliorato con schermi virtuali, ecc.
+Comment[ja]=TWM に仮想デスクトップなどを強化した Claude のウィンドウマネージャ
+Comment[ka]=Claude's Tab Window Manager - TWM-ის გაუმჯობესებული ვერსია
+Comment[kk]=Claude's Tab Window Manager, TWM-ның жетілдірген нұсқасы.
+Comment[km]=កម្មវិធី​គ្រប់គ្រង​បង្អួច​ជា​ផ្ទាំង​របស់ Claude, TWM ដែល​ធ្វើ​ឲ្យ​ប្រសើរ​ដោយ​អេក្រង់​និមិត្ត​ជាដើម
+Comment[lt]=Claude kortelių langų tvarkyklė, TWM praplėsta virtualių ekranų palaikymu ir t.t.
+Comment[mk]=Claude's Tab Window Manager, TWM подобрен менаџер со виртуелни екрани итн.
+Comment[mn]=Клаудиагийн  ТАВ цонхны удирдагч, TWM виртуал дэлгэцээр өргөтгөгдсөн, гэх мэт.
+Comment[mt]=Claude's Tab Window Manager, TWM flimkien ma' virtual screens, eċċ.
+Comment[nb]=Claude's Tab Window Manager, TWM forbedret med virtuelle skrivebord,osv.
+Comment[nds]=Claude's Tab Finsterpleger, TWM verbetert üm virtuelle Schriefdischen usw.
+Comment[ne]=क्लाउडको ट्याब सञ्झ्याल प्रबन्धक, अवास्तविक पर्दाद्वारा बृद्धि गरिएको TWM, आदि
+Comment[nl]=Claude's Tab Window Manager, TWM uitgebreid met virtuele schermen etc.
+Comment[nn]=Claude's Tab Window Manager, TWM med virtuelle skrivebord og andre forbetringar
+Comment[pa]=ਕਲਾਉਡੀ ਦਾ ਟੈਬ ਝਰੋਖਾ ਮੈਨੈਜਰ, TWM ਫਰਜ਼ੀ ਪਰਦਿਆਂ ਆਦਿ ਨਾਲ ਲੈੱਸ ਹੈ।
+Comment[pl]=Menedżer okien Claude, TWM wzbogacony o wirtualne pulpity, itp.
+Comment[pt]=O Tab Window Manager do Claude, um TWM melhorado com ecrãs virtuais, etc.
+Comment[pt_BR]=O gerenciador de janelas em abas do Claude, o TWM melhorado pelas telas virtuais, etc.
+Comment[ro]=Managerul de ferestre al lui Claude, o versiune îmbunătățită de TWM cu ecrane virtuale etc.
+Comment[ru]=Claude's Tab Window Manager - улучшенная версия TWM
+Comment[rw]=Mugenga Dirishya y'Agafishi ya Claude, TWM ivuguruwe na mugaragaza zitagaragara, n'ibindi
+Comment[se]=Claudea Tab Window Manager, TWM mas lea virtuella čállinbeavddit ja eará buorideamit.
+Comment[sk]=Claude's Tab Window Manager, TWM rozšírený o virtuálne plochy, atď.
+Comment[sl]=Claude's Tab Window Manager, TWM izboljšan z navideznimi zasloni ipd.
+Comment[sr]=„Claude's Tab Window Manager“, TWM побољшан виртуелним екранима и сл.
+Comment[sr@Latn]=„Claude's Tab Window Manager“, TWM poboljšan virtuelnim ekranima i sl.
+Comment[sv]=Claudes fönsterhanterare med flikar, TWM förbättrad med virtuella skärmar, etc.
+Comment[ta]= க்ளூடின் தத்தல் சாளர மேளாளர், TWM ஆல் மேம்படுத்தப்பட்ட மெய்நிகர் திரைகள்..
+Comment[tg]=Claude's Tab Window Manager - Версияи навтарини TWM
+Comment[th]=ตัวจัดการแท็บหน้าต่างของ Claude คือ TWM ที่เพิ่มความสามารถด้วยหน้าจอเสมือน และอื่นๆ
+Comment[tr]=Claude's Sekme Pencere Yöneticisi, sanal ekranlar ile TWM genişletilmiş, vb.
+Comment[tt]=Claude's Tab Window Manager, TWM'nıñ qulaylanğan töre
+Comment[uk]=Claude's Tab Window Manager, TWM з підтримкою віртуальних екранів, тощо.
+Comment[vi]=Trình quản lý cửa sổ kiểu Thẻ của Claude, TWM cải tiến với màn hình ảo v.v.
+Comment[wa]=Li Manaedjeu di Purneas a Linwetes di Claude (Claude's Tab Window Manager). TWM permete des forveyowès waitroûles, evnd.
+Comment[zh_CN]=Claude 的标签式窗口管理器,加强了虚拟屏幕等功能的 TWM。
+Comment[zh_TW]=Claude's Tab 視窗管理程式, 基於 TWM 並加強虛擬螢幕等功能
diff --git a/tdm/kfrontend/sessions/cwwm.desktop b/tdm/kfrontend/sessions/cwwm.desktop
new file mode 100644
index 00000000..51b60abd
--- /dev/null
+++ b/tdm/kfrontend/sessions/cwwm.desktop
@@ -0,0 +1,74 @@
+[Desktop Entry]
+Type=XSession
+Exec=cwwm
+TryExec=cwwm
+Name=CWWM
+Name[eo]=CWFA
+Name[hi]=सीडबल्यूडबल्यूएम
+Name[te]=సి డబ్ల్యు డబ్ల్యు ఎం
+Comment=The ChezWam Window Manager, a minimalist window manager based on EvilWM
+Comment[af]=Die ChezWam venster bestuurder. Dis 'n minimalistiese venster bestuurder wat op EvilWM gebaseer is.
+Comment[ar]=مدير نوافذ ChezWam، وهو مدير نوافذ مصغّر مبني على EvilWM
+Comment[be]=Кіраўнік вокнаў ChezWam, мінімалістычны, заснаваны на EvilWM
+Comment[bn]=ChezWam উইণ্ডো ম্যানেজার, EvilWM ভিত্তিক একটি উইণ্ডো ম্যানেজার
+Comment[bs]=ChezWam Window Manager, minimalistički window manager baziran na EvilWM
+Comment[ca]=El gestor de finestres ChezWam, un gestor de finestres minimalista basat en EvilWM
+Comment[cs]=ChezWam, minimalistický správce oken založený na EvilWM
+Comment[csb]=Menedżer òknów ChezWam, prosti menedżer òknów ùsôdzony na spòdlém EvilWM
+Comment[cy]=Y Trefnydd Ffenestri ChezWam, trefnydd ffenestri lleiafol wedi'i seilio ar EvilWM
+Comment[da]=ChezWam vindueshåndteringen, en minimalistisk vindueshåndtering baseret på EvilWM
+Comment[de]=Deer ChezWam-Fenstermanager, eine minimalistische Lösung, die auf EvilWM basiert
+Comment[el]=Ο ChezWam διαχειριστής παραθύρων, ένας μινιμαλιστικός διαχειριστής παραθύρων βασισμένος στον EvilWM
+Comment[eo]=La ChezWam Fenestroadministrilo, devenigita de MalbonaFA
+Comment[es]=El gestor de ventanas ChezWam, un gestor minimalista basado en EvilWM
+Comment[et]=ChezWami aknahaldur on vähenõudlik aknahaldur, mille aluseks on EvilWM
+Comment[eu]=ChezWarn leiho kudeatzailea, EvilWM-en oinarritutako leiho kudeatzaile minimalista
+Comment[fa]=مدیر پنجره ChezWam، مدیر پنجرۀ کمینه بر اساس EvilWM
+Comment[fi]=ChezWam, minimalistinen EvilWM:ään pohjautuva ikkunaohjelma.
+Comment[fr]=Le ChezWam Window Manager, un gestionnaire de fenêtres minimaliste fondé sur EvilWM
+Comment[fy]=The ChezWam Window Manager, in minimalistyske finstersmanager baseare op EvilWM
+Comment[gl]=O Xestor de Fiestras ChezWarm, un xestor minimalista baseado en EvilWM
+Comment[he]=The ChezWam Window Manager, מנהל חלונות מינימליסטי המבוסס על EvilWM
+Comment[hi]=चेकवाम विंडो प्रबंधक, एक अल्पतम विंडो प्रबंधक EvilWM पर आधारित
+Comment[hr]=ChezWam, minimalistički upravitelj prozora zasnovan na EvilWM
+Comment[hu]=ChezWam ablakkezelő, egy nagyon egyszerű ablakkezelő az EvilWM alapján
+Comment[is]=ChezWam gluggastjórinn er lágmarks gluggastjóri sem er byggður á EvilWM
+Comment[it]=Il ChezWam Window Manager, un window manager minimalista basato su EvilWM
+Comment[ja]=ChezWam ウィンドウマネージャ, EvilWM ベースの小さなウィンドウマネージャ
+Comment[ka]=ChezWam Window Manager - მინიმალისტური ფანჯრის მენეჯერი EvilWM -ის ბაზაზე
+Comment[kk]=ChezWam Window Manager, EvilWM-негіздеген шағын терезе менеджері
+Comment[km]=កម្មវិធី​គ្រប់គ្រង​បង្អួច ChezWam ដែល​ជា​កម្មវិធី​គ្រប់គ្រង​បង្អួច​មិន​សូវ​សម្បូរ​បែប​ហើយ​ផ្អែក​លើ EvilWM
+Comment[lt]=ChezWam langų tvarkyklė, minimalistinė langų tvarkyklė, paremta EvilWM
+Comment[mk]=ChezWam Window Manager, минималистички менаџер на прозорци базиран на EvilWM
+Comment[mn]=ChezWam Цонхны удирдагч, EvilWM дээр суурилсан хамгийн жижиг цонхны удирдагч
+Comment[mt]=ChezWam Window Manager - window manager minimu ibbażat fuq EvilWM
+Comment[nb]=The ChezWam Window Manager, en minimalistisk vindusbehandler basert på EvilWM
+Comment[nds]=De ChezWam Finsterpleger is minimalistisch un buut op EvilWM op
+Comment[ne]=चेजवाम सञ्झ्याल प्रबन्धक, EvilWM आधारित मिनिमलिस्ट सञ्झ्याल प्रबन्धक
+Comment[nl]=The ChezWam Window Manager, een minimalistische windowmanager gebaseerd op EvilWM
+Comment[nn]=ChezWam Window Manager, ein minimalistisk vindaugssjef som byggjer på EvilWM
+Comment[pa]=ChezWam ਝਰੋਖਾ ਮੈਨੇਜਰ, ਇੱਕ EvilWM ਤੇ ਆਧਾਰਿਤ ਹਲਕਾ ਝਰੋਖਾ ਮੈਨੇਜਰ ਹੈ
+Comment[pl]=Menedżer okien ChezWam, prosty menedżer okien stworzony na podstawie EvilWM
+Comment[pt]=O ChezWam Window Manager, um gestor de janelas minimalista baseado no EvilWM
+Comment[pt_BR]=O gerenciador de janelas de ChezWam, um gerenciador de janelas minimalista baseado no EvilWM
+Comment[ro]=Managerul de ferestre ChezWam, o versiune minimalistică bazată pe EvilWM
+Comment[ru]=ChezWam Window Manager - минимальный оконный менеджер на основе EvilWM
+Comment[rw]=Mugenga Dirishya ChezWam, mugenga dirishya igira-nto ishingiye kuri EvilWM
+Comment[se]=ChezWam Window Manager, ein minimalisttalaš lásegieđahalli, ráhkaduvvon EvilWM vuođul
+Comment[sk]=The ChezWam Window Manager, minimálny správca okien založený na EvilWM
+Comment[sl]=ChezWam Window Manager, skromen okenski upravitelj na osnovi EvilWM
+Comment[sr]=„ChezWam Window Manager“, минималистички менаџер прозора заснован на EvilWM-у
+Comment[sr@Latn]=„ChezWam Window Manager“, minimalistički menadžer prozora zasnovan na EvilWM-u
+Comment[sv]=Fönsterhanteraren Chezwam, en minimalistisk fönsterhanterare baserad på Ond WM
+Comment[ta]=செஸ்வாம் சாளர மேளாளர்,EvilWM ஐ அடிப்படையிலான குறைந்தபட்ச சாளர மேளாளர்
+Comment[tg]=ChezWam Window Manager - Мудири равзанаҳои хурд дар асоси EvilWM
+Comment[th]=ตัวจัดการหน้าต่าง ChezWarm คือ ระบบจัดการ หน้าต่างขนาดเล็ก สร้างจากพื้นฐานของ EvilWM
+Comment[tr]=ChezWam Pencere Yöneticisi
+Comment[tt]=ChezWam Window Manager, EvilWM asılında ciñel täräzä-idäräçe
+Comment[uk]=Мінімалістичний менеджер вікон ChezWam, заснований на EvilWM
+Comment[uz]=EvilWM asosida yaratilgan juda oddiy oyna boshqaruvchi
+Comment[uz@cyrillic]=EvilWM асосида яратилган жуда оддий ойна бошқарувчи
+Comment[vi]=Trình quản lý cửa sổ ChezWam, một trình quản lý cửa sổ đơn giản dựa trên EvilWM
+Comment[wa]=Li Manaedjeu di Purneas di ChezWam (ChezWam Window Manager). On manaedjeu di purneas tot simpe, båzé so EvilWM
+Comment[zh_CN]=ChezWam 窗口管理器,基于 EvilWM 的最小化窗口管理器
+Comment[zh_TW]=The ChezWam 視窗管理程式,基於 EvilWM 的小型化視窗管理程式
diff --git a/tdm/kfrontend/sessions/enlightenment.desktop b/tdm/kfrontend/sessions/enlightenment.desktop
new file mode 100644
index 00000000..66dcdd57
--- /dev/null
+++ b/tdm/kfrontend/sessions/enlightenment.desktop
@@ -0,0 +1,86 @@
+[Desktop Entry]
+Type=XSession
+Exec=enlightenment_start
+TryExec=enlightenment
+Name=Enlightenment
+Name[bn]=এনলাইটেনমেন্ট
+Name[cy]=Goleuni (Enlightenment)
+Name[eo]=Lumaĵo
+Name[fa]=روشن‌فکری
+Name[hi]=एनलाइटनमेंट
+Name[km]=ភ្លឺ
+Name[mn]=Гэгээрэл
+Name[ne]=बुद्धत्व
+Name[pa]=ਗਿਆਨ
+Name[rw]=Imurika
+Name[ta]=விளக்கிக்கூறுதல்
+Name[te]=జ్ఞానొదయం
+Comment=An extremely themable very feature-rich window manager
+Comment[af]='n Uitbreibare, tema geaktiveerde venster bestuurder
+Comment[ar]=مدير نوافذ غني بالمزايا وقابل لاستخدام السّمات بشكل كبير.
+Comment[be]=Абсалютна змяняльны, багаты на здольнасці кіраўнік вокнаў
+Comment[bn]=প্রচুর বৈশিষ্ট্য সম্বলিত একটি উইণ্ডো ম্যানেজার, যা বহুভাবে নিজের পছন্দমত বদলে নেওয়া যায়
+Comment[bs]=Izuzetno prilagodljiv window manager bogat opcijama
+Comment[ca]=Un gestor de finestres extremadament temible molt ric en característiques
+Comment[cs]=Na funkce bohatý správce oken s širokou škálou témat
+Comment[csb]=Bògati w fùnkcëje menedżer òknów ò wiôldżich mòżnotach zjinaczi wëzdrzatkù
+Comment[cy]=Trefnydd ffenestri sy'n llawn o nodweddion, efo llawer o themau.
+Comment[da]=En ekstremt tema-fleksibel egenskabsrig vindueshåndtering
+Comment[de]=Sehr design- und funktionsreicher Fenstermanager
+Comment[el]=Ένας εξαιρετικά παραμετροποιήσιμος και πλούσιος σε χαρακτηριστικά διαχειριστής παραθύρων
+Comment[eo]=Fenestroadministrilo kun tre multaj eblecoj
+Comment[es]=Un gestor de ventanas lleno de características y extremadamente personalizable
+Comment[et]=Äärmiselt paljude teemade ja väga laialdaste võimalustega aknahaldur
+Comment[eu]=Gaitasun ugari dituen, eta zeharo pertsonalizagarria den leiho kudeatzailea
+Comment[fa]=مدیر پنجره با ویژگی زیاد و شدیداً موضوعی
+Comment[fi]=Erittäin muokattavissa oleva ominaisuusrikas ikkunaohjelma
+Comment[fr]=Un gestionnaire de fenêtres avec beaucoup de thèmes et de fonctionnalités
+Comment[fy]=In tige rike en ynstelbere finstersmanager
+Comment[gl]=Un xestor de fiestras moi configurábel en apariencia e rico en características
+Comment[he]=מנהל חלונות פונקציונלי המכיל אפשרויות רבות להגדרת ערכות נושא
+Comment[hi]=एक विंडो प्रबंधक जो अत्यंत प्रसंग युक्त तथा विशेषता से भरपूर है
+Comment[hr]=Izuzetno prilagodljiv upravitelj prozora, bogat mogućnostima
+Comment[hu]=Egy nagyon sokoldalúan témázható, sok lehetőséget biztosító ablakkezelő
+Comment[is]=Afskaplega öflugur gluggastjóri með góðum þemastuðningi
+Comment[it]=Un window manager estremamente temabile con molte funzionalità
+Comment[ja]=詳細な部分までもテーマ化が可能な非常に多機能のウィンドウマネージャ
+Comment[ka]=მრავალფუნქციური ფანჯრის მენეჯერი თემების მხარდაჭერით
+Comment[kk]=Қасиеттер жағынан бай, көп тақырыпты терезе менеджері
+Comment[km]=កម្មវិធី​គ្រប់គ្រង​បង្អួច​មាន​លក្ខណៈ​ពិសេស​សម្បូរ​បែប ដែល​អាច​ប្ដូរ​រូបរាង​បាន​តាម​ចិត្ត
+Comment[ko]=다양한 곳을 꾸밀 수 있는 기능이 풍부한 창 관리자
+Comment[lt]=Daug temų ir savybių turinti langų tvarkyklė
+Comment[lv]=Tēmām un iespējām bagāts logu menedžeris
+Comment[mk]=Менаџер на прозорци богат со можности и екстремно подложен на стилизирање со теми
+Comment[mn]=Маш ирээдүйтэй цонхны удирдагч
+Comment[ms]=Pengurus tetingkap kaya ciri yang amat boleh tema
+Comment[mt]=Window manager rikk u b'ħafna effetti viżwali.
+Comment[nb]=En svært omfattende vindusbehandler som kan tilpasses med temaer
+Comment[nds]=En Finsterpleger mit bannig vele Funkschonen un Mustern
+Comment[ne]=अत्याधिक विषयवस्तु योग्य धेरै आकृति सञ्झ्याल प्रबन्धक
+Comment[nl]=Een zeer rijke en configureerbare windowmanager
+Comment[nn]=Ein svært omfattande vindaugssjef som kan tilpassast med tema
+Comment[pa]=ਇੱਕ ਸਰੂਪ ਦੇ ਪੂਰੇ ਫੀਚਰਾਂ ਨਾਲ ਭਰਪੂਰ ਝਰੋਖਾ ਮੈਨੇਜਰ
+Comment[pl]=Bogaty w funkcje menedżer okien o dużych możliwościach zmiany wyglądu
+Comment[pt]=Um gestor de janelas muito rico em funcionalidades e extremamente personalizado na sua aparência
+Comment[pt_BR]=Um gerenciador de janelas rico em recursos e extremamente configurável através de temas
+Comment[ro]=Un manager de ferestre extrem de versatil și cu multe facilități
+Comment[ru]=Многофункциональный, поддерживающий темы оконный менеджер
+Comment[rw]=Mugenga Dirishya biranga-bikize cyane ngirwa-nsanganyamatsiko mu buryo burenze
+Comment[se]=Lášegieđahalli mas leat erenoamáš ollu doaimmat ja maid sáhttá heivehit fáttáin
+Comment[sk]=Správca okien s veľkým množstvom funkcií a extrémnou podporou tém
+Comment[sl]=Okenski upravitelj, zelo prilagodljiv in poln možnosti
+Comment[sr]=Изузетно прилагодљив менаџер прозора са пуно могућности
+Comment[sr@Latn]=Izuzetno prilagodljiv menadžer prozora sa puno mogućnosti
+Comment[sv]=En ytterst anpassningsbar mycket funktionsrik fönsterhanterare
+Comment[ta]=நிறைய தன்மைகள் அடங்கிய சாளர மேளாளர்
+Comment[tg]=Мудири равзанаҳо дорои мавзӯъҳои гуногун ва дигар бисёр функсияҳо
+Comment[th]=ระบบจัดการหน้าต่างที่เต็มไปด้วยความสามารถ และใช้ชุดตกแต่งมากมาย
+Comment[tr]=İleri derecede temalanabilir, özellik zengini bir masaüstü yöneticisi
+Comment[tt]=Küpçaralı tışlanulı täräzä-idäräçe
+Comment[uk]=Менеджер вікон з потужною підтримкою тем та різноманітних функцій
+Comment[uz]=Mavzu va imkoniyatlarga juda boy oyna boshqaruvchi
+Comment[uz@cyrillic]=Мавзу ва имкониятларга жуда бой ойна бошқарувчи
+Comment[vi]=Một trình quản lý cửa sổ cực kỳ dễ thay đổi sắc thái với nhiều tích năng
+Comment[wa]=On manaedjeu di purneas foirt bén po-z eployî des tinmes et foirt ritche en usteyes
+Comment[zh_CN]=强主题化的多功能窗口管理器
+Comment[zh_TW]=一個功能相當豐富的視窗管理程式
diff --git a/tdm/kfrontend/sessions/evilwm.desktop b/tdm/kfrontend/sessions/evilwm.desktop
new file mode 100644
index 00000000..3c8c4f65
--- /dev/null
+++ b/tdm/kfrontend/sessions/evilwm.desktop
@@ -0,0 +1,77 @@
+[Desktop Entry]
+Type=XSession
+Exec=evilwm
+TryExec=evilwm
+Name=EvilWM
+Name[eo]=MalbonaFA
+Name[hi]=एविलडबल्यूएम
+Name[sv]=Ond WM
+Name[te]=ఈవిల్ డబ్ల్యు ఎం
+Comment=A minimalist window manager based on AEWM
+Comment[af]='n Minimalistiese venster bestuurder wat op AEWM gebaseer is
+Comment[ar]=مدير نوافذ مصغّر مبني على AEWM
+Comment[be]=Кіраўнік вокнаў для мінімаліста, заснаваны на AEWM
+Comment[bn]=AEWM ভিত্তিক একটি পরিমিত উইণ্ডো ম্যানেজার
+Comment[bs]=Minimalistički window manager baziran na AEWM
+Comment[ca]=Un gestor de finestres minimalista basat en AEWM
+Comment[cs]=Minimalistický správce oken založený na AEWM
+Comment[csb]=Prosti menedżer òknów ùsôdzony na spòdlém AEWM
+Comment[cy]=Trefnydd ffenestri lleiafol wedi'i seilio ar AEM
+Comment[da]=En minimalistisk vindueshåndtering baseret på AEWM
+Comment[de]=Minimalistischer Fenstermanager, der auf AEWM basiert
+Comment[el]=Ένας μινιμαλιστικός διαχειριστής παραθύρων βασισμένος στον AEWM
+Comment[eo]=Minimumema fenestroadministrilo
+Comment[es]=Un administrado de ventanas minimalista basado en AEWM
+Comment[et]=Vähenõudlik aknahaldur, mille aluseks on AEWM
+Comment[eu]=AEWMn oinarritutako leiho kudeatzaile minimalista
+Comment[fa]=یک مدیر پنجرۀ کمینه براساس AEWM
+Comment[fi]=Minimalistinen, AEWM:ään pohjautuva ikkunaohjelma
+Comment[fr]=Un gestionnaire de fenêtres fondé sur AEWM
+Comment[fy]=In minimalistyske finstersmanager basearre op AEWM
+Comment[gl]=Un xestor de fiestras minimalista baseado en AEWM
+Comment[he]=מנהל חלונות מינימליסטי המבוסס על AEWM
+Comment[hi]= एक अल्पतम विंडो प्रबंधक एईडबल्यूएम पर आधारित
+Comment[hr]=Minimalistički upravitelj prozora zasnovan na AEWM-u
+Comment[hu]=Egy nagyon egyszerű ablakkezelő az AEWM alapján
+Comment[is]=Lágmarks gluggastjóri sem er byggður á AEWM
+Comment[it]=Un window manager minimalista basato su AEWM
+Comment[ja]=AEWM ベースの小さなウィンドウマネージャ
+Comment[ka]=მინიმალისტური ფანჯრის მენეჯერი AEWM-ის ბაზაზე
+Comment[kk]=AEWM-негіздеген шағын терезе менеджері
+Comment[km]=កម្មវិធី​គ្រប់គ្រង​បង្អួច​លក្ខណៈ​ពិសេស​តិច ដែល​ផ្អែក​លើ AEWM
+Comment[ko]=AEWM 기반 창 관리자
+Comment[lt]=Minimalistinė langų tvarkyklė, paremta AEWM
+Comment[lv]=Minimālistisks logu menedžeris bāzēts uz AEWM
+Comment[mk]=Минималистички менаџер на прозорци базиран на AEWM
+Comment[mn]=AEWM дээр суурилсан цонхны удирдагч
+Comment[mt]=Window manager minimu ibbażat fuq AEWM
+Comment[nb]=En minimalistisk vindusbehandler basert på AEWM
+Comment[nds]=En minimalistischen Finsterpleger, de op AEWM opbuut
+Comment[ne]=AEWM आधारित मिनिमलिस्ट सञ्झ्याल प्रबन्धक
+Comment[nl]=Een minimalistische windowmanager gebaseerd op AEWM
+Comment[nn]=Ein minimalistisk vindaugssjef som byggjer på AEWM
+Comment[pa]=AEWM ਤੇ ਆਧਾਰਿਤ ਨਿਊਨਤਮ ਝਰੋਖਾ ਮੈਨੇਜਰ
+Comment[pl]=Prosty menedżer okien stworzony na podstawie AEWM
+Comment[pt]=Um gestor de janelas minimalista baseado no AEWM
+Comment[pt_BR]=Um gerenciador de janelas minimalista baseado no AEWM
+Comment[ro]=Un manager de ferestre minimalistic bazat pe AEWM
+Comment[ru]=Минимальный оконный менеджер, основанный на AEWM
+Comment[rw]=Mugenga dirishya igira-nto ishingiye kuri AEWM
+Comment[se]=Minimalisttalaš lásegieđahalli, ráhkaduvvon AEWM vuođul
+Comment[sk]=Minimálny správca okien založený na AEWM
+Comment[sl]=Minimalističen okenski upravitelj na osnovi AEWM
+Comment[sr]=Минималистички менаџер прозора заснован на AEWM-у
+Comment[sr@Latn]=Minimalistički menadžer prozora zasnovan na AEWM-u
+Comment[sv]=Minimalistisk fönsterhanterare baserad på AEWM
+Comment[ta]=AEWM அடிப்படையிலான குறைதபட்ச சாளர மேளாளர்
+Comment[tg]=Мудири равзанаҳои хурд дар асоси AEWM
+Comment[th]=ระบบจัดการหน้าต่างขนาดเล็ก สร้างจากพื้นฐานของ AEWM
+Comment[tr]=AEWM tabanlı küçük bir pencere yöneticisi
+Comment[tt]=AEWM asılında ciñel täräcä-idäräçe
+Comment[uk]=Мінімалістичний менеджер вікон, заснований на AEWM
+Comment[uz]=AEWM asosida yaratilgan juda oddiy oyna boshqaruvchi
+Comment[uz@cyrillic]=AEWM асосида яратилган жуда оддий ойна бошқарувчи
+Comment[vi]=Một trình quản lý cửa sổ đơn giản dựa trên AEWM
+Comment[wa]=On manaedjeu di purneas minimå båzé so AEWM
+Comment[zh_CN]=基于 AEWM 的最小化窗口管理器
+Comment[zh_TW]=一個基於 AEWM 的小型化視窗管理程式
diff --git a/tdm/kfrontend/sessions/fluxbox.desktop b/tdm/kfrontend/sessions/fluxbox.desktop
new file mode 100644
index 00000000..df6a0813
--- /dev/null
+++ b/tdm/kfrontend/sessions/fluxbox.desktop
@@ -0,0 +1,81 @@
+[Desktop Entry]
+Type=XSession
+Exec=startfluxbox
+TryExec=startfluxbox
+Name=Fluxbox
+Name[bn]=ফ্লাক্সবক্স
+Name[cy]=Llif-flwch (Fluxbox)
+Name[eo]=Fluujo
+Name[hi]=फ्ल्क्स-बाक्स
+Name[ne]=फ्लक्सबक्स
+Name[pa]=ਫਕਸਬਕਸ
+Name[rw]=AgasandukuUmujyoumwe
+Name[ta]=ப்ளக்ஸ் பெட்டி
+Name[te]=ఫ్లక్స్ బాక్స్
+Name[tg]=Қуттии Flux
+Comment=A highly configurable and low resource window manager based on Blackbox
+Comment[af]='n Baie konfigureerbare en lae hulpbron intensiewe venster bestuurder, wat op Blackbox gebaseer is.
+Comment[ar]=مدير نوافذ قابل للإعداد بشكل كبير ويستخدم القليل من موارد الجهاز وهو مبني Blackbox
+Comment[be]=Кіраўнік вокнаў, заснаваны на Blackbox, з вялікімі здольнасцямі змяняцца і з нізкай патрабавальнасцю да рэсурсаў
+Comment[bn]=ব্ল্যাকবক্স ভিত্তিক একটি উইণ্ডো ম্যানেজার, যা নানাভাবে কনফিগার করা যায়, কিন্তু খুবই কম রিসোর্স ব্যবহার করে
+Comment[bs]=Visoko prilagodljiv window manager sa malim zauzećem resursa baziran na Blackbox-u
+Comment[ca]=Un gestor de finestres altament configurable i que necessita pocs recursos basat en Blackbox
+Comment[cs]=Vysoce přizpůsobitelný a nízkoúrovňový správce oken založený na Blackboxu
+Comment[csb]=Menedżer òknów òpiarti na Blackbox ò wiôldżich mòżnotach kònfigùracëji ë nisczich żądaniach
+Comment[cy]=Trefnydd ffenestri hawdd ei ffurfweddu ac ysgafn ei ddefnydd adnoddau, wedi'i seilio ar Ddu-flwch (Blackbox)
+Comment[da]=En meget indstillelig vindueshåndtering med lavt ressourceforbrug baseret på Blackbox
+Comment[de]=Sehr flexibler, aber ressourcenschonender Fenstermanager, der auf Blackbox basiert
+Comment[el]=Ένας ιδιαίτερα παραμετροποιήσιμος και με μικρή κατανάλωση πόρων διαχειριστής παραθύρων βασισμένος στον Blackbox
+Comment[eo]=Fenestroadministrilo devenigita de Negrujo
+Comment[es]=Un gestor de ventanas basado en Blackbox muy configurable y con poco consumo de recursos
+Comment[et]=Väga hästi kohandatav ja vähenõudlik aknahaldur, mille aluseks on Blackbox
+Comment[eu]=Blackbox-en oinarritutako leiho kudeatzaile zeharo konfiguragarria, eta errekurtso gutxi kontsumitzen dituena
+Comment[fa]=یک مدیر پنجره با قابلیت پیکربندی بالا و منبع پایین براساس Blackbox
+Comment[fi]=Blackboxiin pohjautuva erittäin muokattava ja vähäisen resurssitarpeen omaava ikkunaohjelma
+Comment[fr]=Un gestionnaire de fenêtres très configurable et utilisant peu de ressources, fondé sur Blackbox
+Comment[fy]=In tige ynstelbere lichtgewicht finstersmanager basearre op Blackbox
+Comment[gl]=Un xestor de fiestras moi configurábel e lixeiro baseado en Blackbox
+Comment[he]=מנהל חלונות בעל הגדרות רבות הצורך משאבים מעטים ומבוסס עלBlackbox
+Comment[hi]=ब्लेक-बाक्स आधारित, अत्यंत कॉन्फ़िगरेबल तथा कम साधन चाहने वाला विंडो प्रबंधक
+Comment[hr]=Visoko konfigurabilan upravitelj prozora, male potrošnje resursa, zasnovan na Blackbox-u
+Comment[hu]=Egy Blackbox-alapú ablakkezelő, alacsony erőforrásigénnyel, sokféle beállítási lehetőséggel
+Comment[is]=Öflugur gluggastjóri sem notar lítið af auðlindum vélarinnar sem er byggður á Blackbox
+Comment[it]= Un window manager molto configurabile e che utilizza poche risorse basato su Blackbox
+Comment[ja]=Blackbox ベースの高度な設定が可能でリソースにやさしいウィンドウマネージャ
+Comment[ka]=კონფიგურირებადი ფანჯრის მენეჯერი Blackbox -ის ბაზაზე
+Comment[kk]=Blackbox-негіздеген, баптаулары көп, үнемді терезе менеджері
+Comment[km]=កម្មវិធី​គ្រប់គ្រង​បង្អួច​ដែល​អាច​កំណត់​រចនាសម្ព័ន្ធ​បាន​ខ្ពស់ និង​ប្រើ​ធនធាន​តិច ដែល​ផ្អែក​លើ Blackbox
+Comment[ko]=Blackbox 기반의 다양하게 설정 가능하고 자원을 적게 사용하는 창 관리자
+Comment[lt]=Daug konfigūravimo parinkčių turinti ir mažai resursų naudojanti langų tvarkyklė, paremta Blackbox
+Comment[lv]=Plaši konfigurējams un resursus taupošs logu menedžeris bāzēts uz Blackbox
+Comment[mk]=Високо конфигурабилен менаџер на прозорци со мали побарувања на ресурси базиран на Blackbox
+Comment[mn]=Хар хайрцаг дээр суурилсан маш бага нөөц хэрэглэдэг тохируулах чадвар өндөр цонхны удирдагч
+Comment[mt]=Window manager ħafif u konfigurabbli ibbażat fuq BlackBox
+Comment[nb]=En lite ressurskrevende og svært fleksibel vindusbehandler basert på Blackbox
+Comment[nds]=En Finsterpleger, de wenig Ressourcen bruukt, man bannig vele Instellen hett. Opbuut op Blackbox
+Comment[ne]=कालो बाकसमा आधारित उच्च कन्फिगरयोग्य र न्यून संसाधन सञ्झ्याल प्रबन्धक
+Comment[nl]=Een zeer configureerbare lichtgewicht windowmanager gebaseerd op Blackbox.
+Comment[nn]=Ein lite ressurskrevjande og svært fleksibel vindaugssjef basert på Blackbox
+Comment[pa]=ਇੱਕ ਬਿਲਕੁੱਲ ਹਲਕਾ ਤੇ ਜਿਆਦਾ ਸੋਧਯੋਗ ਫਾਇਲ਼ ਮੈਨੇਜਰ
+Comment[pl]=Menedżer okien oparty na Blackbox o dużych możliwościach konfiguracji i niskich wymaganiach
+Comment[pt]=Um gestor de janelas bastante configurável e que usa poucos recursos, baseado no Blackbox
+Comment[pt_BR]=Um gerenciador de janelas altamente configurável e com baixo uso de recursos, baseado no Blackbox
+Comment[ro]=Un manager de ferestre foarte configurabil și mic, bazat pe Blackbox
+Comment[ru]=Настраиваемый оконный менеджер, основанный на Blackbox
+Comment[rw]=Mugenga dirishya mbonezwa mu buryo buhanitse kandi bikorana bike ishingiye ku Gasandukumukara
+Comment[se]=Lásegieđahalli vuođđoduvvon Blackbox:as, hui heivehahtti ja geavaha unnán resurssaid
+Comment[sk]=Veľmi konfigurovateľný a nenáročný správca okien založený na Blackbox
+Comment[sl]=Visoko nastavljiv in učinkovit okenski upravitelj na osnovi Blackboxa
+Comment[sr]=Врло подесив и незахтеван менаџер прозора заснован на Blackbox-у
+Comment[sr@Latn]=Vrlo podesiv i nezahtevan menadžer prozora zasnovan na Blackbox-u
+Comment[sv]=Mycket anpassningsbar fönsterhanterare med litet resursbehov baserad på Blackbox
+Comment[ta]=கறுப்புபெட்டி சார்ந்த அமைக்கக்கூடிய குறைந்த வள சாளர மேளாளர்
+Comment[tg]=Мудири равзанаҳои танзимшаванда дар асоси Blackbox
+Comment[th]=ระบบจัดการหน้าต่างที่สามารถปรับแต่งได้อย่างละ เอียด และใช้ทรัพยากรน้อย สร้างบนพื้นฐานของ Blackbox
+Comment[tr]=Blackbox temelli, kolayca özelleştirilebilir düşük kaynaklı bir pencere yöneticisi
+Comment[tt]=Blackbox asılında qorılğan, yaqşı caylana torğan täräcä-idäräçe
+Comment[uk]=Дуже гнучкий та невибагливий для ресурсів менеджер вікон, заснований на Blackbox
+Comment[vi]=Một trình quản lý cửa sổ rất dễ cấu hình và đòi hỏi ít tài nguyên dựa trên Blackbox
+Comment[wa]=On ledjir et foirt apontiåve manaedjeu di purneas båzé so Blackbox
+Comment[zh_CN]=基于 BlackBox 可深入配置且占用资源较少的窗口管理器
+Comment[zh_TW]=一個基於 Blackbox 且高可組態及低資源的視窗管理程式
diff --git a/tdm/kfrontend/sessions/flwm.desktop b/tdm/kfrontend/sessions/flwm.desktop
new file mode 100644
index 00000000..d6dc2401
--- /dev/null
+++ b/tdm/kfrontend/sessions/flwm.desktop
@@ -0,0 +1,77 @@
+[Desktop Entry]
+Type=XSession
+Exec=flwm
+TryExec=flwm
+Name=FLWM
+Name[eo]=RMFA
+Name[hi]=एफएलडबल्यूएम
+Name[te]=ఎఫ్ ఎల్ డబ్ల్యు ఎం
+Name[th]=ตัวจัดการหน้าต่าง FLWM
+Comment=The Fast Light Window Manager, based primarily on WM2
+Comment[af]=Die Vinnige, ligte venster bestuurder, wat op WM2 gebaseer is
+Comment[ar]=مدير النوافذ السريع الخفيف، مبني بشكل أساسي على WM2
+Comment[be]=The Fast Light Window Manager, заснаваны на WM2
+Comment[bn]=ফাস্ট লাইট উইণ্ডো ম্যানেজার, WM2 ভিত্তি করে তৈরি
+Comment[bs]=Fast Light Window Manager, baziran uglavnom na WM2
+Comment[ca]=El gestor de finestres Fast Light, primerament basat en WM2
+Comment[cs]=Fast Light Window Manager založený původně na WM2
+Comment[csb]=Fast Light Window Manager, menedżer òknów ùsôdzony przédno na WM2
+Comment[cy]=Y Trefnydd Ffenestri Chwim ac Ysgafn, wedi'i seilio ar WM2 am y rhan fwyaf
+Comment[da]=Fast Light vindueshåndtering, baseret først og fremmest på WM2
+Comment[de]=Der Fast Light Window Manager, der vor allem auf WM2 basiert
+Comment[el]=Ο Fast Light διαχειριστής παραθύρων, βασισμένος κυρίως στον WM2
+Comment[eo]=Rapida malpeza fenestroadministrilo
+Comment[es]=El Fast Light Window Manager, basado principalmente en WM2
+Comment[et]=Kiire ja vähenõudlik aknahaldur, aluseks peamiselt WM2
+Comment[eu]=Batez ere WM2-en oinarritutako leiho kudeatzaile arin eta bizkorra
+Comment[fa]=مدیر پنجرۀ سریع و سبک، در اصل بر اساس WM2
+Comment[fi]=Fast Light Window Manager. Pohjautuu suurimmaksi osin WM2:een
+Comment[fr]=The Fast Light Window Manager, fondé au départ sur WM2
+Comment[fy]=De Fast Light Window Manager, primêr basearre op WM2
+Comment[gl]=O Fast Light Window Manager, un xestor de fiestras lixeiro baseado en WM2
+Comment[he]=The Fast Light Window Manager, מבוסס בעיקר על WM2
+Comment[hi]=मुख्यतः डबल्यूएम2 पर आधारित तेज और हल्का विंडो प्रबंधक
+Comment[hr]=Brzi i lagani upravitelj prozora (FLWM), zasnovan na WM2
+Comment[hu]=Fast Light Window Manager ablakkezelő, elsősorban a WM2 alapján
+Comment[is]=Léttur og hraðvirkur gluggastjóri sem er aðallega byggður á WM2
+Comment[it]=Il Fast Light Window Manager, basato principalmente su WM2
+Comment[ja]="高速で軽い"WM2 ベースのウィンドウマネージャ
+Comment[ka]=სწრაფი და მსუბუქი ფანჯრების მენეჯერი WM2 -ის ბაზაზე
+Comment[kk]=WM2-негіздеген жеңіл және жедел терезе менеджері
+Comment[km]=Fast Light Window Manager ផ្អែក​ចម្បង​លើ WM2
+Comment[ko]=WM2에 기반을 둔 빠르고 가벼운 창 관리자
+Comment[lt]=Greita ir lengva langų tvarkyklė, paremta daugiausiai WM2
+Comment[lv]=Fast Light logu menedžeris, bāzēts galvenokārt uz WM2
+Comment[mk]=Fast Light Window Manager, менаџер примарно базиран на WM2
+Comment[mn]=Ерөнхийдөө WM2 дээр суурилсан хурдан хөнгөн цонхны удирдагч
+Comment[mt]=Fast Light Window Manager, ibbażat fuq WM2
+Comment[nb]=En rask, lett vindusbehandler (Fast Light Window Manager), mest basert på WM2
+Comment[nds]=De "Fast Light"-Finsterpleger, to'n gröttsten Deel opbuut op WM2
+Comment[ne]=साधारणतया WM2 मा आधारित छिटो हल्का सञ्झ्याल प्रबन्धक
+Comment[nl]=De Fast Light Window Manager, primair gebaseerd op WM2.
+Comment[nn]=Ein rask, lett vindaugssjef (Fast Light Window Manager), mest basert på WM2
+Comment[pa]=ਇੱਕ ਹਲਕਾ ਤੇਜ਼ ਫਾਇਲ਼ ਮੈਨੇਜਰ, ਜੋ ਕਿ WM2 ਤੇ ਆਧਾਰਿਤ ਹੈ
+Comment[pl]=Fast Light Window Manager, menedżer okien stworzony głownie na podstawie WM2
+Comment[pt]=O Fast Light Window Manager, baseado em primeiro lugar no WM2
+Comment[pt_BR]=Acrônimo para Fast Light Window Manager (gerenciador rápido e leve), baseado primeiramente no WM2
+Comment[ro]=Fast Light Window Manager, bazat în principal pe WM2
+Comment[ru]=Быстрый и лёгкий оконный менеджер, основанный на WM2
+Comment[rw]=Mugenga Dirishya Yihuta Yoroshye, ishingiye mbere na mbere kuri WM2
+Comment[se]=Jođánis, geahpes lásegieđahalli, ráhkaduvvon WM2 vuođul
+Comment[sk]=The Fast Light Window Manager založený na WM2
+Comment[sl]=Fast Light Window Manager, v glavnem na osnovi WM2
+Comment[sr]=Брзи лаки менаџер прозора (FLWM), заснован на WM2
+Comment[sr@Latn]=Brzi laki menadžer prozora (FLWM), zasnovan na WM2
+Comment[sv]=Fönsterhanteraren Fast Light Window Manager, i huvudsak baserad på WM2
+Comment[ta]=WM2 அடிப்படையிலான வேக ஒளி வேக சாளர மேளாளர்
+Comment[tg]=мудири равзанаҳои тез ва осон дар асоси WM2
+Comment[th]=ระบบจัดการหน้าต่างที่เร็วและเบา สร้างบนพื้นฐานของ WM2
+Comment[tr]=Fast Light Pencere Yöneticisi
+Comment[tt]=WM2 asılında qorılğan, citez ciñel täräcä-idäräçe
+Comment[uk]=Швидкий легкий менеджер вікон, заснований здебільшого на WM2
+Comment[uz]=Asosan WM2 asosida yaratilgan tez va oddiy oyna boshqaruvchi
+Comment[uz@cyrillic]=Асосан WM2 асосида яратилган тез ва оддий ойна бошқарувчи
+Comment[vi]=Trình Quản lý Cửa sổ Nhanh và Nhẹ, dựa chủ yếu vào WM2
+Comment[wa]=Li Roed et Ledjir Manaedjeu di Purneas (ast Light Window Manager) båzé so WM2
+Comment[zh_CN]=又快又轻巧的窗口管理器,主要基于 WM2
+Comment[zh_TW]=一個主要基於 WM2 且快速及輕量化的視窗管理程式
diff --git a/tdm/kfrontend/sessions/fvwm.desktop b/tdm/kfrontend/sessions/fvwm.desktop
new file mode 100644
index 00000000..20ae57d4
--- /dev/null
+++ b/tdm/kfrontend/sessions/fvwm.desktop
@@ -0,0 +1,71 @@
+[Desktop Entry]
+Type=XSession
+Exec=fvwm
+TryExec=fvwm
+Name=FVWM
+Name[hi]=एफ़वीडबल्यूएम
+Name[te]=ఎఫ్ వి డబ్ల్యు ఎం
+Comment=A powerful ICCCM-compliant multiple virtual desktop window manager
+Comment[af]='n Kragtige, ICCCM-aanpasbare veelvuldige virtuele werkskermvenster bestuurder.
+Comment[ar]=مدير نوافذ قوي ومتوافق مع ICCCM ذي أسطح مكتب وهمية متعددة
+Comment[be]=Магутны ICCCM-сумяшчальны кіраўнік вокнаў з падтрымкай віртуальных працоўных сталоў
+Comment[bn]= একটি শক্তিশালী ICCCM-compliant উইণ্ডো ম্যানেজার, যাতে একাধিক ভার্চুয়াল ডেস্কটপ সম্ভব
+Comment[bs]=Moćan ICCCM-sukladan window manager sa podrškom za više virtuelnih desktopa
+Comment[ca]=Un poderós gestor de finestres per a múltiples escriptoris virtuals que compleix amb ICCCM
+Comment[csb]=Stolemny menedżer òknów zgòdny z ICCCM òbsłëgòwujący wirtualné pùltë
+Comment[cy]=Trefnydd ffenestri pwerus efo penbyrddau rhith lluosol, sy'n cydymffurfio â ICCCM
+Comment[da]=En kraftig ICCCM-kompliant vindueshåndtering med flere virtuelle desktoppe
+Comment[de]=Ein leistungsfähiger ICCCM-kompatibler Fenstermanager mit virtuellen Arbeitsflächen
+Comment[el]=Ένας πολύ δυνατός, συμβατός με το ICCCM, διαχειριστής παραθύρων με πολλαπλές εικονικές επιφάνειες εργασίας
+Comment[eo]=Fenestroadministrilo
+Comment[es]=Un potente gestor de ventanas, compatible con ICCCM y que soporta varios escritorios virtuales
+Comment[et]=Võimas ICCCM nõuetele vastav mitme virtuaalse töölauaga aknahaldur
+Comment[eu]=ICCCM konpatiblea den, eta mahaigain birtual ugari dituen leiho kudeatzaile bortitza
+Comment[fa]=یک مدیر پنجرۀ رومیزی مجازی چندگانه ICCCM-compliant نیرومند
+Comment[fi]=Tehokas ICCCM-mukautuva virtuaalityöpöytiä tukeva ikkunaohjelma
+Comment[fr]=Un gestionnaire de fenêtres puissant compatible ICCCM avec gestion de bureaux virtuels multiples
+Comment[fy]=In krêftige ICCCM-compliant finstersmanager mei meardere buroblêden
+Comment[gl]=Un xestor de fiestras potente acorde coa ICCCM con múltiplos escritórios virtuais
+Comment[he]=מנהל חלונות עצמתי עם תאימות ל־ICCCM בעל שולחנות עבודה וירטואליים רבים
+Comment[hi]=शक्तिशाली आईसीसीसीएम-कम्पलाएंट अनेक आभासी डेस्कटॉप विंडो प्रबंधक
+Comment[hr]=Comment=Moćni, ICCCM kompatibilan, upravitelj prozora s više virtualnih radnih površina
+Comment[hu]=Egy sokoldalú, ICCCM-kompatibilis ablakkezelő, virtuális munkaasztal-kezeléssel
+Comment[is]=Öflugur ICCCM samhæfður gluggastjóri með sýndarskjáborðum
+Comment[it]=Un window manager molto potente e ICCCM-compatibile che supporta i desktop virtuali
+Comment[ja]=複数の仮想デスクトップをサポートした ICCCM 準拠のパワフルなウィンドウマネージャ
+Comment[ka]=ძლიერი ICCCM-თავსებადი ვირტულური სამუშაო დაფების მხარდამჭერი ფანჯრის მენეჯერი
+Comment[kk]=Қуатты ICCCM-үйлесімді, көп виртуалды үстел қолдайтын терезе менеджері
+Comment[km]=កម្មវិធី​គ្រប់គ្រង​បង្អួច​ផ្ទៃតុ​និមិត្ត​ច្រើន​ដ៏​មាន​អានុភាព ដែល​អនុវត្ត​តាម ICCCM
+Comment[ko]=다중 가상 데스크톱을 사용하는 ICCCM 호환 창 관리자
+Comment[lt]=galinga, su ICCCM suderinama daugelio virtualių darbastalių langų tvarkyklė
+Comment[lv]=Spēcīgs ICCCM-savietojams logu menedžeris ar vairāku darbvirsmu atbalstu
+Comment[mk]=Моќен менаџер на прозорци со повеќе виртуелни површини во согласност со ICCCM
+Comment[mt]=Window manager b'saħħtu, konformi ma' ICCCM, b'desktops virtwali.
+Comment[nb]=En slagkraftig vindusbehandler med flere virtuelle skrivebord, som støtter ICCCM
+Comment[nds]=En kraftvulle, ICCCM-kompatible Finsterpleger mit vele virtuelle Schriefdischen
+Comment[ne]=शक्तिशाली ICCCM-मान्ने बहुविध अवास्तविक डेस्कटप सञ्झ्याल प्रबन्धक
+Comment[nl]=Een krachtige ICCCM-compliant windowmanager met meerdere bureaubladen
+Comment[nn]=Ein slagkraftig vindaugssjef med fleire virtuelle skrivebord, som støttar ICCCM
+Comment[pa]=ਇੱਕ ਸ਼ਕਤੀਸ਼ਾਲੀ ICCCM-ਅਨੁਕੂਲ ਬਹੁ-ਫਰਜ਼ੀ ਵੇਹੜਿਆਂ ਵਾਲਾ ਝਰੋਖਾ ਮੈਨੇਜਰ
+Comment[pl]=Potężny menedżer okien zgodny z ICCCM obsługujący wirtualne pulpity
+Comment[pt]=Um gestor de janelas poderoso em conformidade com o ICCCM e que suporta vários ecrãs virtuais
+Comment[pt_BR]=Um poderoso gerenciador de janelas compatível com o ICCM, com suporte a múltiplas áreas de trabalho virtuais
+Comment[ro]=Un manager de ferestre puternic compliant ICCCM ce suportă ecrane virtuale
+Comment[ru]=Мощный ICCCM-совместимый оконный менеджер, поддерживающий виртуальные рабочие столы
+Comment[rw]=igikoranisha-ICCCM nyembaraga mugenga dirishya y'ibiro bitandukanye bitagaragara
+Comment[se]=Fápmolaš ICCCM-heivvolaš lásegieđahalli mas lea virtuealla čállinbeavddit
+Comment[sk]=Výkonný správca okien kompatibilný s ICCCM s podporou virtuálnych plôch
+Comment[sl]=Močan okenski upravitelj z večimi navideznimi namizji in popolnoma v skladu z ICCCM
+Comment[sr]=Моћни, ICCCM-сагласни, менаџер прозора са више виртуелних радних површина
+Comment[sr@Latn]=Moćni, ICCCM-saglasni, menadžer prozora sa više virtuelnih radnih površina
+Comment[sv]=Kraftfull fönsterhanterare med flera virtuella skrivbord som följer ICCCM
+Comment[ta]=ICCCM-தரத்தில் பலதரப்பட்ட மெய்நிகர் மேல் மேசை சாளர மேளாளர்
+Comment[tg]=Мудири равзанаҳои бузург дар асоси ICCCM дорои мудири равзанаҳо бо мизикориҳои виртуалӣ
+Comment[th]=ระบบจัดการหน้าต่างที่มีหลายพื้นที่ทำงานเสมือน สอดรับกับ ICCCM ประสิทธิภาพสูง
+Comment[tr]=Güçlü ICCCM-uyumlu çoklu sanal masaüstü yöneticisi
+Comment[tt]=ICCCM-ütkän, küp öställär totqan köçle täräzä-idäräçe
+Comment[uk]=Потужний, сумісний з ICCCM менеджер вікон, з підтримкою віртуальних стільниць
+Comment[vi]=Trình quản lý cửa sổ tương thích với ICCCM nhiều chức năng, quản lý nhiều màn hình nền ảo
+Comment[wa]=On manaedjeu di purneas avou multi-forveyowès sicribannes ki rote avou ICCM
+Comment[zh_CN]=强大的多虚拟桌面窗口管理器,与 ICCCM 兼容
+Comment[zh_TW]=一個強大的 ICCCM 相容的多重虛擬桌面視窗管理程式
diff --git a/tdm/kfrontend/sessions/fvwm2.desktop b/tdm/kfrontend/sessions/fvwm2.desktop
new file mode 100644
index 00000000..1a25a91e
--- /dev/null
+++ b/tdm/kfrontend/sessions/fvwm2.desktop
@@ -0,0 +1,70 @@
+[Desktop Entry]
+Type=XSession
+Exec=fvwm2
+TryExec=fvwm2
+Name=FVWM2
+Name[te]=ఎఫ్ వి డబ్ల్యు ఎం 2
+Comment=A powerful ICCCM-compliant multiple virtual desktop window manager
+Comment[af]='n Kragtige, ICCCM-aanpasbare veelvuldige virtuele werkskermvenster bestuurder.
+Comment[ar]=مدير نوافذ قوي ومتوافق مع ICCCM ذي أسطح مكتب وهمية متعددة
+Comment[be]=Магутны ICCCM-сумяшчальны кіраўнік вокнаў з падтрымкай віртуальных працоўных сталоў
+Comment[bn]= একটি শক্তিশালী ICCCM-compliant উইণ্ডো ম্যানেজার, যাতে একাধিক ভার্চুয়াল ডেস্কটপ সম্ভব
+Comment[bs]=Moćan ICCCM-sukladan window manager sa podrškom za više virtuelnih desktopa
+Comment[ca]=Un poderós gestor de finestres per a múltiples escriptoris virtuals que compleix amb ICCCM
+Comment[csb]=Stolemny menedżer òknów zgòdny z ICCCM òbsłëgòwujący wirtualné pùltë
+Comment[cy]=Trefnydd ffenestri pwerus efo penbyrddau rhith lluosol, sy'n cydymffurfio â ICCCM
+Comment[da]=En kraftig ICCCM-kompliant vindueshåndtering med flere virtuelle desktoppe
+Comment[de]=Ein leistungsfähiger ICCCM-kompatibler Fenstermanager mit virtuellen Arbeitsflächen
+Comment[el]=Ένας πολύ δυνατός, συμβατός με το ICCCM, διαχειριστής παραθύρων με πολλαπλές εικονικές επιφάνειες εργασίας
+Comment[eo]=Fenestroadministrilo
+Comment[es]=Un potente gestor de ventanas, compatible con ICCCM y que soporta varios escritorios virtuales
+Comment[et]=Võimas ICCCM nõuetele vastav mitme virtuaalse töölauaga aknahaldur
+Comment[eu]=ICCCM konpatiblea den, eta mahaigain birtual ugari dituen leiho kudeatzaile bortitza
+Comment[fa]=یک مدیر پنجرۀ رومیزی مجازی چندگانه ICCCM-compliant نیرومند
+Comment[fi]=Tehokas ICCCM-mukautuva virtuaalityöpöytiä tukeva ikkunaohjelma
+Comment[fr]=Un gestionnaire de fenêtres puissant compatible ICCCM avec gestion de bureaux virtuels multiples
+Comment[fy]=In krêftige ICCCM-compliant finstersmanager mei meardere buroblêden
+Comment[gl]=Un xestor de fiestras potente acorde coa ICCCM con múltiplos escritórios virtuais
+Comment[he]=מנהל חלונות עצמתי עם תאימות ל־ICCCM בעל שולחנות עבודה וירטואליים רבים
+Comment[hi]=शक्तिशाली आईसीसीसीएम-कम्पलाएंट अनेक आभासी डेस्कटॉप विंडो प्रबंधक
+Comment[hr]=Comment=Moćni, ICCCM kompatibilan, upravitelj prozora s više virtualnih radnih površina
+Comment[hu]=Egy sokoldalú, ICCCM-kompatibilis ablakkezelő, virtuális munkaasztal-kezeléssel
+Comment[is]=Öflugur ICCCM samhæfður gluggastjóri með sýndarskjáborðum
+Comment[it]=Un window manager molto potente e ICCCM-compatibile che supporta i desktop virtuali
+Comment[ja]=複数の仮想デスクトップをサポートした ICCCM 準拠のパワフルなウィンドウマネージャ
+Comment[ka]=ძლიერი ICCCM-თავსებადი ვირტულური სამუშაო დაფების მხარდამჭერი ფანჯრის მენეჯერი
+Comment[kk]=Қуатты ICCCM-үйлесімді, көп виртуалды үстел қолдайтын терезе менеджері
+Comment[km]=កម្មវិធី​គ្រប់គ្រង​បង្អួច​ផ្ទៃតុ​និមិត្ត​ច្រើន​ដ៏​មាន​អានុភាព ដែល​អនុវត្ត​តាម ICCCM
+Comment[ko]=다중 가상 데스크톱을 사용하는 ICCCM 호환 창 관리자
+Comment[lt]=galinga, su ICCCM suderinama daugelio virtualių darbastalių langų tvarkyklė
+Comment[lv]=Spēcīgs ICCCM-savietojams logu menedžeris ar vairāku darbvirsmu atbalstu
+Comment[mk]=Моќен менаџер на прозорци со повеќе виртуелни површини во согласност со ICCCM
+Comment[mt]=Window manager b'saħħtu, konformi ma' ICCCM, b'desktops virtwali.
+Comment[nb]=En slagkraftig vindusbehandler med flere virtuelle skrivebord, som støtter ICCCM
+Comment[nds]=En kraftvulle, ICCCM-kompatible Finsterpleger mit vele virtuelle Schriefdischen
+Comment[ne]=शक्तिशाली ICCCM-मान्ने बहुविध अवास्तविक डेस्कटप सञ्झ्याल प्रबन्धक
+Comment[nl]=Een krachtige ICCCM-compliant windowmanager met meerdere bureaubladen
+Comment[nn]=Ein slagkraftig vindaugssjef med fleire virtuelle skrivebord, som støttar ICCCM
+Comment[pa]=ਇੱਕ ਸ਼ਕਤੀਸ਼ਾਲੀ ICCCM-ਅਨੁਕੂਲ ਬਹੁ-ਫਰਜ਼ੀ ਵੇਹੜਿਆਂ ਵਾਲਾ ਝਰੋਖਾ ਮੈਨੇਜਰ
+Comment[pl]=Potężny menedżer okien zgodny z ICCCM obsługujący wirtualne pulpity
+Comment[pt]=Um gestor de janelas poderoso em conformidade com o ICCCM e que suporta vários ecrãs virtuais
+Comment[pt_BR]=Um poderoso gerenciador de janelas compatível com o ICCM, com suporte a múltiplas áreas de trabalho virtuais
+Comment[ro]=Un manager de ferestre puternic compliant ICCCM ce suportă ecrane virtuale
+Comment[ru]=Мощный ICCCM-совместимый оконный менеджер, поддерживающий виртуальные рабочие столы
+Comment[rw]=igikoranisha-ICCCM nyembaraga mugenga dirishya y'ibiro bitandukanye bitagaragara
+Comment[se]=Fápmolaš ICCCM-heivvolaš lásegieđahalli mas lea virtuealla čállinbeavddit
+Comment[sk]=Výkonný správca okien kompatibilný s ICCCM s podporou virtuálnych plôch
+Comment[sl]=Močan okenski upravitelj z večimi navideznimi namizji in popolnoma v skladu z ICCCM
+Comment[sr]=Моћни, ICCCM-сагласни, менаџер прозора са више виртуелних радних површина
+Comment[sr@Latn]=Moćni, ICCCM-saglasni, menadžer prozora sa više virtuelnih radnih površina
+Comment[sv]=Kraftfull fönsterhanterare med flera virtuella skrivbord som följer ICCCM
+Comment[ta]=ICCCM-தரத்தில் பலதரப்பட்ட மெய்நிகர் மேல் மேசை சாளர மேளாளர்
+Comment[tg]=Мудири равзанаҳои бузург дар асоси ICCCM дорои мудири равзанаҳо бо мизикориҳои виртуалӣ
+Comment[th]=ระบบจัดการหน้าต่างที่มีหลายพื้นที่ทำงานเสมือน สอดรับกับ ICCCM ประสิทธิภาพสูง
+Comment[tr]=Güçlü ICCCM-uyumlu çoklu sanal masaüstü yöneticisi
+Comment[tt]=ICCCM-ütkän, küp öställär totqan köçle täräzä-idäräçe
+Comment[uk]=Потужний, сумісний з ICCCM менеджер вікон, з підтримкою віртуальних стільниць
+Comment[vi]=Trình quản lý cửa sổ tương thích với ICCCM nhiều chức năng, quản lý nhiều màn hình nền ảo
+Comment[wa]=On manaedjeu di purneas avou multi-forveyowès sicribannes ki rote avou ICCM
+Comment[zh_CN]=强大的多虚拟桌面窗口管理器,与 ICCCM 兼容
+Comment[zh_TW]=一個強大的 ICCCM 相容的多重虛擬桌面視窗管理程式
diff --git a/tdm/kfrontend/sessions/fvwm95.desktop b/tdm/kfrontend/sessions/fvwm95.desktop
new file mode 100644
index 00000000..2bbd1c40
--- /dev/null
+++ b/tdm/kfrontend/sessions/fvwm95.desktop
@@ -0,0 +1,76 @@
+[Desktop Entry]
+Type=XSession
+Exec=fvwm95
+TryExec=fvwm95
+Name=FVWM95
+Name[hi]=एफ़वीडबल्यूएम95
+Name[te]=ఎఫ్ వి డబ్ల్యు ఎం 95
+Comment=A Windows 95 look-alike derivative of FVWM
+Comment[af]='n FVWM venster bestuurder wat soos Windows 95 lyk
+Comment[ar]=شبيه بـWin95 ومشتق من FVWM
+Comment[be]=Вытворная ад FVWM, падобная на Windows 95
+Comment[bn]=FVWM-ভিত্তিক Windows 95-এর মত দেখতে একটি উইণ্ডো ম্যানেজার
+Comment[bs]=Derivacija FVWM nalik na Windows 95
+Comment[ca]=Un semblant a Win95 derivat de FVWM
+Comment[cs]=Správce oken se vzhledem Windows 95 odvozený od FVWM
+Comment[csb]=Pòchòdzący z FVWM menedżer òknów ò wëzdrzatkù szlachùjącym za Windows 95
+Comment[cy]=Deilliant o FVWM sy'n edrych yn debyg i Windows95
+Comment[da]=En Windows 95-lignende vindueshåndtering afledt af FVWM
+Comment[de]=Ein Abkömmling von FVWM im Stil von Windows 95
+Comment[el]=Ένας παρόμοιος με τα Windows 95 διαχειριστής παραθύρων προερχόμενος από τον FVWM
+Comment[eo]=Fenestroadministrilo kiel tiu de Vindozo 95
+Comment[es]=Un derivado de FVWM de aspecto similar a Win95
+Comment[et]=FVWM derivaat, mis näeb välja nagu Windows 95
+Comment[eu]=Windows 95en itxura duen FVWMren ondorengo bat
+Comment[fa]=ویندوز ۹۵ شبیه مشتق FVWM
+Comment[fi]=Windows 95:lta näyttävä FVWM-johdannainen
+Comment[fr]=Un gestionnaire de fenêtres ressemblant à Windows 95 dérivant de FVWM
+Comment[fy]=In op Windows 95 lykjende fariant fan FVWM
+Comment[gl]=Un xestor de fiestras coma o de Windows 95 derivado de FVWM
+Comment[he]=נגזרת של FVWM הנראה כמו חלונות 95
+Comment[hi]=विंडोज़ 95 जैसा दिखने वाला एफ़वीडबल्यूएम का प्रतिरूप
+Comment[hr]=Derivat FVWM-a nalik na Windows 95
+Comment[hu]=Win95-szerű FVWM-változat
+Comment[is]=Útgáfa af FVWM sem líkist Windows 95
+Comment[it]=Una variante di FVWM che assomiglia a Windows 95
+Comment[ja]=Windows95 に似た外見の FVWM 派生ウィンドウマネージャ
+Comment[ka]=FVWM კლონი Windows 95-ის სტილში
+Comment[kk]=Windows 95 секілді FVWM-негіздеген терезе менеджері
+Comment[km]=ស្រដៀង Windows 95 ដែល​ក្លាយ​មក​ពី FVWM
+Comment[ko]=FVWM의 윈도 95를 닮은 변종
+Comment[lt]=Windows 95 išvaizdą primenanti FVWM atmaina
+Comment[lv]=Windows 95 līdzīgs FVWM atvasinājums
+Comment[mk]=Деривација на FVWM менаџерот со изглед на Windows 95
+Comment[mn]=FVWM -ээс уламжилсан Виндовс 95 шиг харагдалттай
+Comment[ms]=Terbitan FVWM yang menyerupai Windows 95
+Comment[mt]=Derivattiv ta' FVWM jixbaħ lil Windows 95
+Comment[nb]=En variant av FVWM som ser ut som Windows 95
+Comment[nds]=Süht ut as A Windows 95 un is vun FVWM afleddt
+Comment[ne]=विण्डोज ९५ FVWM को डेरिभेटिभ जस्तो छ
+Comment[nl]=Een op Windows 95 lijkende variant van FVWM
+Comment[nn]=Ein variant av FVWM som ser ut som Windows 95
+Comment[pa]=ਵਿੰਡੋ 95 ਵਰਗਾ FVWM ਦਾ ਇੱਕ ਰੂਪ
+Comment[pl]=Wywodzący się z FVWM menedżer okien o wyglądzie podobnym do Windows 95
+Comment[pt]=Uma derivação do FVWM parecida com o Windows 95
+Comment[pt_BR]=Um derivado do FVWM com a aparência do Windows 95
+Comment[ro]=O versiune de FVWM cu aspect de Windows 95
+Comment[ru]=Клон FVWM в стиле Windows 95
+Comment[rw]=Windows 95 isa nk'ikomoka kuri FVWM
+Comment[se]=FVWM-vuođđoduvvon lásegieđahalli mii lea Windows 95-lágan
+Comment[sk]=Správca okien podobný Windows 95 založený na FVWM
+Comment[sl]=Izpeljanka FVWM v izgledu Windows 95
+Comment[sr]=Дериват FVWM-а налик на Windows 95
+Comment[sr@Latn]=Derivat FVWM-a nalik na Windows 95
+Comment[sv]=Fönsterhanterare som liknar Windows 95 med ursprung i FVWM
+Comment[ta]=FVWM லிருந்து தோன்றிய விண்டோஸ் 95 ஐப் போன்ற
+Comment[tg]=Windows 95 look-монанди маҳсулии FVWM
+Comment[th]=FVWM ที่ถูกทำให้ดูเหมือนวินโดวส์ 95
+Comment[tr]=Windows 95'e benzeyen bir pencere yönetimi
+Comment[tt]=Windows 95 küreneşendä FVWM qabatlama
+Comment[uk]=Похідний від FVWM з виглядом Windows 95
+Comment[uz]=Win95'ga oʻxshagan FVWM'ning turi
+Comment[uz@cyrillic]=Win95'га ўхшаган FVWM'нинг тури
+Comment[vi]=Trình quản lý cửa sổ giống Windows 95, hậu duệ của FVWM
+Comment[wa]=On manaedjeu di purneas rishonnant a Windows 95 et k' est båzé so FVWM
+Comment[zh_CN]=一个与 Windows 95 外观类似的 FVWM 变种
+Comment[zh_TW]=一個由 FVWM 演化出來且外觀像 Win95 的視窗管理程式
diff --git a/tdm/kfrontend/sessions/gnome.desktop b/tdm/kfrontend/sessions/gnome.desktop
new file mode 100644
index 00000000..ed89391e
--- /dev/null
+++ b/tdm/kfrontend/sessions/gnome.desktop
@@ -0,0 +1,81 @@
+[Desktop Entry]
+Type=XSession
+Exec=gnome-session
+TryExec=gnome-session
+Name=GNOME
+Name[bn]=গনোম
+Name[eo]=Gnomikuo
+Name[hi]=ग्नोम
+Name[ko]=세임 그놈
+Name[mn]=ГНОМЕ
+Name[ne]=जिनोम
+Name[sv]=Gnome
+Name[ta]=க்னோம்
+Name[te]=గ్నొమ్
+Comment=The GNU Network Object Model Environment. A complete, free and easy-to-use desktop environment
+Comment[af]=Die GNU 'Network Object Model Environment'. 'n Volledige, gratis en maklik om te gebruik werkskerm omgewing.
+Comment[ar]=بيئة نموذج الكائن الشبكي من GNU، بيئة سطح مكتبي حرّة وسهلة الاستخدام
+Comment[be]=The GNU Network Object Model Environment. Поўнае, свабоднае і простае ў выкарыстанні працоўнае асяроддзе
+Comment[bn]=দি গনিউ নেটওয়ার্ক অবজেক্টমডেল এনভায়রনমেন্ট। একটি পূর্ণ, মুক্ত এবং সহজেই ব্যবহারযোগ্য ডেস্কটপ এনভায়রনমেন্ট
+Comment[bs]=GNU Network Object Model Environment. Kompletna, slobodna i jednostavna za upotrebu desktop okolina
+Comment[ca]=El GNU Network Object Model Environment. Un complet, lliure i fàcil d'usar entorn d'escriptori
+Comment[cs]=GNOME, GNU Network Object Model Environment. Kompletní, svobodné a uživatelsky přívětivé garfické prostředí.
+Comment[csb]=GNU Network Object Model Environment (GNOME). Fùlwôrtné, wòlné ë prosté w brëkòwaniô òkrãżé pùltu
+Comment[cy]=Yr Amgylchedd Model Gwrthrych Rhwydwaith GNU (GNU Network Object Model Environment). Amgylchedd penbwrdd cyflawn, rhydd, a hawdd ei ddefnyddio.
+Comment[da]=GNU Network Object Model Environment. Et fuldstænding, frit og nemt at bruge desktopmiljø
+Comment[de]=Das GNU Network Object Model Environment. Eine vollständige, freie und leicht bedienbare Arbeitsumgebung
+Comment[el]=Το GNU Network Object Model Environment. Ένα πλήρης, ελεύθερο και εύκολο στη χρήση περιβάλλον επιφάνειας εργασίας
+Comment[eo]=Plena labortabla ĉirkaŭaĵo
+Comment[es]=El GNU Network Object Model Environment, un entorno de escritorio completo, libre y fácil de usar
+Comment[et]=GNU Network Object Model Environment on täielik, vaba ja väga hõlpsasti kasutatav töölaua keskkond
+Comment[eu]=GNU Network Object Model Environment. mahaigain-ingurune oso, libre eta erabilterraza
+Comment[fa]=محیط مدل شئ شبکه گنو. محیط رومیزی کامل، آزاد و آسان برای استفاده.
+Comment[fi]=GNU Network Object Model Environment. Valmis, vapaa ja helppokäyttöinen työpöytäympäristö
+Comment[fr]=The GNU Network Object Model Environment. Un environnement de bureau complet, gratuit et facile à utiliser
+Comment[fy]=De GNU Network Object Model Environment, In komplete, frije en ienfâldige te brûken buroblêd omwrâld
+Comment[gl]=O GNU Network Object Model Environment. Un entorno de escritório completo, libre e de uso doado
+Comment[he]=The GNU Network Object Model Environment. סביבת עבודה מלאה, חופשית וקלה לשימוש
+Comment[hi]=जीएनयू नेटवर्क ऑब्जेक्ट मॉडल एनवायरनमेंट. एक संपूर्ण, उपयोग में आसान डेस्कटॉप वातावरण
+Comment[hr]=GNOME - GNU Network Object Model Environment - Cjelokupno, besplatno i jednostavno okruženje radne površine
+Comment[hu]=GNU Network Object Model Environment (GNOME), egy teljes, ingyenes, könnyen kezelhető grafikus környezet
+Comment[is]=GNU Network Object Model Environment er fullkomið og fjrálst skjáborðsumhverfi sem er auðvelt að nota
+Comment[it]=Il GNU Network Object Model Environment. Un ambiente desktop completo, libero e facile da usare
+Comment[ja]=GNU オブジェクトモデル環境, 完全にフリーで使いやすいデスクトップ環境
+Comment[ka]=GNU Network Object Model Environment - სრული, თავისუფალი და ადვილად გამოყენებადი სამუშაო გარემო
+Comment[kk]=GNU Network Object Model Environment. Толық, еркін таратылатын, ыңғайлы графикалық орта
+Comment[km]=GNU Network Object Model Environment ។ បរិស្ថាន​ផ្ទៃតុ​ពេញលេញ, ឥត​គិត​ថ្លៃ និង​ងាយស្រួល​ប្រើ
+Comment[ko]=GNU Network Object Model Environment(그놈). 완전한 자유 소프트웨어 데스크톱 환경입니다.
+Comment[lt]=GNU tinklo objektų modeliavimo aplinka. Savarankiška, laisva ir lengvai naudojama darbastalio aplinka
+Comment[lv]=GNU Network Object Model Environment. Pilnvērtīga bezmaksas viegli lietojama darba vide.
+Comment[mk]=GNU Network Object Model Environment. Работна околина која е комплетна, слободна и едноставна за користење
+Comment[mn]=GNU Network Object Model Environment. Бүрэн, үнэгүй хэрэглэхэд хялбар дэлгэцийн системийн орчин
+Comment[mt]=GNU Network Object Model Environment. Ambjent grafiku komplet, ħieles u faċli tużah.
+Comment[nb]=GNU Network Object Model Environment. Et skrivebordsmiljø som er komplett, fritt og lett å bruke.
+Comment[nds]=De "GNU Network Object Model Environment". En komplette Schriefdisch-Ümgeven, ümsunst un eenfach to bruken
+Comment[ne]=GNU सञ्जाल बस्तु नमूना वातावरण । पूर्ण, स्वतन्त्र र प्रयोग गर्न सजिलो डेस्कटप वातावरण
+Comment[nl]=De GNU Network Object Model Environment, een complete, vrije en eenvoudig te gebruiken desktop environment.
+Comment[nn]=GNU Network Object Model Environment. Eit skrivebordsmiljø som er komplett, fritt og lett å bruka.
+Comment[pa]=GNU Network Object Model Environment, ਇੱਕ ਸੰਪੂਰਨ, ਮੁਫਤ ਅਤ ਵਰਤਣ ਵਿੱਚ ਅਤਿ ਆਸਾਨ ਵੇਹੜਾ ਵਾਤਾਵਰਣ
+Comment[pl]=GNU Network Object Model Environment (GNOME). Pełne, wolne i łatwe w użyciu środowisko pulpitu
+Comment[pt]=O GNU Network Object Model Environment. Um ambiente de trabalho completo, livre e fácil de usar
+Comment[pt_BR]=Acrônimo para GNU Network Object Model Environment ou Ambiente de Modelo de Objetos de Rede GNU; um ambiente de trabalho completo, livre e fácil de usar
+Comment[ro]=GNU Network Object Model Environment. Un mediu grafic complet, gratuit și ușor de utilizat
+Comment[ru]=GNU Network Object Model Environment - полная, свободная и лёгкая в использовании графическая среда
+Comment[rw]=Ibikikije Moderi Igikoresho Urusobemiyoboro GNU. Ibikikije by'ibiro byuzuye, by'ubuntu kandi byoroshye-gukoresha.
+Comment[se]=GNU Netword Object Model Environment: Čállinbeavdebiras mii lea aibbas fridja ja álki geavahit.
+Comment[sk]=The GNU Network Object Model Environment. Úplné, voľne šíriteľné a ľahko použiteľné pracovné prostredie
+Comment[sl]=GNU Network Object Model Environment. Popolno, prosto in preposto namizno okolje
+Comment[sr]=„GNU Network Object Model Environment“(Gnome, Гном). Потпуно, бесплатно и лако за коришћење радно окружење
+Comment[sr@Latn]=„GNU Network Object Model Environment“(Gnome, Gnom). Potpuno, besplatno i lako za korišćenje radno okruženje
+Comment[sv]=GNU Network Object Model Environment. En fullständig, fri och lättanvänd skrivbordsmiljö
+Comment[ta]=GNU மாதிரி வலை பொருள் சூழல்.முழுமையான , இலவச சுலபமாக பயன்படுத்தக்கூடிய மேல்மேசை சூழல்
+Comment[th]=GNU Network Object Model Environment สภาพแวดล้อมสำหรับเดสก์ทอปที่ครบถ้วน, ฟรี และใช้งานง่าย
+Comment[tr]=GNU Network Object Model Environment (GNOME)
+Comment[tt]=The GNU Network Object Model Environment. Qullanu öçen ciñel, buşlay, tulıçaralı östäl möxite
+Comment[uk]=The GNU Network Object Model Environment. Повнофункціональне, вільне та зручне графічне середовище
+Comment[uz]=GNOME (GNU Network Object Model Environment) - mukammal, erkin va foydalanish uchun juda qulay ish stoli muhiti
+Comment[uz@cyrillic]=GNOME (GNU Network Object Model Environment) - мукаммал, эркин ва фойдаланиш учун жуда қулай иш столи муҳити
+Comment[vi]=Môi trường Mạng Mô hình Đối tượng của GNU. Một môi trường màn hình nền đầy đủ, tự do và dễ sử dụng
+Comment[wa]=L' evironmint di modele di cayets d' rantoele GNU (GNU Network Object Model Environment). On complet evironmint d' sicribanne, libe et åjhey a -z eployî.
+Comment[zh_CN]=GNU 网络对象模型环境。完整、自由、易用的桌面环境
+Comment[zh_TW]=GNU 網路物件模型環境。一個完整,免費且容易使用的桌面環境
diff --git a/tdm/kfrontend/sessions/golem.desktop b/tdm/kfrontend/sessions/golem.desktop
new file mode 100644
index 00000000..3ba7f2b4
--- /dev/null
+++ b/tdm/kfrontend/sessions/golem.desktop
@@ -0,0 +1,81 @@
+[Desktop Entry]
+Type=XSession
+Exec=golem
+TryExec=golem
+Name=Golem
+Name[bn]=গোলেম
+Name[eo]=Golemo
+Name[hi]=गोलेम
+Name[ne]=गोलेम
+Name[pa]=ਗੋਲੀਮ
+Name[te]=గొలెం
+Comment=A lightweight window manager
+Comment[af]='n Lig gewig venster bestuurder
+Comment[ar]=مدير نوافر خفيف العبء
+Comment[be]=Лёгкі кіраўнік вокнаў
+Comment[bn]=একটি হাল্কা উইণ্ডো ম্যানেজার
+Comment[bs]=Lagani window manager
+Comment[ca]=Un lleuger gestor de finestres KDE
+Comment[cs]=Malý správce oken
+Comment[csb]=Menedżer òknół ò môłëch żądaniach
+Comment[cy]=Trefnydd ffenestri ysgafn
+Comment[da]=En letvægtsvindueshåndtering
+Comment[de]=Eine schlanker Fenstermanager
+Comment[el]=Ένας ελαφρύς διαχειριστής παραθύρων
+Comment[eo]=Malpeza fenestroadministrilo
+Comment[es]=Un gestor de ventanas ligero
+Comment[et]=Imeväike aknahaldur
+Comment[eu]=Leiho kudeatzaile arina
+Comment[fa]=یک مدیر پنجرۀ سبک
+Comment[fi]=Kevyt ikkunaohjelma
+Comment[fr]=Un gestionnaire de fenêtres très léger
+Comment[fy]=In lichtgewicht finstersmanager
+Comment[gl]=Un xestor de fiestras lixeiro
+Comment[he]=מנהל החלונות קל משקל
+Comment[hi]=एक हल्का विंडो प्रबंधक
+Comment[hr]=Lagani upravitelj prozora
+Comment[hu]=Egy nagyon egyszerű ablakkezelő
+Comment[is]=Léttur gluggastjóri
+Comment[it]=Un window manager leggero
+Comment[ja]=軽量なウィンドウマネージャ
+Comment[ka]=მსუბუქი ფანჯრი მენეჯერი
+Comment[kk]=Жеңіл терезе менеджері
+Comment[km]=កម្មវិធី​គ្រប់គ្រង​បង្អួច​សមត្ថភាព​ខ្សោយ
+Comment[ko]=가벼운 창 관리자
+Comment[lt]=Nedaug resursų eikvojanti langų tvarkyklė
+Comment[lv]=Viegls logu menedžeris
+Comment[mk]=Лесен менаџер на прозорци
+Comment[mn]=Хөнгөн цонхны удирдагч
+Comment[ms]=Pengurus tetingkap ringan
+Comment[mt]=Window manager ħafif
+Comment[nb]=En lettvekts vindusbehandler
+Comment[nds]=En ranke Finsterpleger
+Comment[ne]=हल्का वजन सञ्झ्याल प्रबन्धक
+Comment[nl]=Een lichtgewicht windowmanager
+Comment[nn]=Ein lett vindaugssjef
+Comment[pa]=ਇੱਕ ਹਲਕਾ ਝਰੋਖਾ ਮੈਨੇਜਰ
+Comment[pl]=Menedżer okien o małych wymaganiach
+Comment[pt]=Um gestor de janelas leve
+Comment[pt_BR]=Um gerenciador de janelas leve
+Comment[ro]=Un manager de ferestre foarte mic
+Comment[ru]=Лёгкий оконный менеджер
+Comment[rw]=Mugenga dirishya yoroshye
+Comment[se]=Geahpes lásegieđahalli
+Comment[sk]=Nenáročný správca okien
+Comment[sl]=Lahek okenski upravitelj
+Comment[sr]=Лагани менаџер прозора
+Comment[sr@Latn]=Lagani menadžer prozora
+Comment[sv]=Lättviktig fönsterhanterare
+Comment[ta]=குறைவான எடை உடைய சாளர மேலாளர்
+Comment[te]=తెలికైన విండొ అభికర్త
+Comment[tg]=Мудири тирезаи сабук
+Comment[th]=ระบบจัดการหน้าต่างขนาดเบา
+Comment[tr]=Hızlı çalışan bir pencere yöneticisi
+Comment[tt]=Ciñel täräzä-idäräçe
+Comment[uk]=Швидкий менеджер вікон
+Comment[uz]=Oddiy oyna boshqaruvchi
+Comment[uz@cyrillic]=Оддий ойна бошқарувчи
+Comment[vi]=Trình quản lý cửa sổ nhẹ ký
+Comment[wa]=On ledjir manaedjeu di purneas
+Comment[zh_CN]=轻量级窗口管理器
+Comment[zh_TW]=一個輕量化的視窗管理程式
diff --git a/tdm/kfrontend/sessions/icewm.desktop b/tdm/kfrontend/sessions/icewm.desktop
new file mode 100644
index 00000000..8b70361f
--- /dev/null
+++ b/tdm/kfrontend/sessions/icewm.desktop
@@ -0,0 +1,81 @@
+[Desktop Entry]
+Type=XSession
+Exec=icewm-session
+TryExec=icewm-session
+Name=IceWM
+Name[eo]=GlaciFA
+Name[hi]=आइस-डबल्यूएम
+Name[lo]=ຕົວຈັດການຫນ້າຕ່າງ IceWM
+Name[sv]=Ice WM
+Name[te]=ఐస్ డబ్ల్యు ఎం
+Name[th]=ตัวจัดการหน้าต่าง IceWM
+Comment=A Windows 95-OS/2-Motif-like window manager
+Comment[af]='n Windows 95-OS/2-Motif tipe venster bestuurder
+Comment[ar]=مدير نوافذ مشابه لـ Win95-OS/2-Motif
+Comment[be]=Кіраўнік вокнаў, падобны на Windows 95-OS/2-Motif
+Comment[bn]=Windows 95-OS/2-Motif-এর অনুরূপ একটি উইণ্ডো ম্যানেজার
+Comment[bs]=Window manager nalik na Windows 95-OS/2-Motif
+Comment[ca]=Un gestor de finestres com els de Windows 95-OS/2-Motif
+Comment[cs]=Správce oken podobný Windows 95-OS/2-Motif
+Comment[csb]=Menedżer òknół szlachùjący za Windows 95-OS/2-Motif
+Comment[cy]=Trefnydd ffenestri sy'n debyg i Windows95-OS/2-Motif
+Comment[da]=En Windows 95-OS/2-Motif-lignende vindueshåndtering
+Comment[de]=Fenstermanager im Stil von Windows 95, OS/2 und Motif
+Comment[el]=Ένας διαχειριστής παραθύρων παρόμοιος με τα Windows 95-OS/2-Motif
+Comment[eo]=Fenestroadministrilo kiel Vindozo 95, OS/2 kaj Motifo
+Comment[es]=Un gestor de ventanas similar a Win95-OS/2-Motif
+Comment[et]=Aknahaldur, mis näeb välja nagu Windows 95-OS/2-Motif
+Comment[eu]=Windows 95 OS/2 Motif-en itxura duen leiho kudeatzailea
+Comment[fa]=یک مدیر پنجره شبیه Windows 95-OS/2-Motif
+Comment[fi]=Windows 95:n ja OS/2-Motifin tyylinen ikkunaohjelma
+Comment[fr]=Un gestionnaire de fenêtres ressemblant à Windows 95-OS/2-Motif
+Comment[fy]=In Win95-OS/2-Motif-likens finstersmanager
+Comment[gl]=Un xestor de fiestras coma o de Windows 95-OS/2-Motif
+Comment[he]=מנהל חלונות מבוסס Motif הדומה במראהו לחלונות 95/OS-2
+Comment[hi]=विंडोज़ 95-ओएस/2-मोटिफ जैसा विंडो प्रबंधक
+Comment[hr]=Upravitelj prozora nalik na Windows 95/OS/2/Motif
+Comment[hu]=Win95-OS/2-Motif-szerű ablakkezelő
+Comment[is]=Gluggastjóri sem líkist 95-OS/2-Motif
+Comment[it]=Un window manager in stile Windows 95-OS/2-Motif
+Comment[ja]=Windows95, OS/2, Motif に似たウィンドウマネージャ
+Comment[ka]=ფანჯრების მენეჯერი Windows95-OS/2-Motif სტილში
+Comment[kk]=Windows 95-OS/2-Motif-секілді терезе менеджері
+Comment[km]=កម្មវិធី​គ្រប់គ្រង​បង្អួច​ដែល​ដូច Windows 95-OS/2-Motif
+Comment[ko]=윈도 95, OS/2, Motif를 닮은 창 관리자
+Comment[lt]=A Windows 95-OS/2-Motif-primenanti langų tvarkyklė
+Comment[lv]=Windows 95 - OS/2 - Motif līdzīgs logu menedžeris
+Comment[mk]=Менаџер на прозорци со изглед на Windows 95, OS/2 и Motif
+Comment[mn]=Виндовс 95-OS/2-Motif-шиг цонхны удирдагч
+Comment[ms]=Pengurus tetingkap seperti Motif Windows 95-OS/2
+Comment[mt]=Window manager jixbaħ lill-Windows 95-OS/2-Motif
+Comment[nb]=En vindusbehandler som likner Windows 95-OS/2-Motif
+Comment[nds]=Finsterpleger, de utsüht as Windows 95-OS/2-Motif
+Comment[ne]=विण्डोज ९५-OS/2-मोटिफ जस्तो सञ्झ्याल प्रबन्धक
+Comment[nl]=Een Win95-OS/2-Motif-achtige windowmanager
+Comment[nn]=Ein vindaugssjef som liknar Windows 95-OS/2-Motif
+Comment[pa]=ਇੱਕ ਵਿੰਡੋ 95-OS/2-Motif-ਵਰਗਾ ਝਰੋਖਾ ਮੈਨੇਜਰ
+Comment[pl]=Menedżer okien podobny do Windows 95-OS/2-Motif
+Comment[pt]=Um gestor de janelas parecido com o Windows 95, o OS/2 e o Motif
+Comment[pt_BR]=Um gerenciador de janelas parecido com Windows 95-OS/2-Motif
+Comment[ro]=Un manager de ferestre cu aspect de Windows 95, OS/2 sau Motif
+Comment[ru]=Оконный менеджер в стиле Windows95-OS/2-Motif
+Comment[rw]=Windows 95-OS/2-umutako-nka mugenga dirishya
+Comment[se]=Windows 95-OS/2-Motif-lágan lásegieđahalli
+Comment[sk]=Správca okien podobný Windows 95-OS/2-Motif
+Comment[sl]=Okenski upravitelj, podoben Windows 95, OS/2 in Motifu
+Comment[sr]=Менаџер прозора налик на Windows 95/OS/2/Motif
+Comment[sr@Latn]=Menadžer prozora nalik na Windows 95/OS/2/Motif
+Comment[sv]=Fönsterhanterare som liknar Windows 95-OS/2-Motif
+Comment[ta]=சாளரங்கள் 95-OS/2-மாடிஃப்-லைக் சாளர மேலாளர்
+Comment[te]=విండొస్ 95-ఒఎస్/2 -మొటిఫ్ లాంటి విండొ అభికర్త
+Comment[tg]=Windows 95-OS/2-Motif-монанди мудири тиреза
+Comment[th]=ระบบจัดการหน้าต่างของที่ดูคล้าย วินโดวส์ 95-โอเอสทู-โมทิฟ
+Comment[tr]=Windows 95-OS/2-Motif benzeri bir pencere yöneticisi
+Comment[tt]=Windows 95-OS/2-Motif küreneşendä täräzä-idäräçe
+Comment[uk]=Менеджер вікон на кшталт Windows 95-OS/2-Motif
+Comment[uz]=Win95-OS/2-Motif'ga oʻxshash oyna boshqaruvchi
+Comment[uz@cyrillic]=Win95-OS/2-Motif'га ўхшаш ойна бошқарувчи
+Comment[vi]=Trình quản lý cửa sổ với mô típ kiểu Windows 95
+Comment[wa]=On manaedjeu di purneas rishonnant Windows95-OS/2-Motif
+Comment[zh_CN]=类似 Windows-OS/2-Motif 的窗口管理器
+Comment[zh_TW]=一個像 Win95-OS/2-Motif 的視窗管理程式
diff --git a/tdm/kfrontend/sessions/ion.desktop b/tdm/kfrontend/sessions/ion.desktop
new file mode 100644
index 00000000..c4ae9ca0
--- /dev/null
+++ b/tdm/kfrontend/sessions/ion.desktop
@@ -0,0 +1,77 @@
+[Desktop Entry]
+Type=XSession
+Exec=ion
+TryExec=ion
+Name=Ion
+Name[bn]=আয়ন (Ion)
+Name[eo]=Iono
+Name[hi]=आयन
+Name[ja]=ION
+Name[ko]=카메룬
+Name[pa]=ਲੋਨ
+Name[te]=ఐయాన్
+Name[th]=ไอออน
+Comment=A keyboard-friendly window manager with tiled windows, based on PWM
+Comment[af]='n Sleutelbord vriendelike venster bestuurder, met geteëlde vensters. Dis op PWM gebaseer.
+Comment[ar]=مدير نوافذ سهل استخدام لوحة المفاتيح ذي نوافذ معنونة، مبني على PWM
+Comment[be]=Кіраўнік вокнаў для працы з клавіятурай, заснаваны на PWM
+Comment[bn]=PWM ভিত্তিক উইণ্ডো ম্যানেজার, যা কীবোর্ড দিয়ে নিয়ন্ত্রণ করা সহজ
+Comment[bs]=Window manager za tastaturu sa popločanim prozorima, baziran na PWM
+Comment[ca]=Un gestor de finestres amigable amb el teclat i amb finestres alicatades, basat en PWM
+Comment[csb]=Menedżer òknów z dobrą òbsłëgą klawiaturë ë kachelkòwaniém òknów, ùsôdzony na spòdlém PWM
+Comment[cy]=Trefnydd ffenestri sy'n hawdd ei ddefnyddio o'r alweddell, efo ffenestri wedi'u teilio, wedi'i seilio ar PVM
+Comment[da]=En tastaturvenlig vindueshåndtering med fliselagte vinduer, baseret på PWM
+Comment[de]=Tastaturfreundlicher Fenstermanager mit gekachelten Fenstern, basiert auf PWM
+Comment[el]=Ένας φιλικός με το πληκτρολόγιο διαχειριστής παραθύρων με υποστήριξη παραθύρων σε παράθεση, βασισμένος στον PWM
+Comment[eo]=Fenestroadministrilo por la uzo klaviara
+Comment[es]=Un gestor de ventanas utilizable desde el teclado con mosaico de ventanas, basado en PWM
+Comment[et]=Klaviatuurisõprade aknahaldur paanitud akendega, aluseks PWM
+Comment[eu]=PWMn oinarritutako leiho-mosaikoa duen leiho kudeatzailea, teklatutik erabil daitekeena
+Comment[fa]=یک مدیر پنجرۀ صفحه کلید پسند با پنجره‌های کاشی‌شده، براساس PWM
+Comment[fi]=Näppäimistöystävällinen ikkunaohjelma
+Comment[fr]=Un gestionnaire de fenêtres utilisable au clavier avec des fenêtres en mosaïque, fondé sur PWM
+Comment[fy]=In toetseboerdfreonlike finstersmanager mei tegele finsters. basearre op PWM
+Comment[gl]=Un xestor de fiestras de manexo co teclado e fiestras en mosaico baseado en PWM
+Comment[he]=מנהל חלונות ידידותי למקלדת עם חלונות פרושים המבוסס על PWM
+Comment[hi]=पीडबल्यूएम आधारित चटाई विंडो युक्त विंडो प्रबंधक जो कुंजीपट फ्रेडली है
+Comment[hr]=Comment=Upravitelj prozora s popločenim prozorima, namijenjen tipkovnici i zasnovan na PWM-u
+Comment[hu]=Egy billentyűzetről könnyen kezelhető ablakkezelő, mozaikszerű ablakelrendezéssel, a PWM alapján
+Comment[is]=Gluggastjóri sem er gott að vinna í með lyklaborðinu einu, byggður á PWM
+Comment[it]=Un window manager "amico della tastiera" con finestre affiancate, basato su PWM
+Comment[ja]=PWM ベースのキーボード操作に適したタイル表示式のウィンドウマネージャ
+Comment[ka]=კლავიატურით მართვადი ფანჯრების მენეჯერი, PWM-ის ბაზაზე
+Comment[kk]=PWM-негіздеген, пернетақтадан басқарылатын, терезелері кезектескен, терезе менеджері
+Comment[km]=កម្មវិធី​គ្រប់គ្រង​បង្អួច​ដែល​ងាយ​ប្រើ​ជាមួយ​ក្ដារចុច ហើយ​អាច​រៀប​បង្អួច​ជា​ក្បឿង និង​ផ្អែក​លើ PWM
+Comment[lt]=Patogi dirbti su klaviatūra langų tvarkyklė su išklotais langais, paremta PWM
+Comment[lv]=Tastatūrai draudzīgs logu menedžeris ar tiled logiem, bāzēts uz PWM
+Comment[mk]=Менаџер на прозорци со поплочени прозорци базиран на PWM погоден за работа со тастатура
+Comment[mn]=PWM дээр суурилсан гараар ажиллахад тохиромжтой цонх удирдагч
+Comment[ms]=Pengurus tetingkap mesra papan kekunci dengan tetingkap berjubin, berdasarkan PWM
+Comment[mt]=Window manager ibbażat fuq PWM, b'sapport għal tastieri u windows imqassma fuiq madum
+Comment[nb]=En tastaturvennlig vindusbehandler med flislagte vinduer, basert på PWM
+Comment[nds]=En tastatuurfründliche Finsterpleger mit kachelte Finstern, opbuut op PWM
+Comment[ne]=शीर्षक सञ्झ्यालसँग सोझो सञ्झ्याल प्रबन्धक कुञ्जीपाटी
+Comment[nl]=Een toetsenbordvriendelijke windowmanager met getegelde vensters. Gebaseerd op PWM
+Comment[nn]=Ein tastaturvennleg vindaugssjef med flislagde vindauge, basert på PWM
+Comment[pa]=ਇੱਕ ਕੀ-ਬੋਰਡ ਸਹਾਇਕ ਝਰੋਖਾ ਮੈਨੇਜਰ, ਜੋ ਕਿ PWM ਤੇ ਆਧਾਰਿਤ ਹੈ
+Comment[pl]=Menedżer okien z dobrą obsługą klawiatury i kafelkowaniem okiem, stworzony na podstawie PWM
+Comment[pt]=Um gestor de janelas amigável para o teclado, com janelas lado-a-lado, baseado no PWM
+Comment[pt_BR]=Um gerenciador de janelas amigável com o teclado, com janelas ladrilhadas, baseado no PWM
+Comment[ro]=Un manager de ferestre ușor de utilizat din tastatură, cu ferestre ce pot fi așezate în mozaic, bazat pe PWM
+Comment[ru]=Управляемый с клавиатуры оконный менежер, основанный на PWM
+Comment[rw]=mugenga dirishya ya mwandikisho-yoroshyeikoresha ifite amadirishya agerekeranye, ishingiye kuri PWM
+Comment[se]=Boallobeavdeustitlaš lašegieđahalli, mas leat bálddalas láset, ráhkaduvvon PWM vuođul
+Comment[sk]=Správca okien s podporou kláves, usporiadania okien do dlaždíc, založený na PWM
+Comment[sl]=Tipkovnici prijazen okenski upravitelj z razdeljenimi okni, na osnovi PWM
+Comment[sr]=Пријатељски према тастатури менаџер прозора са наслаганим прозорима, заснован на PWM-у
+Comment[sr@Latn]=Prijateljski prema tastaturi menadžer prozora sa naslaganim prozorima, zasnovan na PWM-u
+Comment[sv]=Tangentbordsvänlig fönsterhanterare med fönster sida vid sida, baserad på PWM
+Comment[ta]=PWM அடிப்படையிலான விசைப்பலகையால் கையாளமுடிந்த சாளர மேளாளர்
+Comment[th]=ระบบจัดการหน้าต่างที่เป็นมิตรกับการใช้แป้นพิมพ์ พร้อมกับหน้าต่างที่ถูกปูเรียง สร้างจาก PWM
+Comment[tr]=PWM tabanlı, klavye dostu uzatılmış pencereleriyle bir pencere yönetici
+Comment[tt]=Täräzä bülü belän töylek-söygän täräzä-idäräçe, PWM asılında
+Comment[uk]=Менеджер вікон налаштований для легкого використання з клавіатурою, засновано на PWM
+Comment[vi]=Trình quản lý cửa sổ thiết kết thân thiện với việc dùng bàn phím, có các cửa sổ xếp ngói, dựa trên PWM
+Comment[wa]=On manaedjeu di purneas k' inme li taprece avou des purneas å pus grand, båzé so PWM
+Comment[zh_CN]=一个基于 PWM 的窗口管理器,适合键盘操作,可平铺窗口
+Comment[zh_TW]=一個基於 PWM 且方便鍵盤使用和支援棋盤化視窗的視窗管理程式
diff --git a/tdm/kfrontend/sessions/larswm.desktop b/tdm/kfrontend/sessions/larswm.desktop
new file mode 100644
index 00000000..072b382c
--- /dev/null
+++ b/tdm/kfrontend/sessions/larswm.desktop
@@ -0,0 +1,72 @@
+[Desktop Entry]
+Type=XSession
+Exec=larswm
+TryExec=larswm
+Name=LarsWM
+Name[eo]=Lazero
+Name[hi]=लार्स-डबल्यूएम
+Name[ko]=라이코스
+Name[sv]=Lars WM
+Name[te]=లార్స్ డబ్ల్యు ఎం
+Comment=The Lars Window Manager, based on 9WM, supports tiled windows
+Comment[af]=Die Lars venster bestuurder, wat op 9WM gebaseer is. Dit ondersteun geteëlde vensters.
+Comment[ar]=مدير نوافذ لارس، مبني على 9WM، يدعم النوافذ المعنونة
+Comment[be]=Кіраўнік вокнаў Lars Window Manager, заснаваны на 9WM
+Comment[bn]=লার্স উইণ্ডো ম্যানেজার, 9WM-এর ওপর ভিত্তি করে তৈরি
+Comment[bs]=Lars Window Manager, baziran 9WM, podržava popločane prozore
+Comment[ca]=El gestor de finestres Lars, basat en 9WM, permet finestres alicatades
+Comment[csb]=Menedżer òknów Larsa, ùsôdzony na spòdlém 9WM, wspiérô kachelkòwanié òknów
+Comment[cy]=Y Trefnydd Ffenestri Lars, wedi'i seilio ar 9WM, sy'n cynnal ffenestri wedi'u teilio
+Comment[da]=Lars vindueshåndteringen, baseret på 9WM, understøtter fliselagte vinduer
+Comment[de]=Lars-Fenstermanager, basiert auf 9WM und unterstützt gekachelte Fenstern
+Comment[el]=Ο διαχειριστής παραθύρων Lars, βασισμένος στον 9WM, υποστηρίζει παράθυρα σε παράθεση
+Comment[eo]=La Laza Fenestroadministrilo, devenigita de 9FA
+Comment[es]=El Lars Window Manager, basado en 9WM, soporta mosaico de ventanas
+Comment[et]=Larsi aknahaldur, mille aluseks on 9WM, toetab paanitud aknaid
+Comment[eu]=Lars leiho kudeatzailea, 9WM-n oinarritua, leiho-mosaikorako euskarria duena
+Comment[fa]=مدیر پنجرۀ Lars، بر اساس 9WM، پنجره‌های کاشی‌شده را پشتیبانی می‌کند.
+Comment[fi]=Lars-ikkunaohjelma. Pohjautuu 9WM:ään ja tukee järjestettyjä ikkunoita
+Comment[fr]=The Lars Window Manager, fondé sur 9WM, avec une gestion des fenêtres en mosaïque
+Comment[fy]=De Lars Window Manager, basearre op 9WM. Biedt stipe foar tegele finsters
+Comment[gl]=O Xestor de Fiestras Lars, baseado en 9WM, atura fiestras en mosaico
+Comment[he]=The Lars Window Manager, מבוסס על 9WM, תומך בחלונות פרושים
+Comment[hi]=9डबल्यूएम आधारित लार्स विंडो प्रबंधक, चटाई विडो समर्थित करता है
+Comment[hr]=Lars upravitelj prozora, zasnovan na 9WMu, podržava popločene prozore
+Comment[hu]=Lars ablakkezelője, a 9WM alapján, mozaikszerű ablakelrendezési lehetőséggel
+Comment[is]=Lars gluggastjórinn, byggður á 9WM og styður flísaða glugga
+Comment[it]=Il Window Manager di Lars, basato su 9WM, supporta le finestre affiancate
+Comment[ja]=Lars ウィンドウマネージャ, 9WMベース, タイル表示をサポートするウィンドウマネージャ
+Comment[kk]=9WM-негіздеген терезе менеджері
+Comment[km]=Lars Window Manager ផ្អែក​លើ 9WM គាំទ្រ​បង្អួច​ជា​ក្បឿង
+Comment[lt]=Lars langų tvarkyklė, paremta 9WM, turi galimybę iškloti langus
+Comment[mk]=Lars Window Manager, менаџер базиран на 9WM, поддржува поплочени прозорци
+Comment[mn]=The Lars Window Manager, 9WM дээр суурилсан, олон цонхтой
+Comment[ms]=Pengurus Tetingkap Lars, berdasarkan 9WM, menyokong tetingkap berjubin
+Comment[mt]=Lars Window Manager - ibbażat fuq 9WM u jiflaħ windows imqassma f'madum
+Comment[nb]=Lars vindusbehandler, basert på 9WM, støtter flislagte vinduer
+Comment[nds]=De Lars-Finsterpleger, opbuut op 9WM, ünnerstütt kachelte Finstern
+Comment[ne]=9WM मा आधारित लार्स सञ्झ्याल प्रबन्धक, टायल गरिएका सञ्झ्यालहरू समर्थन गर्छ
+Comment[nl]=De Lars Window Manager, gebaseerd op 9WM. Biedt ondersteuning voor getegelde vensters
+Comment[nn]=Vindaugssjefen Lars, basert på 9WM, støttar flislagde vindauge
+Comment[pa]=ਲਾਰਸ ਫਾਇਲ਼ ਮੈਨੇਜਰ 9WM ਤੇ ਆਧਾਰਿਤ, ਝਰੋਖਿਆਂ ਦੇ ਸਮੇਟਣ ਲਈ ਸਹਾਈ
+Comment[pl]=Menedżer okien Larsa, stworzony na podstawie 9WM, obsługuje kafelkowanie okien
+Comment[pt]=O Lars Window Manager, baseado no 9WM, e que suporta janelas lado-a-lado
+Comment[pt_BR]=O gerenciador de janelas Lars, baseado no 9WM, com suporte a janelas ladrilhadas
+Comment[ro]=Managerul de ferestre al lui Lars, bazat pe 9WM. Suportă ferestre aranjate în mozaic
+Comment[ru]=Оконный менеджер на основе 9wm
+Comment[rw]=Mugenga Dirishya Lars, ishingiye kuri 9WM, yemera amadirishya agerekeranye
+Comment[se]=Lásegieđahalli Lars, ráhkaduvvon 9WM vuođul, doarju bálddalas lásiid.
+Comment[sk]=The Lars Window Manager založený na 9WM s podporou okien usporiadaných do dlaždíc
+Comment[sl]=Larsov okenski upravitelj, na osnovi 9WM, podpira porazdeljena okna
+Comment[sr]=„Lars Window Manager“, заснован на 9WM-у, подржава наслагане прозоре
+Comment[sr@Latn]=„Lars Window Manager“, zasnovan na 9WM-u, podržava naslagane prozore
+Comment[sv]=Lars fönsterhanterare, baserad på 9WM, med stöd för fönster sida vid sida
+Comment[ta]=9WM அடிபடையிலான லார்ஸ் சாளர மேலாளர் சீரமைக்கப்பட்ட சாளரங்களை ஆதரிக்கிறது
+Comment[th]=ระบบจัดการหน้าต่าง Lars สร้างจาก 9WM สนับสนุนการปูเรียงหน้าต่าง
+Comment[tr]=Lars Pencere Yöneticisi
+Comment[tt]=Lars Window Manager, 9WM asılında, bülengän täräzä tota
+Comment[uk]=The Lars Window Manager, засновано на 9WM, підтримує розташування вікон плиткою
+Comment[vi]= Trình Quản lý Cửa sổ Lars, dựa vào 9WM, hỗ trợ cửa sổ xếp ngói
+Comment[wa]=Li manaedjeu d' purnea d' Lasrs (Lars Window Manager), båzé so 9WM, sopoite les purneas å pus grand
+Comment[zh_CN]=Lars 窗口管理器,基于 9WM,支持平铺窗口
+Comment[zh_TW]=The Lars 視窗管理程式,基於 9WM,支援棋盤化視窗
diff --git a/tdm/kfrontend/sessions/lwm.desktop b/tdm/kfrontend/sessions/lwm.desktop
new file mode 100644
index 00000000..2f3e0ff0
--- /dev/null
+++ b/tdm/kfrontend/sessions/lwm.desktop
@@ -0,0 +1,76 @@
+[Desktop Entry]
+Type=XSession
+Exec=lwm
+TryExec=lwm
+Name=LWM
+Name[eo]=MFA
+Name[hi]=एलडबल्यूएम
+Name[te]=ఎల్ డబ్ల్యు ఎం
+Name[th]=ตัวจัดการหน้าต่าง LWM
+Comment=The Lightweight Window Manager. A non-configurable, bare window manager
+Comment[af]=Die lig gewig venster bestuurder.
+Comment[ar]=مدير النوافذ خفيف العبء، مدير نوافذ مجرّد غير قابل للإعداد
+Comment[be]=The Lightweight Window Manager. Пусты кіраўнік вокнаў без падтрымкі настаўленняў
+Comment[bn]=দি লাইটওয়েট উইণ্ডো ম্যানেজার
+Comment[bs]=Lightweight Window Manager. Ne-podesivi, potpuno osnovni window manager
+Comment[ca]=El gestor de finestres Lightweight. Un gestor de finestres no configurable i pelat
+Comment[cs]=The Lightweight Window Manager. Prostý a nekonfigurovatelný správce oken
+Comment[csb]=Lightweight Window Manager (Letczi menedżer òknół). Bro prosti menedżer òknów bez mòżnoté kònfigùracëji
+Comment[cy]=Y Trefnydd Ffenestri Ysgafn. Trefnydd ffenestri noeth, na ellir ffurfweddu
+Comment[da]=Lightweight Window Manager, en ikke-indstillelig, minimal vindueshåndtering
+Comment[de]=Lightweight Window Manager -- reiner Fenstermanager ohne Einstellmöglichkeiten
+Comment[el]=Ο ελαφρύς διαχειριστής παραθύρων. Ένας μη παραμετροποιήσιμος, πολύ απλός διαχειριστής παραθύρων
+Comment[eo]=Malpeza Fenestroadministrilo
+Comment[es]=El Lightweight Window Manager, un sencillísimo y no configurable gestor de ventanas
+Comment[et]=Imeväike aknahaldur on seadistamatu, sõna otseses mõttes ainult akende haldur
+Comment[eu]=Libhtweight leiho kudeatzailea. Konfiguraziorik onartzen ez duen leiho-kudeatzaile zeharo sinplea
+Comment[fa]=مدیر پنجرۀ سبک، مدیر پنجرۀ غیرقابل پیکربندی و ساده
+Comment[fi]=Kevyt ikkunaohjelma. Paljas, ei muokattavissa oleva ikkunaohjelma
+Comment[fr]=The Lightweight Window Manager. Un gestionnaire de fenêtres non configurable et nu
+Comment[fy]=De Lightweight Window Manager, in net-ynstelbere, keale finstersmanager
+Comment[gl]=O Xestor de Fiestras Lixeiro.
+Comment[he]=The Lightweight Window Manager. מנהל חלונות מצומצם בלי אפשרויות להגדרה.
+Comment[hi]=हल्का विंडो प्रबंधक. खाली विंडो प्रबंधक जो कॉन्फ़िगर नहीं हो सकता
+Comment[hr]=LWM - Lightweight Window Manager (Lagani upravitelj prozora) - Temeljni upravitelj prozora bez mogućnosti konfiguriranja
+Comment[hu]=Lightweight Window Manager, egy könnyen konfigurálható, alapszintű ablakkezelő
+Comment[is]=Hinn létti gluggastjóri. Ekki stillanlegur og hrár
+Comment[it]=Il Window Manager Leggero. Un window manager essenziale e non configurabile
+Comment[ja]=設定項目のない、単純なウィンドウマネージャ
+Comment[ka]=მსუბუქი არაკონფიგურირებადი ფანჯრების მენეჯერი
+Comment[kk]=Lightweight Window Manager. Баптауы жоқ, жай терезе менеджері
+Comment[km]=កម្មវិធី​គ្រប់គ្រង​បង្អួច​សមត្ថភាព​ខ្សោយ ។ កម្មវិធី​គ្រប់គ្រង​បង្អួច​ដែល​គ្មាន​អ្វី​បិទបាំង ហើយ​មិន​អាច​កំណត់​រចនាសម្ព័ន្ធ​បាន
+Comment[lt]=„Lengva“ langų tvarkyklė. Nekonfigūruojama, „plika“ langų tvarkyklė
+Comment[lv]=Vieglais logu menedžeris. Nekonfigurējams, vienkāršs logu menedžeris
+Comment[mk]=Lightweight Window Manager. Неконфигурабилен, скоро празен менаџер на прозорци
+Comment[mn]=The Lightweight Window Manager. Тохируулгах боломжгүй,цонхны удирдлага
+Comment[ms]=Pengurus tetingkap Ringan. Tidak boleh konfigur, pengurus tetingkap terdedah
+Comment[mt]=Lightweight Window Manager. Window Manager sempliċi u mhux konfigurabbli
+Comment[nb]=Lettvekts vindusbehandler- Lightweight Window Manager. En enkel vindusbehandler uten innstillinger.
+Comment[nds]=De "Lightweight"-Finsterpleger. En reen Finsterpleger ahn Instellen
+Comment[ne]=हल्का वजन सञ्झ्याल प्रबन्धक । कन्फिगर गर्न नसकिने, बेयर सञ्झ्याल प्रबन्धक
+Comment[nl]=De Lightweight Window Manager, een niet-instelbare, kale windowmanager
+Comment[nn]=Lightweight Window Manager. Ein enkel vindaugssjef utan innstillingar.
+Comment[pa]=ਇੱਕ ਹਲਕਾ, ਨਾ-ਸੰਰਚਿਤਯੋਗ ਪੱਟੀ ਝਰੋਖਾ ਮੈਨੇਜਰ
+Comment[pl]=Lightweight Window Manager (Lekki menedżer okien). Surowy menedżer okien bez możliwości konfiguracji
+Comment[pt]=O Lightweight Window Manager. Um gestor de janelas não-configurável e básico
+Comment[pt_BR]=Um gerenciador de janelas leve, sendo básico e não muito configurável
+Comment[ro]=Lightweight Window Manager. Un manager de ferestre neconfigurabil și minimal
+Comment[ru]=Облегчённый, не настраиваемый простой оконный менеджер
+Comment[rw]=Mugenga Dirishya Yoroshye. Mugenga dirishya idafite ikintu, itabonezwa.
+Comment[se]=Lightweight Window Manager. Oktageardánis lásegieđahalli mii ii lea heivehahtti.
+Comment[sk]=The Lightweight Window Manager. Nenastaviteľný, jednoduchý správca okien
+Comment[sl]=Lahek okenski upravitelj. Ni nastavljiv, osnovni okenski upravitelj
+Comment[sr]=„Lightweight Window Manager“. Неподесив, голи менаџер прозора
+Comment[sr@Latn]=„Lightweight Window Manager“. Nepodesiv, goli menadžer prozora
+Comment[sv]=Den lättviktiga fönsterhanteraren. En enkel fönsterhanterare utan anpassningsmöjligheter
+Comment[ta]=குறைந்த எடையுள்ள சாளர மேலாளர். வடிவமைக்க முடியாத
+Comment[th]=Lightweight Window Manager ระบบจัดการหน้าต่างเปล่าๆ ที่ไม่สามารถปรับแต่งได้เลย
+Comment[tr]=Lightweight Pencere Yöneticisi. Yapılandırılamayan, kaba pencere yönetici
+Comment[tt]=Lightweight Window Manager. Caylanmí torğan, ciñel täräzä-idäräçe
+Comment[uk]=Невеличкий менеджер вікон без можливості налаштування
+Comment[vi]=Trình Quản lý Cửa sổ Nhẹ ký. Rất khó cấu hình
+Comment[wa]=Li Ledjir Manaedjeu di Purneas (Lightweight Window Manager). On manaedjeu di purneas tot simpe, nén apontiåve
+Comment[zh_CN]=轻量级窗口管理器。不可配置的裸窗口管理器
+Comment[zh_TW]=一個輕量化的視窗管理程式。不可組態、只有基礎視窗管理的視窗管理程式
+# this can't be used as a session in itself
+Hidden=true
diff --git a/tdm/kfrontend/sessions/matchbox.desktop b/tdm/kfrontend/sessions/matchbox.desktop
new file mode 100644
index 00000000..3bec343b
--- /dev/null
+++ b/tdm/kfrontend/sessions/matchbox.desktop
@@ -0,0 +1,82 @@
+[Desktop Entry]
+Type=XSession
+Exec=matchbox-window-manager
+TryExec=matchbox-window-manager
+Name=Matchbox
+Name[bn]=ম্যাচবক্স
+Name[eo]=Alumetujo
+Name[hi]=मैचबॉक्स
+Name[ne]=मिल्ने बाकस
+Name[pa]=ਮੈਚ-ਬਾਕਸ
+Name[rw]=Agasandukugahura
+Name[ta]=பொருத்தப்பெட்டி
+Name[te]=అగ్గి పెట్టె
+Name[tg]=Қуттии гӯгирд
+Name[wa]=Boesse di brocales (Matchbox)
+Comment=A window manager for handheld devices
+Comment[af]='n Venster bestuurder vir draagbare toestelle
+Comment[ar]=مدير نوافذ للأجهزة اليدوية
+Comment[be]=Кіраўнік вокнаў для кішанёвых кампутараў
+Comment[bn]=হ্যাণ্ডহেল্ড যন্ত্রাদির উপযোগী একটি উইণ্ডো ম্যানেজার
+Comment[bs]=Window manager za ručne uređaje
+Comment[ca]=Un gestor de finestres per a dispositius de ma
+Comment[cs]=Správce oken pro PDA
+Comment[csb]=Menedżer òknów dlô palmtopów
+Comment[cy]=Trefnydd ffenestri ar gyfer llawiaduron
+Comment[da]=En vindueshåndtering for håndholdte enheder
+Comment[de]=Fenstermanager für portable Geräte
+Comment[el]=Ένας διακομιστής παραθύρων για συσκευές παλάμης
+Comment[eo]=Fenestroadministrilo por manaj aparatoj
+Comment[es]=Un gestor de ventanas para dispositivos de mano
+Comment[et]=Aknahaldur pihuarvutitele
+Comment[eu]=Eskuan erabiltzeko gailuentzako leiho kudeatzailea
+Comment[fa]=یک مدیر پنجره برای دستگاههای دستی
+Comment[fi]=ikkunaohjelma PDA-laitteisiin
+Comment[fr]=Un gestionnaire de fenêtres pour les périphériques contrôlés à la main
+Comment[fy]=In finstersmanager foar hânkompjûters
+Comment[gl]=Un xestor de fiestras para dispositivos manuais
+Comment[he]=מנהל חלונות למכשירים נישאים
+Comment[hi]=हाथ में रखने वाले औज़ारों के लिए विंडो प्रबंधक
+Comment[hr]=Upravitelj prozora za ručna računala
+Comment[hu]=Ez az ablakkezelő elsősorban kéziszámítógépekhez ajánlott
+Comment[is]=Gluggastjóri fyrir lófatölvur
+Comment[it]=Un window manager per palmari
+Comment[ja]=ハンドヘルドデバイス向けのウィンドウマネージャ
+Comment[ka]=ფანჯრების მენეჯერი მობილური მოწყობილობებისთვის
+Comment[kk]=Қол құрылғыларға арналған терезе менеджері
+Comment[km]=កម្មវិធី​គ្រប់គ្រង​បង្អួច សម្រាប់​ឧបករណ៍​យួរដៃ
+Comment[ko]=핸드헬드 장치를 위한 창 관리자
+Comment[lt]=Langų tvarkyklė įvairiems įrenginiams
+Comment[lv]=Logu menedžeris priekš portatīvajām iekārtām
+Comment[mk]=Менаџер на прозорци за преносни уреди
+Comment[mn]=Гар төхөөрөмжид зориулсан цонхны удирдлага
+Comment[ms]=Pengurus tetingkap untuk peranti telapak
+Comment[mt]=Window manager għal apparat "handheld"
+Comment[nb]=En vindusbehandler for håndholdte enheter
+Comment[nds]=Finsterpleger för Handreekner
+Comment[ne]=ह्यान्डहेल्ड यन्त्रहरूका लागि सञ्झ्याल प्रबन्धक
+Comment[nl]=Een windowmanager voor handcomputers
+Comment[nn]=Ein vindaugssjef for handhaldne einingar
+Comment[pa]=ਹੱਥਲੇ ਜੰਤਰਾਂ ਲਈ ਝਰੋਖਾ ਮੈਨੇਜਰ
+Comment[pl]=Menedżer okien dla palmtopów
+Comment[pt]=Um gestor de janelas para dispositivos móveis
+Comment[pt_BR]=Um gerenciador de janelas para dispositivos handheld
+Comment[ro]=Un manager de ferestre pentru PDA-uri
+Comment[ru]=Оконный менеджер для мобильных устройств
+Comment[rw]=Mugenga dirishya y'amapareye atwarwa-ntoki
+Comment[se]=Lásegieđahalli giehtaovttadagaid várás
+Comment[sk]=Správca okien pre prenosné zariadenia
+Comment[sl]=Okenski upravitelj za dlančne naprave
+Comment[sr]=Менаџер прозора за мале преносне уређаје
+Comment[sr@Latn]=Menadžer prozora za male prenosne uređaje
+Comment[sv]=Fönsterhanterare för handburna enheter
+Comment[ta]=கையில் உள்ள சாதனங்களுக்கான சாளர மேலாளர்
+Comment[tg]=Як мудири тиреза барои дастгоҳҳои дастӣ
+Comment[th]=ระบบจัดการหน้าต่างของอุปกรณ์มือถือ
+Comment[tr]=El bilgisayarları için bir pencere yöneticisi
+Comment[tt]=Qul cıhazı öçen täräzä-idäräçe
+Comment[uk]=Менеджер вікон для портативних пристроїв
+Comment[vi]=Trình quản lý cửa sổ dành cho thiết bị cầm tay
+Comment[wa]=On manaedjeu di purneas po les éndjins ebarkés
+Comment[zh_CN]=手持设备的窗口管理器
+Comment[zh_TW]=一個掌上型設備所使用的視窗管理程式
diff --git a/tdm/kfrontend/sessions/metacity.desktop b/tdm/kfrontend/sessions/metacity.desktop
new file mode 100644
index 00000000..d2a5a553
--- /dev/null
+++ b/tdm/kfrontend/sessions/metacity.desktop
@@ -0,0 +1,83 @@
+[Desktop Entry]
+Type=XSession
+Exec=metacity
+TryExec=metacity
+Name=Metacity
+Name[bn]=মেটাসিটি
+Name[eo]=Metaurbo
+Name[hi]=मेटासिटी
+Name[mn]=Метасити
+Name[ne]=मेटासिटी
+Name[rw]=Metacity(Mugenga-dirishya)
+Name[ta]=மெடாசிட்டி
+Name[te]=మెటాసిటి
+Comment=A lightweight GTK2 based window manager
+Comment[af]=Die lig gewig GTK2 gebaseerde venster bestuurder
+Comment[ar]=مدير نوافذ خفيف العبء مبني على GTK2
+Comment[be]=Лёгкі кіраўнік вокнаў, заснаваны на GTK2
+Comment[bn]=একটি হাল্কা GTK2 ভিত্তিক উইণ্ডো ম্যানেজার
+Comment[bs]=Lagani window manager baziran na GTK2
+Comment[ca]=Un gestor de finestres lleuger basat en GTK2
+Comment[cs]=Malý správce oken založený na GTK2
+Comment[csb]=Menedżer òknół ò môłëch żądniach, òpiarti na GTK2
+Comment[cy]=Trefnydd ffenestri ysgafn, wedi'i seilio ar GTK2
+Comment[da]=En letvægts GTK2 baseret vindueshåndtering
+Comment[de]=Schlanker Fenstermanager, der auf GTK2 basiert
+Comment[el]=Ένας ελαφρύς διαχειριστής παραθύρων βασισμένος στο GTK2
+Comment[eo]=Malpeza fenestroadministrilo
+Comment[es]=Un gestor de ventanas ligero basado en GTK2
+Comment[et]=Imeväike aknahaldur, mille aluseks on GTK2
+Comment[eu]=GTK2n oinarritutako leiho kudeatzaile arin bat
+Comment[fa]=GTK2 سبک بر اساس مدیر پنجره
+Comment[fi]=Kevyt, GTK2-pohjainen ikkunaohjelma
+Comment[fr]=Un gestionnaire de fenêtres fondé sur GTK2 et léger
+Comment[fy]=In lichtgewicht op GTK2 basearre finstersmanager
+Comment[gl]=Un xestor de fiestras lixeiro baseado en GTK2
+Comment[he]=מנהל חלונות קל מבוסס GTK2
+Comment[hi]=जीटीके2 आधारित हल्का विंडो प्रबंधक
+Comment[hr]=Lagani upravitelj prozora zasnovan na GTK2
+Comment[hu]=Egy egyszerű, GTK2-alapú ablakkezelő
+Comment[is]=Léttur gluggastjóri byggður á GTK2
+Comment[it]=Un window manager leggero basato su GTK2
+Comment[ja]=GTK2 ベースの軽量なウィンドウマネージャ
+Comment[ka]=GTK2-ს ბაზაზე მსუბუქი ფანჯრის მენეჯერი
+Comment[kk]=GTK2-негіздеген, жеңіл терезе менеджері
+Comment[km]=កម្មវិធី​គ្រប់គ្រង​បង្អួច​សមត្ថភាព​ខ្សោយ ដែល​ផ្អែក​លើ GTK2
+Comment[ko]=가벼운 GTK2 기반 창 관리자
+Comment[lt]=Nedaug resursų reikalaujanti langų tvarkyklė, paremta GTK2
+Comment[lv]=Viegls GTK 2 bāzēts logu menedžeris
+Comment[mk]=Лесен менаџер на прозорци базиран на GTK2
+Comment[mn]=Хөнгөн GTK2 суурьт цонхны удирдагч
+Comment[ms]=Pengurus tetingkap berasaskan GTK2 ringan
+Comment[mt]=Window manager ħafif ibbażat fuq GTK2
+Comment[nb]=En lettvekts vindusbehandler basert på GTK2
+Comment[nds]=En ranke Finsterpleger, opbuut op GTK2
+Comment[ne]=सञ्झ्याल प्रबन्धकमा आधारित हल्का वजन GTK2
+Comment[nl]=Een lichtgewicht op GTK2 gebaseerde windowmanager
+Comment[nn]=En lett vindaugssjef basert på GTK2
+Comment[pa]=ਇੱਕ ਹਲਕਾ GTK2 ਤੇ ਆਧਾਰਿਤ ਝਰੋਖਾ ਮੈਨੇਜਰ
+Comment[pl]=Menedżer okien o małych wymaganiach, oparty na GTK2
+Comment[pt]=Um gestor de janelas leve, baseado em GTK2
+Comment[pt_BR]=Um gerenciador de Janelas leve baseado em GTK2
+Comment[ro]=Un manager de ferestre mic bazat pe GTK2
+Comment[ru]=Лёгкий оконный менеджер на основе GTK2
+Comment[rw]=Mugenga dirishya ishingiye kuri GTK2 yoroshye
+Comment[se]=Geahpes GTK2-vuođđoduvvon lásegieđahalli
+Comment[sk]=Nenáročný správca okien založený na GTK2
+Comment[sl]=Lahek okenski upravitelj na osnovi GTK2
+Comment[sr]=Лагани менаџер прозора заснован на GTK2
+Comment[sr@Latn]=Lagani menadžer prozora zasnovan na GTK2
+Comment[sv]=Lättviktig GTK2-baserad fönsterhanterare
+Comment[ta]=சாளர மேலாளர் அடிப்படையிலான ஒரு குறைந்த எடை GTK2
+Comment[te]=తెలికైన జిటికె2 ఆధారిత విండొ అభికర్త
+Comment[tg]=Сабуки GTK2 ба асоси мудири тиреза
+Comment[th]=ระบบจัดการหน้าต่างขนาดเบาที่ใช้ GTK2
+Comment[tr]=Gtk2 tabanlı hafif bir pencere yöneticisi
+Comment[tt]=GTK2 asılında ciñel täräzä-idäräçe
+Comment[uk]=Простий менеджер вікон для GTK2
+Comment[uz]=GTK2 asosida yaratilgan oddiy oyna boshqaruvchi
+Comment[uz@cyrillic]=GTK2 асосида яратилган оддий ойна бошқарувчи
+Comment[vi]=Trình quản lý cửa sổ nhỏ gọn dựa trên GTK2
+Comment[wa]=On ledjir manaedjeu di purneas båzé so GTK2
+Comment[zh_CN]=轻量级 GTK2 窗口管理器
+Comment[zh_TW]=一個基於 GTK2 的輕量化視窗管理程式
diff --git a/tdm/kfrontend/sessions/mwm.desktop b/tdm/kfrontend/sessions/mwm.desktop
new file mode 100644
index 00000000..b1d6e2ac
--- /dev/null
+++ b/tdm/kfrontend/sessions/mwm.desktop
@@ -0,0 +1,78 @@
+[Desktop Entry]
+Type=XSession
+Exec=mwm
+TryExec=mwm
+Name=MWM
+Name[eo]=MFA
+Name[hi]=एमडबल्यूएम
+Name[te]=ఎం డబ్ల్యు ఎం
+Name[th]=ตัวจัดการหน้าต่าง MWM
+Comment=The Motif Window Manager
+Comment[af]=Die Motif venster bestuurder
+Comment[ar]=مسيير النوافذ Motif
+Comment[be]=Кіраўнік вокнаў Motif
+Comment[bn]=দি মোটিফ উইণ্ডো ম্যানেজার
+Comment[bs]=Motif Window Manager
+Comment[ca]=El gestor de finestres Motif
+Comment[cs]=Motif Window Manager
+Comment[csb]=Menedżer òknów Motif
+Comment[cy]=Y Trefnydd Ffenestri Motif
+Comment[da]=Motif vindueshåndtering
+Comment[de]=Motif-Fenstermanager
+Comment[el]=Ο διαχειριστής παραθύρων Motif
+Comment[eo]=Motifa fenestroadministrilo
+Comment[es]=El gestor de ventanas de Motif
+Comment[et]=Motifi aknahaldur
+Comment[eu]=Motif leiho kudeatzailea
+Comment[fa]=مدیر پنجره موتیف
+Comment[fi]=Motif-ikkunaohjelma
+Comment[fr]=Le gestionnaire de fenêtres Motif
+Comment[fy]=De Motif Window Manager
+Comment[ga]=Bainisteoir fuinneoga Motif
+Comment[gl]=O Xestor de Fiestras Motif
+Comment[he]=מנהל החלונות Motif
+Comment[hi]=मोटिफ विंडो प्रबंधक
+Comment[hr]=Motif upravitelj prozora
+Comment[hu]=Motif ablakkezelő
+Comment[is]=Motif gluggastjórinn
+Comment[it]=Il window manager di Motif
+Comment[ja]=Motif 風のウィンドウマネージャ
+Comment[ka]=ფანჯრის მენეჯერი Motif
+Comment[kk]=Motif терезе менеджері
+Comment[km]=កម្មវិធី​គ្រប់គ្រង​បង្អួច Motif
+Comment[ko]=Motif 창 관리자
+Comment[lt]=Motif langų tvarkyklė
+Comment[lv]=Motif logu menedžeris
+Comment[mk]=Менаџерот на прозорци Motif
+Comment[mn]=Motif Цонхны удирдагч
+Comment[ms]=Pengurus Tertingkap Motif
+Comment[mt]=Window manager tal-Motif
+Comment[nb]=Motif vindusbehandler
+Comment[nds]=De Motif-Finsterpleger
+Comment[ne]=मोटिफ सञ्झ्याल प्रबन्धक
+Comment[nl]=De Motif Window Manager
+Comment[nn]=Motif-vindaugssjefen
+Comment[pa]=Motif ਝਰੋਖਾ ਮੈਨੇਜਰ
+Comment[pl]=Menedżer okien Motif
+Comment[pt]=O gestor de janelas do Motif
+Comment[pt_BR]=O gerenciador de janelas Motif
+Comment[ro]=Managerul de ferestre Motif
+Comment[ru]=Оконный менеджер Motif
+Comment[rw]=Mugenga Dirishya Umutako
+Comment[se]=Motif lásegieđahalli
+Comment[sk]=Správca okien Motif
+Comment[sl]=Okenski upravitelj Motif
+Comment[sv]=Motifs fönsterhanterare
+Comment[ta]=மோடிஃப் சாளர மேலாளர்
+Comment[te]=మొటిఫ్ విండొ అభికర్త
+Comment[tg]=Мавзӯъи мудири тиреза
+Comment[th]=ระบบจัดการหน้าต่างของโมทิฟ
+Comment[tr]=Motif Pencere Yöneticisi
+Comment[tt]=Motif Täräzä İdäräçe
+Comment[uk]=Менеджер вікон Motif
+Comment[uz]=Motif oyna boshqaruvchi
+Comment[uz@cyrillic]=Motif ойна бошқарувчи
+Comment[vi]=Trình quản lý cửa sổ Motif
+Comment[wa]=Li manaedjeu di purneas di Motif
+Comment[zh_CN]=Motif 窗口管理器
+Comment[zh_TW]=Motif 視窗管理程式
diff --git a/tdm/kfrontend/sessions/olvwm.desktop b/tdm/kfrontend/sessions/olvwm.desktop
new file mode 100644
index 00000000..23dee116
--- /dev/null
+++ b/tdm/kfrontend/sessions/olvwm.desktop
@@ -0,0 +1,71 @@
+[Desktop Entry]
+Type=XSession
+Exec=olvwm-x-window-manager
+TryExec=olvwm-x-window-manager
+Name=OLVWM
+Name[br]=OVLWM
+Name[eo]=OLVFA
+Name[hi]=ओएलवीडबल्यूएम
+Name[te]=ఒ ఎల్ వి డబ్యు ఎం
+Comment=The OpenLook Virtual Window Manager. OLWM enhanced for handling of virtual desktops
+Comment[af]=Die OpenLook virtuele venster bestuurder. OLWM wat uitgebrei is vir virtuele werkskerms
+Comment[ar]=مدير النوافذ الوهمي OpenLook، محسّن للتعامل مع أسطح المكتب الوهمية
+Comment[be]=The OpenLook Virtual Window Manager. OLWM дапрацаваны для падтрымкі віртуальных працоўных сталоў
+Comment[bn]=দি ওপেনলুক ভার্চুয়াল উইণ্ডো ম্যানেজার। OLWM-এর বর্ধিত সংস্করণ যাতে ভার্চুয়াল ডেস্কটপ সমর্থিত
+Comment[bs]=OpenLook Virtual Window Manager. OLWM proširen podrškom za virtualne desktope
+Comment[ca]=El OpenLook Virtual Window Manager. OLWM millorat per a escriptoris virtuals de ma
+Comment[csb]=OpenLook Virtual Window Manager. OLWM zbògacony ò wspiarce wirtualnëch pùltów
+Comment[cy]=Y Trefnydd Ffenestri Rhith GolwgAgored (OpenLook). OLWM wedi'i wella i gynnal penbyrddau rhith
+Comment[da]=OpenLook Virtual Window Manager. OLWM udvidet med håndtering af virtuelle desktoppe
+Comment[de]=OpenLook virtueller Fenstermanager, OLWM mit verbesserter Verwaltung von virtuellen Arbeitsflächen
+Comment[el]=Ο OpenLook εικονικός διαχειριστής παραθύρων. Ο OLWM εμπλουτισμένος με διαχείριση εικονικών επιφανειών εργασίας
+Comment[eo]=Fenestroadministrilo por virtualaj labortabloj
+Comment[es]=El OpenLook Virtual Window Manager, un versión mejorada de OLWM con soporte para escritorios virtuales
+Comment[et]=OpenLook virtuaalne aknahaldur on OLWM, mida on täiendatud virtuaalsete töölaudade võimalusega
+Comment[eu]=OpenLook leiho kudeatzaile birtuala. mahaigain birtualak kudeatzeko OLWM hobetua
+Comment[fa]=مدیر پنجرۀ مجازی OpenLook. OLWM گسترش‌یافته برای گرداندن رومیزیهای مجازی
+Comment[fi]=OpenLook virtuaalinen ikkunanhallinta. OLWM:n paranneltu versio,joka käsittelee virtuaalityöpöytiä paremmin
+Comment[fr]=The OpenLook Virtual Window Manager. OLWM avec en plus la gestion des bureaux virtuels
+Comment[fy]=De OpenLook Virtual Window Manager. OLWM útbreide mei firtuele buroblêden
+Comment[gl]=O OpenLook Virtual Window Manager. OLWM mellorado para manexar escritórios virtuais
+Comment[he]=The OpenLook Virtual Window Manager. OLWM משופר בשביל טיפול בשולחנות עבודה וירטואליים
+Comment[hi]=ओपनलुक आभासी विंडो प्रबंधक. ओएलडबल्यूएम को आभासी डेस्कटॉप हैंडल करने के लिए बेहतर बनाया गया
+Comment[hr]=OpenLook virtualni upravitelj prozora - OLWM unaprijeđen mogućnošću rukovanja s virtualnim radnim površinama
+Comment[hu]=OpenLook Virtual Window Manager (OLWM), virtuális munkaasztalok kezelésére is képes
+Comment[is]=OpenLook sýndargluggastjórinn. Endurbættur með OLWM til að styðja sýndarskjáborð
+Comment[it]=L'OpenLook Virtual Window Manager. OLWM migliorato per gestire i desktop virtuali
+Comment[ja]=OpenLook 仮想ウィンドウマネージャ, OLWM 強化仮想デスクトップ
+Comment[ka]=გაუმჯობესებული ფანჯრის მენეჯერი OpenLook, რამდენიმე სამუშაო დაფის მხარდაჭერით
+Comment[kk]=OpenLook Virtual Window Manager - виртуалды үстелдерді қолдайтын терезе менеджері
+Comment[km]=OpenLook Virtual Window Manager ។ OLWM ដែល​បាន​ធ្វើ​ឲ្យ​ប្រសើរ សម្រាប់​ការ​ប្រើ​ផ្ទៃតុ​និមិត្ត ។
+Comment[lt]=OpenLook virtuali langų tvarkyklė. OLWM išplėsta su virtualių darbastalių palaikymu
+Comment[mk]=OpenLook Virtual Window Manager. OLWM менаџерот со подобрено ракување на виртуелни површини
+Comment[ms]=Pengurus Tetingkap Maya OpenLook. OLWM dipertingkat untuk mengendalikan desktop maya
+Comment[mt]=OpenLook Virtual Window Manager - OLWM flimkien ma' desktops virtwali.
+Comment[nb]=OpenLook Virtual Window Manager. OLWM utvidet med virtuelle skrivebord.
+Comment[nds]=De "OpenLook Virtual Window Manager" is OLWM verwiedert üm virtuelle Schriefdischen
+Comment[ne]=अवास्तविक डेस्कटपहरूको ह्यान्डलका लागि बृद्धि गरिएको OLWM खुला देखिने अवास्तविक सञ्झ्याल प्रबन्धक ।
+Comment[nl]=De OpenLook Virtual Window Manager. OLWM uitgebreid met virtuele bureaubladen
+Comment[nn]=OpenLook Virtual Window Manager. OLWM utvida med virtuelle skrivebord.
+Comment[pa]=OpenLook Virtual Window Manager. OLWM ਫਰਜ਼ੀ ਵੇਹੜਿਆਂ ਲਈ ਖਾਸ ਤੌਰ ਤੇ ਤਿਆਰ
+Comment[pl]=OpenLook Virtual Window Manager. OLWM wzbogacony o obsługę wirtualnych pulpitów
+Comment[pt]=O OpenLook Virtual Window Manager. Um OLWM melhorado para lidar com ecrãs virtuais
+Comment[pt_BR]=Acrônimo para OpenLook Virtual Window Manager, o OLWM melhorado para a manipulação de áreas de trabalho virtuais
+Comment[ro]=OpenLook Virtual Window Manager. Un OLWM îmbunătățit cu ecrane virtuale
+Comment[ru]=Улучшенный оконный менеджер OpenLook, поддерживающий несколько рабочих столов
+Comment[rw]=Mugenga Dirishya Itagaragara GufunguraKureba. OLWM ivuguruwe mu gufasha ibiro bitagaragara
+Comment[se]=The OpenLook Virtual Window Manager. OLWM buoriduvvon nu ahte das leat virtuella čállinbeavddit
+Comment[sk]=Virtuálny správca okien OpenLook. OLWM rozšírený o podporu virtuálnych plôch
+Comment[sl]=Open Look Virtual Window Manager je izboljšan OLWM s podporo navideznim namizjem
+Comment[sr]=„OpenLook Virtual Window Manager“. OLWM побољшан за управљање виртуелним радним површинама
+Comment[sr@Latn]=„OpenLook Virtual Window Manager“. OLWM poboljšan za upravljanje virtuelnim radnim površinama
+Comment[sv]=Open Look virtuell fönsterhanterare. OLWM utökad för att hantera virtuella skrivbord
+Comment[ta]=ஓபன்லுக் மெய்நிகர் சாளர மேலாளர். மெய்நிகர் மேல்மேசைகளை கையாளுவதற்கு OLWM மேம்படுத்தப்பட்டது.
+Comment[th]=ระบบจัดการหน้าต่างเสมือน OpenLook คือ OLWM ที่ถูกเพิ่มเติมความสามารถในการรับมือกับพื้นที่ทำงานเสมือน
+Comment[tr]=OpenLook Sanal Pencere Yöneticisi.
+Comment[tt]=OpenLook Virtual Window Manager. Xıyalí öställär öçen yaqşırtılğan OpenLook
+Comment[uk]=OpenLook Virtual Window Manager. OLWM з підтримкою віртуальних стільниць
+Comment[vi]=Trình Quản lý Cửa sổ Ảo "Cái nhìn Mở". Nó được cải tiến cho việc xử lý màn hình nền ảo
+Comment[wa]=Li Manaedjeu di Forveyou Purnea OpenLook (OpenLook Virtual Window Manager). OLWM permete d' apougnî des forveyowès sicribannes
+Comment[zh_CN]=OpenLook 虚拟窗口管理器。OLWM 特别增强了虚拟桌面的处理
+Comment[zh_TW]=Openlook 視窗管理程式。基於 OLWM 並強化管理虛擬桌面
diff --git a/tdm/kfrontend/sessions/olwm.desktop b/tdm/kfrontend/sessions/olwm.desktop
new file mode 100644
index 00000000..32612eaa
--- /dev/null
+++ b/tdm/kfrontend/sessions/olwm.desktop
@@ -0,0 +1,76 @@
+[Desktop Entry]
+Type=XSession
+Exec=olwm-x-window-manager
+TryExec=olwm-x-window-manager
+Name=OLWM
+Name[eo]=OLFA
+Name[hi]=ओएलडबल्यूएम
+Name[te]=ఒ ఎల్ డబ్యు ఎం
+Name[th]=ตัวจัดการหน้าต่าง OLWM
+Comment=The traditional Open Look Window Manager
+Comment[af]=Die tradisionele Open Look venster bestuurder
+Comment[ar]=مسيير النوافذ Open Look التقليدي
+Comment[be]=Традыцыйны кіраўнік вокнаў Open Look
+Comment[bn]=দি ওপেনলুক উইণ্ডো ম্যানেজার
+Comment[bs]=Tradicionalni Open Look Window Manager
+Comment[ca]=El tradicional gestor de finestres Open Look
+Comment[cs]=Tradiční Open Look Window Manager
+Comment[csb]=Tradicëjny menedżer òknów Open Look
+Comment[cy]=Y Trefnydd Ffenestri GolwgAgored (OpenLook) traddodiadol
+Comment[da]=Den traditionelle Open Look vindueshåndtering
+Comment[de]=Der traditionelle Open-Look-Fenstermanager
+Comment[el]=Ο παραδοσιακός διαχειριστής παραθύρων Open Look
+Comment[eo]=La klasika OL-fenestroadministrilo
+Comment[es]=El tradicional Open Look Window Manager
+Comment[et]=Tavapärane OpenLooki aknahaldur
+Comment[eu]=Betiko Open Look leiho kudeatzailea
+Comment[fa]=مدیر پنجره Open Look سنتی
+Comment[fi]=Perinteinen Open Look -ikkunaohjelma
+Comment[fr]=Le gestionnaire de fenêtres traditionnel Open Look
+Comment[fy]=De tradisjoneel iepen like finstersManager
+Comment[gl]=O tradicional Xestor de Fiestras de Open Look
+Comment[he]=Open Look Window Manager המסורתי
+Comment[hi]=परम्परागत ओपन लुक विंडो प्रबंधक
+Comment[hr]=Tradicionalni 'Open Look' upravitelj prozora
+Comment[hu]=A hagyományos Open Look ablakkezelő
+Comment[is]=Hinn hefðbundni Open Look gluggastjóri
+Comment[it]=L'Open Look Window Manager tradizionale
+Comment[ja]=伝統的な OpenLook ウィンドウマネージャ
+Comment[ka]=OpenLook სისტემის ტრადიციული ფანჯრის მენეჯერი
+Comment[kk]=Дәстүрлі Open Look терезе менеджері
+Comment[km]=កម្មវិធី​គ្រប់គ្រង​បង្អួច​រូបរាង​បើក​ចំហ​បុរាណ
+Comment[lt]=Tradicinė Open Look langų tvarkyklė
+Comment[lv]=Tradicionālais Open Look logu menedžeris
+Comment[mk]=Традиционален Open Look Window Manager
+Comment[mn]=Уламжилалт нээж харагч цонхны удирдагч
+Comment[ms]=Pengurus Tetingkap OpenLook tradisional
+Comment[mt]=Window manager tradizzjonali ta' OpenLook
+Comment[nb]=Den tradisjonelle Open Look-vindusbehandleren
+Comment[nds]=De traditschonelle OpenLook-Finsterpleger
+Comment[ne]=खुला देखिने परम्परागत सञ्झ्याल प्रबन्धक
+Comment[nl]=De traditionele Open Look Window Manager
+Comment[nn]=Den tradisjonelle Open Look-vindaugssjefen
+Comment[pa]=ਇੱਕ ਮੂਲ ਓਪਨ ਲੁੱਕ ਝਰੋਖਾ ਮੈਨੇਜਰ
+Comment[pl]=Tradycyjny menedżer okien Open Look
+Comment[pt]=O gestor de janelas Open Look tradicional
+Comment[pt_BR]=O tradicional Open Look Window Manager
+Comment[ro]=Managerul de ferestre tradițional Open Look Window Manager
+Comment[ru]=Традиционный оконный менеджер системы OpenLook
+Comment[rw]=Mugenga Dirishya Gufungura Kureba karande
+Comment[se]=Árbevirolaš Open Look lásegieđahalli
+Comment[sk]=Tradičný správca okien Open Look
+Comment[sl]=Tradicionalni Open Look Window Manager
+Comment[sr]=Традиционални „Open Look“ менаџер прозора
+Comment[sr@Latn]=Tradicionalni „Open Look“ menadžer prozora
+Comment[sv]=Den traditionella Open Look fönsterhanteraren
+Comment[ta]=பழமையான சாளர மேலாளர்
+Comment[te]=సాంప్రదాయ ఒపెన్ లుక్ విండొ అభికర్త
+Comment[tg]=Расмшудаи Open Look-и мудири тиреза
+Comment[th]=ระบบจัดการหน้าต่าง OpenLook แบบดั้งเดิม
+Comment[tr]=OpenLook Pencere Yöneticisi
+Comment[tt]=Open Look täräzä-idäräçeneñ töp söreme
+Comment[uk]=Традиційний менеджер вікон Open Look
+Comment[vi]=Trình Quản lý Cửa sổ "Cái nhìn Mở" truyền thống
+Comment[wa]=Li mwaisse Manaedjeu di Purnea OpenLook (OpenLook Virtual Window Manager)
+Comment[zh_CN]=传统的 OpenLook 窗口管理器
+Comment[zh_TW]=傳統的 Open Look 視窗管理程式
diff --git a/tdm/kfrontend/sessions/openbox.desktop b/tdm/kfrontend/sessions/openbox.desktop
new file mode 100644
index 00000000..d0f4a06d
--- /dev/null
+++ b/tdm/kfrontend/sessions/openbox.desktop
@@ -0,0 +1,84 @@
+[Desktop Entry]
+Type=XSession
+Exec=openbox-session
+TryExec=openbox
+Name=Openbox
+Name[bn]=ওপেনবক্স
+Name[cy]=Blwchagored (Openbox)
+Name[eo]=Malfermujo
+Name[hi]=ओपनबाक्स
+Name[ne]=खुला बाकस
+Name[pa]=ਓਪਨ ਬਕਸਾ
+Name[rw]=GufunguraAgasanduku
+Name[ta]=திறப்பு பெட்டி
+Name[te]=ఒపెన్ బాక్స్
+Name[tg]=Кушодани қуттӣ
+Comment=A lightweight window manager based on Blackbox
+Comment[af]='n Lig gewig venster bestuurder wat op Blackbox gebaseer is
+Comment[ar]=مدير نوافذ خفيف العبء مبني على Blackbox
+Comment[be]=Лёгкі кіраўнік вокнаў, заснаваны на Blackbox
+Comment[bn]=ব্ল্যাকবক্স ভিত্তিক হাল্কা উইণ্ডো ম্যানেজার
+Comment[bs]=Lagani window manager baziran na Blackbox-u
+Comment[ca]=Un lleuger gestor de finestres basat en Blackbox
+Comment[cs]=Malý správce oken založený na Blackboxu
+Comment[csb]=Menedżer òknów o môłëch żądaniach, òpairti na Blackbox
+Comment[cy]=Trefnydd ffenestri ysgafn, wedi'i seilio ar Ddu-flwch
+Comment[da]=En letvægts vindueshåndtering baseret på Blackbox
+Comment[de]=Schlanker Fenstermanager, der auf Blackbox beruht
+Comment[el]=Ένας ελαφρύς διαχειριστής παραθύρων βασισμένος στον Blackbox
+Comment[eo]=Fenestroadministrilo devenigita de Negrujo
+Comment[es]=Un gestor de ventanas ligero basado en BlackBox
+Comment[et]=Imeväike aknahaldur, mille aluseks on Blackbox
+Comment[eu]=Blackboxen oinarritutako leiho kudeatzaile arina
+Comment[fa]=یک مدیر پنجرۀ سبک بر اساس Blackbox
+Comment[fi]=Kevyt, Blackboxiin pohjautuva ikkunaohjelma
+Comment[fr]=Un gestionnaire de fenêtres léger fondé sur Blackbox
+Comment[fy]=In lichtgewicht finstersmanager, basearre op Blackbox
+Comment[gl]=Un xestor de fiestras lixeiro baseado en Blackbox
+Comment[he]=מנהל חלונות קל מבוסס על Blackbox
+Comment[hi]=ब्लेकबाक्स आधारित हल्का विंडो प्रबंधक
+Comment[hr]=Lagani upravitelj prozora zasnovan na Blackboxu
+Comment[hu]=Egy nagyon egyszerű ablakkezelő a Blackbox alapján
+Comment[is]=Léttur gluggastjóri byggður á Blackbox
+Comment[it]=Un window manager leggero basato su BlackBox
+Comment[ja]=Blackbox ベースの軽量なウィンドウマネージャ
+Comment[ka]=Blackbox-ის ბაზაზე ფანჯრიოს მენეჯერი
+Comment[kk]=Blackbox-негіздеген жеңіл терезе менеджері
+Comment[km]=កម្មវិធី​គ្រប់គ្រង​បង្អួច​សមត្ថភាព​ខ្សោយ ដែល​ផ្អែក​លើ Blackbox
+Comment[ko]=Blackbox 기반 가벼운 창 관리자
+Comment[lt]=Nedaug resursų reikalaujanti langų tvarkyklė, paremta Blackbox
+Comment[lv]=Viegls logu menedžeris, bāzēts uz Blackbox
+Comment[mk]=Лесен менаџер на прозорци базиран на Blackbox
+Comment[ms]=Pengurus tetingkap ringan berdasarkan Kotak Hitam
+Comment[mt]=Window manager ħafif ibbażat fuq BlackBox
+Comment[nb]=En lettvekts vindusbehandler basert på Blackbox
+Comment[nds]=En ranke Finsterpleger, opbuut op Blackbox
+Comment[ne]=कालो बाकसमा आधारित हल्का वजन सञ्झ्याल प्रबन्धक
+Comment[nl]=Een lichtgewicht windowmanager, gebaseerd op Blackbox
+Comment[nn]=Ein lett vindaugssjef basert på Blackbox
+Comment[pa]=ਬਲੈਕਬਕਸੇ ਤੇ ਆਧਾਰਿਤ ਹਲਕਾ ਝਰੋਖਾ ਮੈਨੇਜਰ
+Comment[pl]=Menedżer okien o małych wymaganiach, oparty na Blackbox
+Comment[pt]=Um gestor de janelas leve baseado no Blackbox
+Comment[pt_BR]=Um gerenciador de janelas leve, baseado no Blackbox
+Comment[ro]=Un manager de ferestre minimal bazat pe Blackbox
+Comment[ru]=Лёгкий оконный менеджер, основанный на Blackbox
+Comment[rw]=Mugenga dirishya yoroshye ishingiye ku Gasandukumukara
+Comment[se]=Geahpes lásegieđahalli ráhkaduvvon Blackboxa vuođul
+Comment[sk]=Nenáročný správca okien založený na Blackbox
+Comment[sl]=Lahek okenski upravitelj na osnovi Blackboxa
+Comment[sr]=Лагани менаџер прозора заснован на Blackbox-у
+Comment[sr@Latn]=Lagani menadžer prozora zasnovan na Blackbox-u
+Comment[sv]=Lättviktig fönsterhanterare baserad på Blackbox
+Comment[ta]=கருப்புப் பெட்டியின் அடிப்படையிலான ஒரு குறைந்த எடை சாளர மேலாளர்
+Comment[te]=బ్లాక్ బాక్స్ ఆధారిత తెలికైన విండొ అభికర్త
+Comment[tg]=Мудири тирезаи сабук ба асоси қуттии сиёҳ
+Comment[th]=ระบบจัดการหน้าต่างขนาดเบา สร้างมาจาก Blackbox
+Comment[tr]=Blackbox temelli küçük bir pencere yöneticisi
+Comment[tt]=Blackbox asılında ciñel täräzä-idäräçe
+Comment[uk]=Легкий менеджер вікон, заснований на Blackbox
+Comment[uz]=Blackbox asosida yaratilgan oddiy oyna boshqaruvchi
+Comment[uz@cyrillic]=Blackbox асосида яратилган оддий ойна бошқарувчи
+Comment[vi]=Trình quản lý cửa sổ nhỏ gọn dựa trên Blackbox
+Comment[wa]=On ledjir manaedjeu di purneas båzé so Blackbox
+Comment[zh_CN]=基于 BlackBox 的轻量级窗口管理器
+Comment[zh_TW]=一個基於 Blackbox 且輕量化的視窗管理程式
diff --git a/tdm/kfrontend/sessions/oroborus.desktop b/tdm/kfrontend/sessions/oroborus.desktop
new file mode 100644
index 00000000..b7ea37c3
--- /dev/null
+++ b/tdm/kfrontend/sessions/oroborus.desktop
@@ -0,0 +1,76 @@
+[Desktop Entry]
+Type=XSession
+Exec=oroborus
+TryExec=oroborus
+Name=Oroborus
+Name[eo]=Koloroj
+Name[hi]=ऑरोबोरस
+Name[pa]=ਓਰੂਬੋਰੁਸ
+Name[te]=ఒరొబొరస్
+Comment=A lightweight themeable window manager
+Comment[af]='n Lig gewig, tema venster bestuurder
+Comment[ar]=مدير نوافذ خفيف العبء قابل لاستخدام السمات
+Comment[be]=Лёгкі кіраўнік вокнаў з падтрымкай тэмаў
+Comment[bn]=হাল্কা থীমযুক্ত উইণ্ডো ম্যানেজার
+Comment[bs]=Lagani window manager sa podrškom za teme
+Comment[ca]=Un gestor de finestres lleuger i configurable amb temes
+Comment[cs]=Malý správce oken s tématy
+Comment[csb]=Menedżer òknów ò môłëch żądanich, z mòżnotą zmianë wëzdrzatkù
+Comment[cy]=Trefnydd ffenestri ysgafn sy'n defnyddio themau
+Comment[da]=En letvægts vindueshåndtering med temaer
+Comment[de]=Schlanker Fenstermanager mit Designs
+Comment[el]=Ένας ελαφρύς διαχειριστής παραθύρων με υποστήριξη θεμάτων
+Comment[eo]=Fenestroadministrilo
+Comment[es]=Un gestor de ventanas ligero con temas
+Comment[et]=Imeväike teemadega aknahaldur
+Comment[eu]=Temak onartzen dituen leiho kudeatzaile arina
+Comment[fa]=یک مدیر پنجرۀ قابل چهره‌بندی سبک
+Comment[fi]=Kevyt teemoitettava ikkunaohjelma
+Comment[fr]=Un gestionnaire de fenêtres avec gestion des thèmes
+Comment[fy]=In lichtgewicht finstersmanager mei temabehear
+Comment[gl]=Un xestor de fiestras lixeiro e con capacidade para temas
+Comment[he]=מנהל חלונות קל ובר התאמה אישית של ערכות נושא
+Comment[hi]=हल्का, प्रसंगयोग्य विंडो प्रबंधक
+Comment[hr]=Lagani upravitelj prozora s temama
+Comment[hu]=Kis erőforrásigényű ablakkezelő, témázási lehetőséggel
+Comment[is]=Léttur þemanlegur gluggastjóri
+Comment[it]=Un window manager leggero che supporta i temi
+Comment[ja]=テーマ化可能な軽量のウィンドウマネージャ
+Comment[ka]=მსუბუქი ფანჯრის მენეჯერი თემების მხარდაჭერით
+Comment[kk]=Жеңіл, нақыштары бар терезе менеджері
+Comment[km]=កម្មវិធី​គ្រប់គ្រង​បង្អួច​អាច​ប្ដូរ​ស្បែក​បាន តែ​មាន​សមត្ថភាព​ខ្សោយ
+Comment[ko]=가벼운 테마를 설정할 수 있는 창 관리자
+Comment[lt]=Nedaug resursų reikalaujanti temas palaikanti langų tvarkyklė
+Comment[lv]=Viegls logu menedžeris ar tēmu atbalstu
+Comment[mk]=Лесен менаџер на прозорци со теми
+Comment[ms]=Pengurus tetingkap boleh tema ringan
+Comment[mt]=Window manager ħafif u temabbli
+Comment[nb]=En lettvekts vindusbehandler med temaer
+Comment[nds]=En ranke Finsterpleger, kann Mustern bruken
+Comment[ne]=विषयवस्तु योग्य हल्का वजन सञ्झ्याल प्रबन्धक
+Comment[nl]=Een lichtgewicht windowmanager met themabeheer
+Comment[nn]=Ein lett vindaugssjef med tema
+Comment[pa]=ਇੱਕ ਸਰੂਪਾਂ ਨਾਲ ਹਲਕਾ ਝਰੋਖਾ ਮੈਨੇਜਰ
+Comment[pl]=Menedżer okien o małych wymaganiach, z możliwością zmiany wyglądu
+Comment[pt]=Um gestor de janelas leve e com suporte para temas
+Comment[pt_BR]=Um gerenciador de Janelas leve com vários temas
+Comment[ro]=Un manager de ferestre mic și configurabil cu diverse tematici
+Comment[ru]=Лёгкий оконный менеджер, поддерживающий темы
+Comment[rw]=Mugenga dirishya ngirwa-nsanganyamatsiko yoroshye
+Comment[se]=Geahpes lásegieđahalli mas leat fáttát
+Comment[sk]=Nenáročný správca okien s podporou tém
+Comment[sl]=Lahek okenski upravitelj s temami
+Comment[sr]=Лагани менаџер прозора са темама
+Comment[sr@Latn]=Lagani menadžer prozora sa temama
+Comment[sv]=Lättviktig fönsterhanterare med teman
+Comment[ta]=குறைந்தஎடை தலைப்புடைய சாளர மேலாளர்
+Comment[th]=ระบบจัดการหน้าต่างขนาดเบาที่ใช้ชุดตกแต่งได้
+Comment[tr]=Küçük, hafif, temalı bir pencere yöneticisi
+Comment[tt]=Tışlana torğan ciñel täräzä-idäräçe
+Comment[uk]=Легкий менеджер вікон з підтримкою тем
+Comment[vi]=Trình quản lý cửa sổ thay đổi được sắc thái
+Comment[wa]=On ledjir manaedjeu di purneas avou des tinmes
+Comment[zh_CN]=轻量级窗口管理器,可定义主题
+Comment[zh_TW]=一個輕量化且有佈景功能的視窗管理程式
+# not usable as a session
+Hidden=true
diff --git a/tdm/kfrontend/sessions/phluid.desktop b/tdm/kfrontend/sessions/phluid.desktop
new file mode 100644
index 00000000..f1cca1d6
--- /dev/null
+++ b/tdm/kfrontend/sessions/phluid.desktop
@@ -0,0 +1,80 @@
+[Desktop Entry]
+Type=XSession
+Exec=phluid
+TryExec=phluid
+Name=Phluid
+Name[eo]=Plena
+Name[hi]=फ्लुइड
+Name[pa]=ਫਲੁਇਡ
+Name[te]=ఫ్లూయిడ్
+Comment=An Imlib2 based window manager
+Comment[af]='n Imlib2 gebaseerde venster bestuurder
+Comment[ar]=مدير نوافذ مبني على Imlib2
+Comment[be]=Кіраўнік вокнаў, заснаваны на Imlib2
+Comment[bn]=Imlib2 ভিত্তিক উইণ্ডো ম্যানেজার
+Comment[bs]=Window manager baziran na Imlib2
+Comment[ca]=Un gestor de finestres basta en Imlib2
+Comment[cs]=Správce oken založený na Imlib2
+Comment[csb]=Menedżer òknów òpiarti na Imlib2
+Comment[cy]=Trefnydd ffenestri wedi'i seilio ar lmlib2
+Comment[da]=En Imlib2 baseret vindueshåndtering
+Comment[de]=Imlib2-basierter Fenstermanager
+Comment[el]=Ένας διαχειριστής παραθύρων βασισμένος στην imlib2
+Comment[eo]=Fenestroadministrilo
+Comment[es]=Un gestor de ventanas basado en Imlib2
+Comment[et]=Aknahaldur, mille aluseks on Imlib2
+Comment[eu]=Imlib2-n oinarritutako leiho kudeatzailea
+Comment[fa]=یک Imlib2 بر اساس مدیر پنجره
+Comment[fi]=Imlib2-pohjainen ikkunaohjelma
+Comment[fr]=Un gestionnaire de fenêtres fondé sur Imlib2
+Comment[fy]=In op imlib2 basearre finstersmanager
+Comment[ga]=Bainisteoir fuinneoga bunaithe ar Imlib2
+Comment[gl]=Un xestor de fiestras baseado en Imlib2
+Comment[he]=מנהל חלונות מבוסס Imlib2
+Comment[hi]=आईएमलिब2 आधारित विंडो प्रबंधक
+Comment[hr]=Upravitelj prozora zasnovan na Imlib2
+Comment[hu]=Egy Imlib2-alapú ablakkezelő
+Comment[is]=Gluggastjóri sem notar Imlib2
+Comment[it]=Un window manager basato su Imlib2
+Comment[ja]=Imlib2ベースのウィンドウマネージャ
+Comment[ka]=ფანჯრის მენეჯერი imlib2 ის ბაზაზე
+Comment[kk]=Imlib2-негіздеген терезе менеджері
+Comment[km]=កម្មវិធី​គ្រប់គ្រង​បង្អួច​ផ្អែក​លើ Imlib2
+Comment[ko]=Imlib2 기반 창 관리자
+Comment[lt]=Langų tvarkyklė, paremta Imlib2
+Comment[lv]=Imlib 2 bāzēts logu menedžeris
+Comment[mk]=Менаџер на прозорци базиран на Imlib2
+Comment[mn]=Imlib2 дээр суурилсан цонхны удирдагч
+Comment[ms]=Pengurus tetingkap berasaskan lmlib2
+Comment[mt]=Window manager ibbażat fuq Imlib2
+Comment[nb]=En vindusbehandler basert på Imlib2
+Comment[nds]=En Finsterpleger opbuut op Imlib2
+Comment[ne]=Imlib2 मा आधारित सञ्झ्याल प्रबन्धक
+Comment[nl]=Een op imlib2 gebaseerde windowmanager
+Comment[nn]=Ein vindaugssjef basert på Imlib2
+Comment[pa]=ਇੱਕ Imlib2 ਆਧਾਰਿਤ ਫਾਇਲ਼ ਮੈਨੇਜਰ
+Comment[pl]=Menedżer okien oparty na Imlib2
+Comment[pt]=Um gestor de janelas baseado na Imlib2
+Comment[pt_BR]=Um gerenciador de janelas baseado na lmlib2
+Comment[ro]=Un manager de ferestre bazat pe Imlib2
+Comment[ru]=Оконный менеджер на основе imlib2
+Comment[rw]=Mugenga dirishya ishingiye kuri Imlib2
+Comment[se]=Imlib2-vuođđoduvvon lásegieđahalli
+Comment[sk]=Správca okien založený na imlib2
+Comment[sl]=Okenski upravitelj na osnovi lmlib2
+Comment[sr]=Менаџер прозора заснован на Imlib2
+Comment[sr@Latn]=Menadžer prozora zasnovan na Imlib2
+Comment[sv]=Imlib2-baserad fönsterhanterare
+Comment[ta]=சாளர மேலாளர் அடிப்படையிலான ஒரு Imlib2
+Comment[te]=ఐఎంలిబ్2 ఆధారిత విండొ అభికర్త
+Comment[tg]=Imlib2 ба асосимудири тиреза
+Comment[th]=ระบบจัดการหน้าต่างที่สร้างบน Imlib2
+Comment[tr]=Imlib2 tabanlı bir pencere yöneticisi
+Comment[tt]=Imlib2 asılında täräzä-idäräçe
+Comment[uk]=Менеджер вікон, заснований на Imlib2
+Comment[uz]=Imlib2 asosida yaratilgan oyna boshqaruvchi
+Comment[uz@cyrillic]=Imlib2 асосида яратилган ойна бошқарувчи
+Comment[vi]=Trình quản lý cửa sổ dựa trên lmlib2
+Comment[wa]=On manaedjeu di purneas båzé so lmlib2
+Comment[zh_CN]=基于 Imlib2 的窗口管理器
+Comment[zh_TW]=一個基於 Imlib2 的視窗管理程式
diff --git a/tdm/kfrontend/sessions/pwm.desktop b/tdm/kfrontend/sessions/pwm.desktop
new file mode 100644
index 00000000..5d967c0c
--- /dev/null
+++ b/tdm/kfrontend/sessions/pwm.desktop
@@ -0,0 +1,72 @@
+[Desktop Entry]
+Type=XSession
+Exec=pwm1
+TryExec=pwm1
+Name=PWM
+Name[eo]=UnuFA
+Name[hi]=पीडबल्यूएम
+Name[te]=పి డబ్ల్యు ఎం
+Name[th]=ตัวจัดการหน้าต่าง PWM
+Comment=A lightweight window manager able to attach multiple windows to one frame
+Comment[af]='n Lig gewig venster bestuurder wat veelvuldige vensters aan een raam kan koppel
+Comment[ar]=مدير نوافذ خفيف العبء قابل لربط عدة نوافذ إلى إطار واحد
+Comment[be]=Лёгкі кіраўнік вокнаў, які можа далучаць некалькі вокнаў да аднаго фрэйма
+Comment[bn]=একটি হাল্কা উইণ্ডো ম্যানেজার, যাতে একটি ফ্রেমে একাধিক উইণ্ডো সংযুক্ত করা সম্ভব
+Comment[bs]=Lagani window manager koji može prikačiti više prozora na jedan okvir
+Comment[ca]=Un lleuger gestor de finestres capaç d'aplegar múltiples finestres en un marc
+Comment[csb]=Menedżer òknów ò môłëch żądaniach, rozmiejący doczepic wiele òknów do jedny ramë
+Comment[cy]=Trefnydd ffenestri ysgafn sy'n gallu atodi mwy nag un ffenestr at un ffrâm
+Comment[da]=En letvægts vindueshåndtering der kan knytte flere vinduer til én ramme
+Comment[de]=Schlanker Fenstermanager, der mehrere Fenster an einen Rahmen andocken kann
+Comment[el]=Ένας ελαφρύς διαχειριστής παραθύρων με δυνατότητα να προσαρτά πολλαπλά παράθυρα σε ένα πλαίσιο
+Comment[eo]=Fenestroadministrilo, kiu faras unun fenestron el kelkaj
+Comment[es]=Un gestor de ventanas ligero capaz de conectar varias ventanas a un mismo marco
+Comment[et]=Imeväike aknahaldur, mis suudab mitu akent ühe raami külge haakida
+Comment[eu]=Hainbat leiho marko bakarrean uztar ditzakeen leiho kudeatzaile arina
+Comment[fa]=مدیر پنجرۀ سبک قادر به پیوست پنجره‌های چندگانه در یک قابک
+Comment[fi]=Kevyt ikkunaohjelma, joka osaa liittää useita ikkunoita yhteen kehykseen
+Comment[fr]=Un gestionnaire de fenêtres léger capable d'attacher plusieurs fenêtres à un même cadre
+Comment[fy]=In lichtgewicht finstersmanager, hokker meardere finsters kin ferbine mei in kader
+Comment[gl]=Un xestor de fiestras lixeiro capaz de adxuntar varias fiestras nun marco
+Comment[he]=מנהל חלונות קל המסוגל לחבר חלונות רבים למסגרת אחת
+Comment[hi]=एक हल्का विंडो प्रबंधक जिसके एक फ़रमा में अनेक विंडो जोड़े जा सकते हैं
+Comment[hr]=Lagani upravitelj prozora koji jednom okviru može pridodati više prozora
+Comment[hu]=Alacsony erőforrásigényű ablakkezelő, több ablakot képes egy kerethez rendelni
+Comment[is]=Léttur gluggastjóri sem getur tengt marga glugga við einn ramma
+Comment[it]=Un window manager leggero in grado di attaccare più finestre ad una cornice
+Comment[ja]=複数のウィンドウ枠を設定可能な軽量なウィンドウマネージャ
+Comment[ka]=მსუბუქი ფანჯრის მენეჯერი, რომელსაც შეუძლია ბევრი ფანჯრის ერთ ჩარჩოში ჩასმა
+Comment[kk]=Жеңіл, бір коршауда бірнеше терезелерді біріктірелетін, терезе менеджері
+Comment[km]=កម្មវិធី​គ្រប់គ្រង​បង្អួច​សមត្ថភាព​ខ្សោយ អាច​ភ្ជាប់​បង្អួច​ច្រើន​ទៅ​ស៊ុម​មួយ
+Comment[lt]=Nedaug resursų reikalaujanti langų tvarkyklė, galinti prijungti daug langų prie vieno rėmo
+Comment[lv]=Viegls logu menedžeris ar iespēju pievienot vairākus logus vienam kadram
+Comment[mk]=Лесен менаџер на прозорци кој може да прикачи повеќе прозорци на една рамка
+Comment[ms]=Pengurus tetingkap ringan yang boleh melekapkan berbilang tetingkap pada satu bingkai
+Comment[mt]=Window manager ħafif li jista' jgħaqqad iżjed minn window waħda fl-istess gwarniċ
+Comment[nb]=En lettvekts vindusbehandler som kan koble flere vinduer til én ramme
+Comment[nds]=En ranke Finsterpleger, de mennige Finstern an een Rahmen andocken kann
+Comment[ne]=एक हल्का वजन सञ्झ्याल प्रबन्धकले बहुभागिय सञ्झ्यालहरूलाई एक फ्रेममा सङ्लग्न गर्न सक्छ
+Comment[nl]=Een lichtgewicht windowmanager, welke meerdere vensters kan verbinden met een frame
+Comment[nn]=Ein lett vindaugssjef som kan kopla fleire vindauge til den same ramma
+Comment[pa]=ਇੱਕ ਹਲਕਾ ਝਰੋਖਾ ਮੈਨੇਜਰ, ਜੋ ਕਿ ਕਈ ਝਰੋਖਿਆਂ ਨੂੰ ਇੱਕ ਫਰੇਮ ਵਿੱਚ ਰੱਖ ਸਕਦਾ ਹੈ
+Comment[pl]=Menedżer okien o małych wymaganiach, potrafiący doczepić wiele okien do jednego obramowania
+Comment[pt]=Um gestor de janelas leve, com a possibilidade de anexar várias janelas a uma área
+Comment[pt_BR]=Um gerenciador de janelas leve, capaz de anexar múltiplas janelas em um quadro
+Comment[ro]=Un manager de ferestre minimal capabil să atașeze multe ferestre la un singur cadru
+Comment[ru]=Лёгкий оконный менеджер, способный объединить несколько окон в одной рамке
+Comment[rw]=Mugenga dirishya yoroshye ishobora gufatishya amadirishya menshi ku ikadiri imwe.
+Comment[se]=Geahpes lásegieđahalli mii sáhttá ovttastahttit máŋga láse seamma rámmii.
+Comment[sk]=Nenáročný správca okien schopný spojiť viac okien do jednoho rámca
+Comment[sl]=Lahek okenski upravitelj, ki lahko pripne več oken na en okvir
+Comment[sr]=Лагани менаџер прозора способан да прикачи више прозора за један оквир
+Comment[sr@Latn]=Lagani menadžer prozora sposoban da prikači više prozora za jedan okvir
+Comment[sv]=Lättviktig fönsterhanterare som kan ansluta flera fönster till en ram
+Comment[ta]=குறைந்த கனமுள்ள பல சாளரங்களை இணைக்க முடிந்த ஒற்றை சாளர மேலாளர்
+Comment[th]=ระบบจัดการหน้าต่างขนาดเบา มีความสามารถในการปะติดหลายๆหน้าต่างลงใน 1 กรอบ
+Comment[tr]=Düşük ağırlıklı bir çok pencereyi bir çerçeveye toplayabilen bir pencere yöneticisi
+Comment[tt]=Ber qısa eçendä berniçä täräzä totaştırala torğan täräzä-idäräçe
+Comment[uk]=Простий менеджер вікон, що дозволяє долучати декілька вікон до однієї рамки
+Comment[vi]=Trình quản lý cửa sổ nhỏ gọn, có thể gắn nhiều cửa sổ vào một khung
+Comment[wa]=On ledjir manaedjeu di purneas ki pout ataetchî sacwants purneas so-z on cåde
+Comment[zh_CN]=轻量级窗口管理器,可将多个窗口附加到一个框架中
+Comment[zh_TW]=一個輕量化且可以將多個視窗結合在一起的視窗管理程式
diff --git a/tdm/kfrontend/sessions/qvwm.desktop b/tdm/kfrontend/sessions/qvwm.desktop
new file mode 100644
index 00000000..922e3e0b
--- /dev/null
+++ b/tdm/kfrontend/sessions/qvwm.desktop
@@ -0,0 +1,80 @@
+[Desktop Entry]
+Type=XSession
+Exec=qvwm
+TryExec=qvwm
+Name=QVWM
+Name[eo]=QVFA
+Name[hi]=क्यूवीडबल्यूएम
+Name[te]=క్యు వి డబ్ల్యు ఎం
+Name[th]=ตัวจัดการหน้าต่าง QVWM
+Comment=A Windows 95 like window manager
+Comment[af]='n Venster bestuurder wat soos Windows 95 lyk
+Comment[ar]=مدير نوافذ شبيه بويندوز 95
+Comment[be]=Кіраўнік вокнаў, падобны на Windows 95
+Comment[bn]=Windows 95-এর অনুরূপ একটি উইণ্ডো ম্যানেজার
+Comment[bs]=Window manager nalik na Windows 95
+Comment[ca]=Un gestor de finestres com el Windows 95
+Comment[cs]=Správce oken se vzhledem Windows 95
+Comment[csb]=Menedżer òknów o wëzdrzatkù szlachùjącym za Windows 95
+Comment[cy]=Trefnydd Ffenestri sy'n debyg i Windows95
+Comment[da]=En Windows 95-lignende vindueshåndtering
+Comment[de]=Fenstermanager im Stil von Windows 95
+Comment[el]=Ένας διαχειριστής παραθύρων παρόμοιος με τα Windows 95
+Comment[eo]=Fenestroadministrilo kiel Vindozo 95
+Comment[es]=Un gestor de ventanas similar a Windows 95
+Comment[et]=Aknahaldur, mis näeb välja nagu Windows 95
+Comment[eu]=Windows 95en itxura duen leiho kudeatzailea
+Comment[fa]=یک مدیر پنجره شبیه ویندوز ۹۵
+Comment[fi]=Windows 95:n tyylinen ikkunaohjelma
+Comment[fr]=Un gestionnaire de fenêtres semblable à Windows 95
+Comment[fy]=In Win95-likens finstersmanager
+Comment[ga]=Bainisteoir fuinneoga cosúil le Windows 95
+Comment[gl]=Un xestor de fiestras como o de Windows 95
+Comment[he]=מנהל חלונות הדומה לחלונות 95
+Comment[hi]=विंडोज़ 95 जैसा विंडो प्रबंधक
+Comment[hr]=Upravitelj prozora nalik na Windows 95
+Comment[hu]=Egy Windows 95-szerű ablakkezelő
+Comment[is]=Gluggastjóri sem líkist Windows 95
+Comment[it]=Un window manager in stile Windows 95
+Comment[ja]=Windows95 風のウィンドウマネージャ
+Comment[ka]=ფანჯრის მენეჯერი Windows 95-ს სტილში
+Comment[kk]=Windows 95 секілді терезе менеджері
+Comment[km]=កម្មវិធី​គ្រប់គ្រង​បង្អួច​ស្រដៀង Windows 95
+Comment[ko]=윈도 95를 닮은 창 관리자
+Comment[lt]=Langų tvarkyklė, primenanti Windows 95
+Comment[lv]=Windows 95 līdzīgs logu menedžeris
+Comment[mk]=Менаџер на прозорци со изглед на Windows 95
+Comment[mn]=Виндовс 95 шиг цонхны удирдагч
+Comment[ms]=Pengurus tetingkap seperti Windows 95
+Comment[mt]=Window manager jixbaħ lil Windows95
+Comment[nb]=En vindusbehandler som likner Windows 95
+Comment[nds]=En Finsterpleger liek to Windows 95
+Comment[ne]=विण्डोज ९५ जस्तो सञ्झ्याल प्रबन्धक
+Comment[nl]=Een Win95-achtige windowmanager
+Comment[nn]=Ein vindaugssjef som liknar Windows 95
+Comment[pa]=ਇੱਕ ਵਿੰਡੋ 95 ਵਰਗਾ ਝਰੋਖਾ ਮੈਨੇਜਰ
+Comment[pl]=Menedżer okien o wyglądzie podobnym do Windows 95
+Comment[pt]=Um gestor de janelas com o visual do Windows 95
+Comment[pt_BR]=Um gerenciador de janelas parecido com o Windows 95
+Comment[ro]=Un manager de ferestre cu aspect de Windows 95
+Comment[ru]=Оконный менеджер в стиле Windows 95
+Comment[rw]=Windows 95 nka mugenga dirishya
+Comment[se]=Windows95-lágan lásegieđahalli
+Comment[sk]=Správca okien podobný Windows 95
+Comment[sl]=Okenski upravitelj, podoben Windows 95
+Comment[sr]=Менаџер прозора налик на Windows 95
+Comment[sr@Latn]=Menadžer prozora nalik na Windows 95
+Comment[sv]=Fönsterhanterare som liknar Windows 95
+Comment[ta]=சாளர மேலாளர் போன்ற விண்டோஸ் 95
+Comment[te]=విండొస్ 95 లాంటి విండొ అభికర్త
+Comment[tg]=Windows 95 монанди мудири тиреза
+Comment[th]=ระบบจัดการหน้าต่างที่ดูคล้ายวินโดวส์ 95
+Comment[tr]=Windows 95 benzeri bir pencere yöneticisi
+Comment[tt]=Windows 95 kebek täräzä-idäräçe
+Comment[uk]=Менеджер вікон на кшталт Windows95
+Comment[uz]=Win95'ga oʻxshagan oyna boshqaruvchi
+Comment[uz@cyrillic]=Win95'га ўхшаган ойна бошқарувчи
+Comment[vi]=Trình quản lý cửa sổ giống Windows 95
+Comment[wa]=On manaedjeu di purneas rishonnant a Windows 95
+Comment[zh_CN]=类似 Windows 95 的窗口管理器
+Comment[zh_TW]=一個像 Win95 的視窗管理程式
diff --git a/tdm/kfrontend/sessions/ratpoison.desktop b/tdm/kfrontend/sessions/ratpoison.desktop
new file mode 100644
index 00000000..1127db15
--- /dev/null
+++ b/tdm/kfrontend/sessions/ratpoison.desktop
@@ -0,0 +1,82 @@
+[Desktop Entry]
+Type=XSession
+Exec=ratpoison
+TryExec=ratpoison
+Name=Ratpoison
+Name[bn]=র‌্যাট-পয়সন
+Name[cy]=Gwenwynllygodmawr (Ratpoison)
+Name[eo]=Raticido
+Name[fa]=مرگ موش
+Name[hi]=रैट-पॉइज़न
+Name[ne]=र्याटपोइजन
+Name[pa]=ਰਾਟਪੋਈਸਾਨ
+Name[rw]=UburoziImbeba
+Name[sv]=Råttgift
+Name[ta]=ராட் பாய்சன்
+Name[te]=ఎలుకలమందు
+Name[vi]=Bả chuột
+Name[wa]=Pwezon po les rats (Ratpoison)
+Comment=A simple keyboard-only window manager modeled after Screen
+Comment[af]='n Eenvoudige venster bestuurder wat net met die sleutel bord werk en op Screen gemoduleer is.
+Comment[ar]=مدير نوافذ بسيط يستخدم لوحة المفاتيح فقط صنع مشابهاً لـScreen
+Comment[be]=Просты кіраўнік вокнаў, працуе толькі з клавіятурай
+Comment[bn]=একটি সরল কীবোর্ড-ভিত্তিক উইণ্ডো ম্যানেজার, Screen-এর আদর্শে তৈরি
+Comment[bs]=Jednostavan windows manager samo za tastaturu, modeliran po uzoru na Screen
+Comment[ca]=Un gestor de finestres simple de sols teclat modelat després de Screen
+Comment[csb]=Prosti menedżer òknów òbsłùgiwôny blós z klawiaturë, szlachùje za programą screen
+Comment[cy]=Trefnydd ffenestri syml sy'n defnyddio'r allweddell yn unig, wedi'i arddullio ar Sgrîn (Screen)
+Comment[da]=En simpel kun-tastatur vindueshåndtering modeleret efter Screen
+Comment[de]=Einfacher Fenstermanager, der nur über die Tastatur bedient wird und Screen nachgebildet ist
+Comment[el]=Ένας απλός, μονό για πληκτρολόγιο, διαχειριστής παραθύρων σχεδιασμένος με βάση το Screen
+Comment[en_GB]=A simple keyboard-only window manager modelled after Screen
+Comment[eo]=Fenestroadministrilo por klaviaro
+Comment[es]=Un gestor de ventanas sólo para teclado realizado a partir de Screen
+Comment[et]=Lihtne ainult klaviatuuri abil kasutatav aknahaldur, mille eeskujuks on Screen
+Comment[eu]=Screen-en oinarriturik egindako leiho kudeatzailea, teklatu hutsez erabiltzekoa
+Comment[fa]=یک مدیر پنجره فقط صفحه کلید سادۀ مدل‌یافته پس از پرده
+Comment[fi]=Yksinkertainen, vain näppäimistöltä käytettävä ikkunamanageri, screen-ohjelman tyyliin
+Comment[fr]=Un gestionnaire de fenêtres simple uniquement dirigeable au clavier et fondé sur Screen
+Comment[fy]=In ienfâldige finstersmanager dy allinnich mei it toetseboerd te betsjinnen is, ynspiraasje troch Screen
+Comment[gl]=Un xestor de fiestras de manexo co teclado modelado despois de Screen
+Comment[he]=מנהל חלונות פשוט למקלדת בלבד המעוצב בסגנון Screen
+Comment[hi]=आफ्टर स्क्रीन आधारित साधारण विंडो प्रबंधक जो सिर्फ कुंजीपट के लिए है
+Comment[hr]=Jednostavan, samo za tipkovnicu, upravitelj prozora napravljen prema Screenu
+Comment[hu]=Egyszerű, csak billentyűzetről vezérelhető ablakkezelő (a Screen alapján)
+Comment[is]=Einfaldur gluggastjóri sem notar eingöngu lyklaborðið hannaður eftir Screen forritinu
+Comment[it]=Un window manager semplice solo-tastiera pensato come Screen
+Comment[ja]=Screen をもとに作られた、キーボードインターフェースのみのウィンドウマネージャ
+Comment[ka]=მარტივი კლაიატურით მართვადი ფანჯრის მმართველი
+Comment[kk]=Screen үлгідегі, тек перенетақтадан басқарылатын, қарапайым терезе менеджері
+Comment[km]=កម្មវិធី​គ្រប់គ្រង​បង្អួច​សាមញ្ញ​ប្រើ​តែ​ក្ដារចុច ដែល​យក​គំរូ​តាម​អេក្រង់
+Comment[lt]=Paprasta, tik klaviatūra valdoma langų tvarkyklė, panaši į Screen
+Comment[lv]=Vienkāršs tikai tastatūras logu menedžeris, līdzīgs Screen
+Comment[mk]=Едноставен менаџер на прозорци кој работи само со тастатура, моделиран според Screen
+Comment[ms]=Pengurus tetingkap hanya papan kekunci ringkas dimodelkan seperti Skrin
+Comment[mt]=Window manager għal tastieri biss immudellat fuq Screen
+Comment[nb]=En enkel tastaturbasert vindusbehandler, etter forbilde av Screen
+Comment[nds]=En eenfache Finsterpleger, de bloots mit de Tastatuur bruukt warrt. Screen weer dat Modell dorför
+Comment[ne]=पर्दा पछाडि सञ्झ्याल प्रबन्धक मात्र नमूना बनाउने साधारण कुञ्जीपाटी
+Comment[nl]=Een eenvoudige windowmanager die alleen met het toetsenbord te bedienen is, geïnspireerd door Screen
+Comment[nn]=Ein enkel tastaturbasert vindaugssjef, med Screen som førebilete
+Comment[pa]=ਪਰਦੇ ਮੈਡੀਊਲ ਬਾਅਦ ਸਿਰਫ ਕੀ-ਬੋਰਡ ਤੇ ਆਧਾਰਿਤ ਝਰੋਖਾ ਮੈਨੇਜਰ
+Comment[pl]=Prosty menedżer okien obsługiwany wyłącznie za pomocą klawiatury, stworzony na podobieństwo programu screen
+Comment[pt]=Um gestor de janelas simples, só para o teclado e modelado sobre o Screen
+Comment[pt_BR]=Um simples gerenciador de janelas baseado somente em teclado, modelado após a tela
+Comment[ro]=Un manager de ferestre manipulat din tastatură, modelat după Screen
+Comment[ru]=Простой клавиатурный оконный менеджер, моделирующий Screen
+Comment[rw]=Mugenga dirishya ya mwandikisho-gusa yoroheje itunganyijwe nyuma ya Mugaragaza
+Comment[se]=Oktageardánis, boallobeavdestivrejuvvon lásegieđahalli, mas lea Screen ovdagovvan
+Comment[sk]=Jednoduchý správca okien ovládaný iba klávesami podľa programu Screen
+Comment[sl]=Preprost okenski uporavljalnik na osnovi Screen, upravlja se samo s tipkovnico
+Comment[sr]=Једноставан, само за тастатуру менаџер прозора, направљен према Screen-у
+Comment[sr@Latn]=Jednostavan, samo za tastaturu menadžer prozora, napravljen prema Screen-u
+Comment[sv]=Enkel fönsterhanterare bara för tangentbord modellerad efter Screen
+Comment[ta]=சாளரமொன்றில் நிழல் ஏறுகிறது
+Comment[th]=ตัวจัดการหน้าต่างแบบเรียบง่าย ใช้แป้นพิมพ์ควบคุมได้อย่างเดียว ถูกสร้างขึ้นมาตามหลัง Screen
+Comment[tr]=Screen'den sonra modellenmiş salt klavye basit pencere yöneticisi
+Comment[tt]=Töylekle genä ciñel täräzä-idäräçe
+Comment[uk]=Простий менеджер вікон, розроблений на базі Screen, з підтримкою тільки клавіатури
+Comment[vi]=Trình quản lý cửa sổ chỉ dùng bàn phím, dựa theo Screen
+Comment[wa]=On simpe manaedjeu di purneas eployant fok li taprece, båzé so ls idêyes da «Screen»
+Comment[zh_CN]=Screen 后又一只支持键盘的窗口管理器
+Comment[zh_TW]=一個簡易、只支援鍵盤的視窗管理程式
diff --git a/tdm/kfrontend/sessions/sapphire.desktop b/tdm/kfrontend/sessions/sapphire.desktop
new file mode 100644
index 00000000..5cdd998d
--- /dev/null
+++ b/tdm/kfrontend/sessions/sapphire.desktop
@@ -0,0 +1,84 @@
+[Desktop Entry]
+Type=XSession
+Exec=sapphire
+TryExec=sapphire
+Name=Sapphire
+Name[bn]=স্যাফায়ার
+Name[eo]=Safiro
+Name[fa]=ياقوت كبود
+Name[hi]=सेफायर
+Name[ka]=საფირონი
+Name[ne]=नीलमणि
+Name[pa]=ਸਾਪਰਫੀਰੀ
+Name[ru]=Сапфир
+Name[ta]=சபையர்
+Name[te]=ఇంద్రనీలం
+Name[tg]=Ёқути кабуд
+Comment=A minimal but configurable window manager
+Comment[af]='n Minimalistiese venster bestuurder, wat nogsteeds opstel funksionaliteit bevat.
+Comment[ar]=مدير نوافذ مصغّر ولكن قابل للإعداد
+Comment[be]=Мінімалістычны кіраўнік вокнаў з магчымасцю настаўлення
+Comment[bn]=পরিমিত কিন্তু থীমযুক্ত উইণ্ডো ম্যানেজার
+Comment[bs]=Minimalan ali podesiv window manager
+Comment[ca]=Un minimalista però configurable gestor de finestres
+Comment[cs]=Minimalistický, ale přizpůsobitelný správce oken
+Comment[csb]=Prosti menedżer òknów, równak z mòżnotą kònfigùracëji
+Comment[cy]=Trefnydd ffenestri lleiafol a ffurfweddir
+Comment[da]=En minimal men indstillelig vindueshåndtering
+Comment[de]=Minimalistischer, aber anpassbarer Fenstermanager
+Comment[el]=Ένας μικρός αλλά παραμετροποιήσιμος διαχειριστής παραθύρων
+Comment[eo]=Fenestroadministrilo
+Comment[es]=Un gestor de ventanas minimalista pero configurable
+Comment[et]=Väga väike, kuid seadistatav aknahaldur
+Comment[eu]=Leiho kudeatzaile minimal baina konfiguragarria
+Comment[fa]=یک مدیر پنجرۀ کمینه، اما قابل پیکربندی
+Comment[fi]=Minimaalinen, mutta muokattavissa oleva ikkunaohjelma
+Comment[fr]=Un gestionnaire de fenêtres minimaliste mais configurable
+Comment[fy]=In minimale mar ynstelbere finstersmanager
+Comment[gl]=Un xestor de fiestras mínimo pero configurábel
+Comment[he]=מנהל חלונות מינימלי אך ניתן להגדרה
+Comment[hi]=एक अल्पतम परंतु कॉन्फ़िगर योग्य विंडो प्रबंधक
+Comment[hr]=Minimalan, ali podesiv upravitelj prozora
+Comment[hu]=Egyszerű, de jól konfigurálható ablakkezelő
+Comment[is]=Einfaldur en stillanlegur gluggastjóri
+Comment[it]=Un window manager minimale ma configurabile
+Comment[ja]=各種設定が可能な小さなウィンドウマネージャ
+Comment[ka]=მინიმალური მაგრამ კონფიგურირებადი ფანჯრის მენეჯერი
+Comment[kk]=Шағын, баптауы бар, терезе менеджері
+Comment[km]=កម្មវិធី​គ្រប់គ្រង​បង្អួច​តូច តែ​អាច​កំណត់​រចនាសម្ព័ន្ធ​បាន
+Comment[ko]=설정 가능한 최소한의 창 관리자
+Comment[lt]=Minimalistinė tačiau konfigūruojama langų tvarkyklė
+Comment[lv]=Minimālistisks, bet konfigurējams logu menedžeris
+Comment[mk]=Минимален но конфигурабилен менаџер на прозорци
+Comment[mn]=Маш жижиг тохируулах боломжгүй цонх удирдагч
+Comment[ms]=Pengurus tetingkap minimum tetapi boleh konfigur
+Comment[mt]=Window manager minimu imma konfigurabbli
+Comment[nb]=En minimal vindusbehandler, men med innstillinger
+Comment[nds]=En minimaal, man instellbor Finsterpleger
+Comment[ne]=सानो तर कन्फिगर गर्न सकिने सञ्झ्याल प्रबन्धक
+Comment[nl]=Een minimale maar instelbare windowmanager
+Comment[nn]=Ein minimal vindaugssjef, men med innstillingar
+Comment[pa]=ਇੱਕ ਨਿਊਨਤਮ, ਪਰ ਸੋਧਯੋਗ ਝਰੋਖਾ ਮੈਨੇਜਰ
+Comment[pl]=Prosty menedżer okien, ale z możliwością konfiguracji
+Comment[pt]=Um gestor de janelas configurável mas mínimo
+Comment[pt_BR]=Um gerenciador de janelas mínimo, mas configurável
+Comment[ro]=Un manager de ferestre minimal, dar configurabil
+Comment[ru]=Минимальный, но настраиваемый оконный менеджер
+Comment[rw]=Ntoya ariko mugenga dirishya ibonezwa
+Comment[se]=Unna, muhto heivehahtti lásegieđahalli
+Comment[sk]=Minimálny, ale nastaviteľný správca okien
+Comment[sl]=Skromen, a nastavljiv okenski upravitelj
+Comment[sr]=Минимални, али подесиви менаџер прозора
+Comment[sr@Latn]=Minimalni, ali podesivi menadžer prozora
+Comment[sv]=Minimal men anpassningsbar fönsterhanterare
+Comment[ta]=சாளர மேலாளரின் மேம்பட்ட திறன்களை வடிவமைக்கலாம்
+Comment[th]=ระบบจัดการหน้าต่างขนาดเล็ก แต่สามารถปรับแต่งได้
+Comment[tr]=Küçük, ancak kolayca özelleştirilebilir bir pencere yöneticisi
+Comment[tt]=Ciñel bulsa da, köylänä torğan täräzä-idäräçe
+Comment[uk]=Мінімальний менеджер вікон з можливістю налаштування
+Comment[uz]=Oddiy, ammo moslab boʻladigan oyna boshqaruvchi
+Comment[uz@cyrillic]=Оддий, аммо мослаб бўладиган ойна бошқарувчи
+Comment[vi]=Trình quản lý cửa sổ tối thiểu, nhưng có thể cấu hình được
+Comment[wa]=On ptit, nén apontiåve, manaedjeu di purnea
+Comment[zh_CN]=很小却可配置的窗口管理器
+Comment[zh_TW]=一個小但可組態的視窗管理程式
diff --git a/tdm/kfrontend/sessions/sawfish.desktop b/tdm/kfrontend/sessions/sawfish.desktop
new file mode 100644
index 00000000..668620ff
--- /dev/null
+++ b/tdm/kfrontend/sessions/sawfish.desktop
@@ -0,0 +1,74 @@
+[Desktop Entry]
+Type=XSession
+Exec=sawfish
+TryExec=sawfish
+Name=Sawfish
+Name[bn]=স-ফিশ
+Name[eo]=Segfiŝo
+Name[fa]=اره‌ماهی
+Name[hi]=सा-फिश
+Name[ne]=सफीस
+Name[pa]=ਸ਼ਾਅਫਿਸ਼
+Name[te]=సాఫిష్
+Comment=An extensible window manager scriptable with an Emacs Lisp-like language
+Comment[af]='n Uitbreibare venster bestuurder met 'n ingeboude skrip taal wat soos Emacs List lyk.
+Comment[ar]=مدير نوافذ قابل للتوسعة يمكن بشفيره بلغة إيماكس ليسب
+Comment[be]=Кіраўнік вокнаў з магчымасцю пашырэння сцэнарамі на мове, падобнай на Emacs Lisp
+Comment[bs]=Proširiv window manager sa podškom za skriptiranje u jeziku sličnom Emacs Lisp-u
+Comment[ca]=Un extensible gestor de finestres mitjançant scripts amb una aparença com el Lisp de Emacs
+Comment[cs]=Rožšiřitelný správce oken skriptovatelný jazykem podobným jazyku Emacs Lisp
+Comment[csb]=Menedżer òknów, jaczi je mòżno rozbùdowac dzãka skriptom w jãzëkù szlachùjącym za Emacs Lisp
+Comment[cy]=Trefnydd ffenestri estynadwy a all ei sgriptio efo iaith sy'n debyg i Emacs Lisp
+Comment[da]=En udvidelig vindueshåndtering der kan scriptes med et Emacs Lisp-lignende sprog
+Comment[de]=Erweiterbarer Fenstermanager, der über Skripts ähnlich Emacs-Lisp gesteuert werden kann
+Comment[el]=Ένας επεκτάσιμος διαχειριστής παραθύρων παραμετροποιήσιμος με μια γλώσσα παρόμοια με την Emacs Lisp
+Comment[eo]=Fenestroadministrilo, kiu uzas Lispon por esti programata
+Comment[es]=Un gestor de ventanas extensible con guiones escritos en un lenguaje similar a Lisp de Emacs
+Comment[et]=Laiendatav aknahaldur, mis kasutab Emacs Lispi keele moodi skripte
+Comment[eu]=Emacs Lisp bezalako hizkuntza batez idatziriko scripten bidez heda daitekeen leiho kudeatzailea
+Comment[fa]=مدیر پنجرۀ توسعه‌پذیر دست‌نوشته‌ای با یک زبان شبیه Emacs Lisp
+Comment[fi]=Laajennettavissa oleva ikkunaohjelma, johon voi luoda komentosarjoja Emacs lispin tyylisellä kielellä
+Comment[fr]=Un gestionnaire de fenêtres extensible, à l'aide scripts dans un langage semblable au Lisp d'Emacs
+Comment[fy]=In útbreidbere finstersmanager, skriptber fia in Emacs Lisp-likene taal
+Comment[gl]=Un xestor de fiestras extensíbel e configurábel con scripts en linguaxe Emacs Lisp
+Comment[he]=מנהל חלונות מקיף הניתן לתכנות עם שפה דמוית Emacs Lisp
+Comment[hi]=ई-मेक्स लिस्प जैसे भाषा में स्क्रिप्ट किया जा सकने लायक विंडो प्रबंधक जिसे विस्तार दिया जा सकता है
+Comment[hr]=Proširivi upravitelj prozora pisan u skripti nalik na jezik Emacs Lisp
+Comment[hu]=Egy könnyen tovább bővíthető ablakkezelő, egy Emacs Lisp-szerű nyelvvel szkriptelhető
+Comment[is]=Viðbætanlegur gluggastjóri sem er skriftanlegur á Emacs Lisp líku máli
+Comment[it]=Un window manager estensibile per cui è possibile fare script in un linguaggio simile all'Emacs lisp
+Comment[ja]=Emacs Lisp 言語スクリプトで機能拡張可能なウィンドウマネージャ
+Comment[ka]=Lisp სკრიპტებით გაფათოვებადი Emacs ის მაგვარი ფანჯრის მენეჯერი
+Comment[kk]=Emacs Lisp-секілді тілдегі скриптті қолданып, кеңейтілетін терезе менеджері
+Comment[km]=កម្មវិធី​គ្រប់គ្រង​បង្អួច​ដែល​អាច​ពង្រីក​បាន ហើយ​អាច​សរសេរ​ស្គ្រីប​ជាមួយ​ភាសា​ដែល​ដូច Emacs Lisp
+Comment[lt]=Langų tvarkyklė, kurią galima išplėsti Emacs Lisp primenančia programavimo kalba
+Comment[lv]=Paplašināms logu menedžeris ar Emacs Lisp līdzīgas valodas atbalstu
+Comment[mk]=Екстензивен менаџер на прозорци кој може да се скриптира со јазик како Emacs Lisp
+Comment[ms]=Pengurus tetingkap boleh kembang dan boleh diskrip dengan bahasa seperti Emacs Lisp
+Comment[mt]=Window manager li jista' jiġi estiż, b'lingwa tixbaħ lil Emacs Lisp
+Comment[nb]=En utvidbar vindusbehandler som kan skriptes med et språk som likner Emacs Lisp.
+Comment[nds]=En verwiederbor Finsterpleger, de över en Skriptspraak liek to Emacs-Lisp stüert warrn kann
+Comment[ne]=इमाक्स लिस्प जस्तो भाषसँग स्क्रिप्ट गर्न सकिने एउटा विस्तारयोग्य सञ्झ्याल प्रबन्धक
+Comment[nl]=Een uitbreidbare windowmanager, scriptbaar via een Emacs Lisp-achtige taal
+Comment[nn]=Ein utvidbar vindaugssjef som kan skriptast med eit språk som liknar Emacs Lisp
+Comment[pa]= Emacs Lisp-ਵਰਗੀ ਭਾਸ਼ਾ ਸਕ੍ਰਿਪਟਯੋਗ ਝਰੋਖਾ ਮੈਨੇਜਰ
+Comment[pl]=Menedżer okien, który można rozszerzać za pomocą skrytów w języku podobnym do Emacs Lisp
+Comment[pt]=Um gestor de janelas extensível e programável com uma linguagem semelhante ao Emacs Lisp
+Comment[pt_BR]=um gerenciador de janelas extensível, baseado em scripts, com uma linguagem parecida com o Lisp do Emacs
+Comment[ro]=Un manager de ferestre extensibil scriptabil cu un limbaj similar cu Emacs Lisp
+Comment[ru]=Расширяемый скриптами Lisp наподобие Emacs оконный менеджер
+Comment[rw]=Mugenga dirishya yagurwa yandikwaho hakoreshejwe Emacs Kudedemanga-nka ururimi
+Comment[sk]=Rozšíriteľný správca okien, ktorého je možné ovládať programovacím jazykom podobným Emacs Lispu
+Comment[sl]=Razširljiv okenski upravitelj, ki se lahko upravlja s skripti v jeziku podobnem Emacs Lisp
+Comment[sr]=Проширив менаџер прозора који се може скриптовати помоћу језика налик на Emacs-ов Lisp
+Comment[sr@Latn]=Proširiv menadžer prozora koji se može skriptovati pomoću jezika nalik na Emacs-ov Lisp
+Comment[sv]=Utökningsbar fönsterhanterare som kan styras med ett Emacs Lisp-liknande skriptspråk
+Comment[ta]=Emacs Lisp-like மொழியுடனான விரிவாக்ககூடிய சாளர மேலாளர் எழுத்தாக்கம்
+Comment[th]=ระบบจัดการหน้าต่างที่สามารถเพิ่มขยายได้ และควบคุมด้วยการเขียนสคริปต์โดยใช้ภาษาแบบ Emacs Lisp
+Comment[tr]=Eklenti destekli Emacs Lisp benzeri bir kodlama dili kullanan kodlanabilir bir pencere yöneticisi
+Comment[tt]=Emacs Lisp-kebek tel belän kiñäylelgän täräzä-idäräçe
+Comment[uk]=Менеджер вікон, що можна розширювати мовою скриптів на кшталт Emacs Lisp
+Comment[vi]=Trình quản lý cửa sổ có thể viết kịch bản được với ngôn ngữ giống Emacs Lisp
+Comment[wa]=On manaedjeu d' purnea k' on pout radjouter des rawetes, apontiåve e scripes dins on lingaedje do stîle Emacs Lisp
+Comment[zh_CN]=可用类似 Emacs Lisp 的语法进行编程的窗口管理器
+Comment[zh_TW]=一個可用類似 Emacs Lisp 語言延伸的視窗管理程式
diff --git a/tdm/kfrontend/sessions/tde.desktop.cmake b/tdm/kfrontend/sessions/tde.desktop.cmake
new file mode 100644
index 00000000..c23a3320
--- /dev/null
+++ b/tdm/kfrontend/sessions/tde.desktop.cmake
@@ -0,0 +1,45 @@
+[Desktop Entry]
+Encoding=UTF-8
+Type=XSession
+Exec=@TDE_BIN_DIR@/starttde
+TryExec=@TDE_BIN_DIR@/starttde
+Name=TDE
+Name[hi]=केडीई
+Name[mn]=КДЭ
+Name[ta]=Kஏற்றக் காவலன்
+Name[xh]=iTDE
+Name[xx]=xxTDExx
+Comment=The Trinity Desktop Environment. A powerful Open Source graphical desktop environment
+Comment[bs]=Trinity Desktop Environment. Moćan grafički desktop otvorenog izvornog koda
+Comment[ca]=L'entorn d'escriptori K. Un poderós entorn d'escriptori gràfic de Codi Font Obert
+Comment[cy]=Yr Amgylchedd Penbwrdd K. Amgylchedd penbwrdd graffegol pwerus, sy'n gôd-agored.
+Comment[da]=K Skrivebordsmiljøet. Et kraftigt, åbent, grafisk skrivebordsmiljø
+Comment[de]=Das Trinity Desktop Environment. Eine mächtige, graphische Arbeitsumgebung und Open Source / Freie Software
+Comment[el]=Το Trinity Desktop Environment. Ένα πανίσχυρο ελεύθερης προέλευσης γραφικό περιβάλλον επιφάνειας εργασίας
+Comment[es]=El Entorno de Escritorio Trinity, un potente entorno de escritorio gráfico realizado de código abierto
+Comment[et]=K töölaua keskkond on võimas vaba tarkvara graafiline töölaua keskkond
+Comment[fi]=TDE-työpöytäympäristö (Trinity Desktop Environment) on tehokas avoimen lähdekoodin graafinen työpöytäympäristö
+Comment[fr]=The Trinity Desktop Environment. Un environnement de bureau graphique, puissant et Open Source
+Comment[he]=The Trinity Desktop Environment. סביבת עבודה גרפית, בעלת-עוצמה בקוד פתוח
+Comment[hi]=के डेस्कटॉप वातावरण. एक शक्तिशाली, ओपन सोर्स चित्रमय डेस्कटॉप वातावरण
+Comment[hu]=A TDE grafikus munkakörnyezet, egy szabad forráskódú grafikus ablakkezelő környezet
+Comment[it]=L'ambiente desktop TDE. Un potente ambiente desktop grafico Open Source
+Comment[mn]=The Trinity Desktop Environment. Хүчирхэг нээлттэй эх код бүхий график дэлгэцийн орчин
+Comment[nb]=Trinity Desktop Environment. Et kraftig grafisk skrivebordsmiljø med åpen kildekode.
+Comment[nl]=De Trinity Desktop Environment, een krachtige open source grafische desktop environment
+Comment[nn]=Trinity Desktop Environment. Eit kraftig grafisk skrivebordsmiljø med open kjeldekode.
+Comment[pl]=Środowisko TDE. Potężne środowisko graficzne Wolnego Oprogramowania.
+Comment[pt]=O Trinity Desktop Environment. Um ambiente gráfico open source poderoso
+Comment[pt_BR]=Acrônimo para Trinity Desktop Environment (ou Ambiente de Trabalho Trinity). Um poderoso ambiente de trabalho gráfico de código aberto
+Comment[ro]=Trinity Desktop Environment. Un mediu grafic cu surse deschise, foarte puternic
+Comment[sk]=The Trinity Desktop Environment. Výkonné, voľne šíriteľné grafické pracovné prostredie
+Comment[sl]=Namizno okolje K. Zmogljivo grafično namizno okolje odprte kode
+Comment[sr]=Trinity Desktop Environment (TDE). Моћно графичко радно окружење отвореног кода
+Comment[sv]=Trinity-skrivbordsmiljön. En kraftfull grafisk skrivbordsmiljö med öppen källkod
+Comment[ta]=Trinityமேல்மேசை சூழல். சக்திவாய்ந்த திறந்த ஆணைமூல சித்திர வகை மேல்மேசை சூழல்
+Comment[tr]=TDE Masaüstü Yöneticisi. Güçlü bir grafiksel masaüstü ortamı
+Comment[uk]=The Trinity Desktop Environment. Потужне графічне середовище з відкритими текстами
+Comment[uz]=TDE (Trinity Desktop Environment) - кучли Open Source график иш столи муҳити
+Comment[vi]=môi trường desktop Trinity, môi trường desktop đồ hoạ mã nguồn mở rất mạnh
+Comment[xx]=xxThe Trinity Desktop Environment. A powerful Open Source graphical desktop environmentxx
+Comment[zh_CN]=三位一体 桌面环境。强大的开放源代码图形桌面环境
diff --git a/tdm/kfrontend/sessions/tde.desktop.in b/tdm/kfrontend/sessions/tde.desktop.in
new file mode 100644
index 00000000..b9472453
--- /dev/null
+++ b/tdm/kfrontend/sessions/tde.desktop.in
@@ -0,0 +1,45 @@
+[Desktop Entry]
+Encoding=UTF-8
+Type=XSession
+Exec=@TDE_BINDIR@/starttde
+TryExec=@TDE_BINDIR@/starttde
+Name=Trinity
+Name[hi]=केडीई
+Name[mn]=КДЭ
+Name[ta]=Kஏற்றக் காவலன்
+Name[xh]=iTDE
+Name[xx]=xxTDExx
+Comment=The Trinity Desktop Environment. A powerful Open Source graphical desktop environment.
+Comment[bs]=Trinity Desktop Environment. Moćan grafički desktop otvorenog izvornog koda
+Comment[ca]=L'entorn d'escriptori Trinity. Un poderós entorn d'escriptori gràfic de Codi Font Obert
+Comment[cy]=Yr Amgylchedd Penbwrdd Trinity. Amgylchedd penbwrdd graffegol pwerus, sy'n gôd-agored.
+Comment[da]=K Skrivebordsmiljøet. Et kraftigt, åbent, grafisk skrivebordsmiljø
+Comment[de]=Das Trinity Desktop Environment. Eine mächtige, graphische Arbeitsumgebung und Open Source / Freie Software
+Comment[el]=Το Trinity Desktop Environment. Ένα πανίσχυρο ελεύθερης προέλευσης γραφικό περιβάλλον επιφάνειας εργασίας
+Comment[es]=El Entorno de Escritorio Trinity, un potente entorno de escritorio gráfico realizado de código abierto
+Comment[et]=K töölaua keskkond on võimas vaba tarkvara graafiline töölaua keskkond
+Comment[fi]=TDE-työpöytäympäristö (Trinity Desktop Environment) on tehokas avoimen lähdekoodin graafinen työpöytäympäristö
+Comment[fr]=The Trinity Desktop Environment. Un environnement de bureau graphique, puissant et Open Source
+Comment[he]=The Trinity Desktop Environment. סביבת עבודה גרפית, בעלת-עוצמה בקוד פתוח
+Comment[hi]=के डेस्कटॉप वातावरण. एक शक्तिशाली, ओपन सोर्स चित्रमय डेस्कटॉप वातावरण
+Comment[hu]=A TDE grafikus munkakörnyezet, egy szabad forráskódú grafikus ablakkezelő környezet
+Comment[it]=L'ambiente desktop TDE. Un potente ambiente desktop grafico Open Source
+Comment[mn]=The Trinity Desktop Environment. Хүчирхэг нээлттэй эх код бүхий график дэлгэцийн орчин
+Comment[nb]=Trinity Desktop Environment. Et kraftig grafisk skrivebordsmiljø med åpen kildekode.
+Comment[nl]=De Trinity Desktop Environment, een krachtige open source grafische desktop environment
+Comment[nn]=Trinity Desktop Environment. Eit kraftig grafisk skrivebordsmiljø med open kjeldekode.
+Comment[pl]=Środowisko TDE. Potężne środowisko graficzne Wolnego Oprogramowania.
+Comment[pt]=O Trinity Desktop Environment. Um ambiente gráfico open source poderoso
+Comment[pt_BR]=Acrônimo para Trinity Desktop Environment (ou Ambiente de Trabalho Trinity). Um poderoso ambiente de trabalho gráfico de código aberto
+Comment[ro]=Trinity Desktop Environment. Un mediu grafic cu surse deschise, foarte puternic
+Comment[sk]=The Trinity Desktop Environment. Výkonné, voľne šíriteľné grafické pracovné prostredie
+Comment[sl]=Namizno okolje K. Zmogljivo grafično namizno okolje odprte kode
+Comment[sr]=Trinity Desktop Environment (TDE). Моћно графичко радно окружење отвореног кода
+Comment[sv]=Trinity-skrivbordsmiljön. En kraftfull grafisk skrivbordsmiljö med öppen källkod
+Comment[ta]= Trinityமேல்மேசை சூழல். சக்திவாய்ந்த திறந்த ஆணைமூல சித்திர வகை மேல்மேசை சூழல்
+Comment[tr]=TDE Masaüstü Yöneticisi. Güçlü bir grafiksel masaüstü ortamı
+Comment[uk]=The Trinity Desktop Environment. Потужне графічне середовище з відкритими текстами
+Comment[uz]=TDE (Trinity Desktop Environment) - кучли Open Source график иш столи муҳити
+Comment[vi]=môi trường desktop K, môi trường desktop đồ hoạ mã nguồn mở rất mạnh
+Comment[xx]=xxThe Trinity Desktop Environment. A powerful Open Source graphical desktop environmentxx
+Comment[zh_CN]=三位一体 桌面环境。强大的开放源代码图形桌面环境
diff --git a/tdm/kfrontend/sessions/twm.desktop b/tdm/kfrontend/sessions/twm.desktop
new file mode 100644
index 00000000..894371ae
--- /dev/null
+++ b/tdm/kfrontend/sessions/twm.desktop
@@ -0,0 +1,71 @@
+[Desktop Entry]
+Type=XSession
+Exec=twm
+TryExec=twm
+Name=TWM
+Name[eo]=TFA
+Name[hi]=टीडबल्यूएम
+Name[te]=టి డబ్ల్యు ఎం
+Comment=The Tab Window Manager
+Comment[af]=Die Tab venster bestuurder
+Comment[ar]=مدير النوافذ Tab
+Comment[be]=Кіраўнік вокнаў з укладкамі Tab Window Manager
+Comment[bn]=দি ট্যাব উইণ্ডো ম্যানেজার
+Comment[bs]=Tab Window Manager
+Comment[ca]=El gestor de finestres Tab
+Comment[csb]=Tab Window Manager
+Comment[cy]=Y Trefnydd Ffenestri Tab
+Comment[da]=Tab-vindueshåndtering
+Comment[de]=Der Tab-Fenstermanager
+Comment[el]=Ο διαχειριστής παραθύρων Tab
+Comment[eo]=Taba fenestroadministrilo
+Comment[es]=El Tab Window Manager
+Comment[et]=Kaartidega aknahaldur
+Comment[eu]=Tab leiho kudeatzailea
+Comment[fa]=مدیر پنجرۀ تب
+Comment[fi]=Välilehtiä tukeva ikkunaohjelma
+Comment[fy]=De Ljepper Finster Behearder
+Comment[gl]=O Xestor de Fiestras Tab
+Comment[hi]=टैब विंडो प्रबंधक
+Comment[hr]=Tab upravitelj prozora
+Comment[hu]=Tab Window Manager ablakkezelő
+Comment[is]=Tab gluggastjórinn
+Comment[it]=Il Tab Window Manager
+Comment[ja]=Tab 化ウィンドウマネージャ
+Comment[ka]=X11 სისტემის ტრადიციული ფანჯრის მენეჯერი
+Comment[kk]=Tab терезе менеджері
+Comment[km]=កម្មវិធី​គ្រប់គ្រង​បង្អួច​ជា​ផ្ទាំង
+Comment[ko]=탭 창 관리자
+Comment[lt]=Kortelių langų tvarkyklė
+Comment[lv]=Tabu logu menedžeris
+Comment[mk]=Tab Window Manager
+Comment[mn]=Tab Цонхны удирдагч
+Comment[ms]=Pengurus Tetingkap Tab
+Comment[mt]=Tab Window Manager
+Comment[nb]=Tab Vindusbehandler
+Comment[nds]=De Tab-Finsterpleger
+Comment[ne]=ट्याब सञ्झ्याल प्रबन्धक
+Comment[nl]=De Tab Window Manager
+Comment[nn]=Tab Window Manager
+Comment[pa]=ਟੈਬ ਝਰੋਖਾ ਮੈਨੇਜਰ
+Comment[pl]=Tab Window Manager
+Comment[pt]=O Tab Window Manager
+Comment[pt_BR]=O Gerenciador de Janelas de Abas
+Comment[ro]=Tab Window Manager
+Comment[ru]=Традиционный оконный менеджер системы X11
+Comment[rw]=Mugenga Dirishya Agafishi
+Comment[se]=Tab-láse lásegieđahalli
+Comment[sk]=Správca okien s kartami
+Comment[sl]=Tab Window Manager, okenski upravitelj z zavihki
+Comment[sv]=Flikfönsterhanteraren
+Comment[ta]=டாப் சாளர மேலாளர்
+Comment[te]=టాబ్ విండొ అభికర్త
+Comment[tg]=Tab-и мудири тиреза
+Comment[th]=Tab Window Manager
+Comment[tr]=Tab Pencere Yöneticisi
+Comment[tt]=X11 sistemendäge kebek tabaqlı täräzä-idäräçe
+Comment[uk]=Tab Window Manager
+Comment[vi]=Trình Quản lý Cửa sổ Thẻ
+Comment[wa]=Li manaedjeu di purneas avou Linwetes (Tab Window Manager)
+Comment[zh_CN]=标签式窗口管理器
+Comment[zh_TW]=Tab 視窗管理程式
diff --git a/tdm/kfrontend/sessions/ude.desktop b/tdm/kfrontend/sessions/ude.desktop
new file mode 100644
index 00000000..108a493e
--- /dev/null
+++ b/tdm/kfrontend/sessions/ude.desktop
@@ -0,0 +1,75 @@
+[Desktop Entry]
+Type=XSession
+Exec=uwm
+TryExec=uwm
+Name=UDE
+Name[eo]=ULĈ
+Name[hi]=यूडीई
+Name[te]=యుడిఈ
+Comment=The UNIX Desktop Environment
+Comment[af]=Die 'Unix Desktop Environment'
+Comment[ar]=بيئة سطح مكتب يونكس
+Comment[be]=Працоўнае асяроддзе UNIX
+Comment[bn]=দি ইউনিক্স ডেস্কটপ এনভায়রনমেন্ট
+Comment[br]=An endro burev UNIX
+Comment[bs]=UNIX Desktop Environment
+Comment[ca]=L'entorn d'escriptori de Unix
+Comment[csb]=Òkrãże pùltu Uniksa
+Comment[cy]=Yr Amgylchedd Penbwrdd UNIX
+Comment[da]=UNIX desktopmiljø
+Comment[de]=Das UNIX Desktop Environment
+Comment[el]=Το περιβάλλον επιφάνειας εργασίας του UNIX
+Comment[eo]=La Uniksa Labortablo Ĉirkauaĵo
+Comment[es]=El UNIX Desktop Environment
+Comment[et]=UNIXi töölaua keskkond
+Comment[eu]=UNIX mahaigain ingurunea
+Comment[fa]=محیط رومیزی یونیکس
+Comment[fi]=UNIX-työpöytäympäristö
+Comment[fy]=De Unix Desktop Environment
+Comment[ga]=Timpeallacht Deisce UNIX (UDE)
+Comment[gl]=O Entorno de Escritório de UNIX
+Comment[hi]=यूनिक्स डेस्कटॉप माहौल
+Comment[hr]=UNIX radno okruženje
+Comment[hu]=UNIX Desktop Environment ablakkezelő
+Comment[is]=UNIX skjáborðsumhverfið
+Comment[it]=Lo Unix Desktop Environment
+Comment[ja]=UNIX デスクトップ環境
+Comment[ka]=UNIX-ის სამუშაო გარემო
+Comment[kk]=UNIX Desktop Environment
+Comment[km]=UNIX Desktop Environment
+Comment[ko]=UNIX 데스크톱 환경
+Comment[lt]=UNIX darbastalio aplinka
+Comment[lv]= UNIX Darba virsmas vide
+Comment[mk]=UNIX Desktop Environment
+Comment[mn]=ЮНИКС ажлын тавцангийн орчин
+Comment[ms]=Persekitaran Desktop UNIX
+Comment[mt]=UNIX Desktop Environment
+Comment[nb]=UNIX Desktop Environment
+Comment[nds]=De UNIX-Schriefdisch-Ümgeven
+Comment[ne]=युनिक्स डेस्कटप वातावरण
+Comment[nl]=De Unix Desktop Environment
+Comment[nn]=UNIX Desktop Environment
+Comment[pa]=UNIX Desktop Environment
+Comment[pl]=Środowisko pulpitu Uniksa
+Comment[pt]=O Unix Desktop Environment
+Comment[pt_BR]=Ambiente de Trabalho do UNIX
+Comment[ro]=Mediul grafic UNIX
+Comment[ru]=UNIX Desktop Environment
+Comment[rw]=Ibikikije Ibiro UNIX
+Comment[se]=UNIX Desktop Environment
+Comment[sl]=Namizno okolje UNIX
+Comment[sr]=Unix радно окружење
+Comment[sr@Latn]=Unix radno okruženje
+Comment[sv]=Unix-skrivbordsmiljön
+Comment[ta]=யுனிக்ஸ் மேல்மேசை சூழல்
+Comment[te]=యూనిక్స్ రంగస్థల పర్యావరణం
+Comment[tg]=Атрофи мизи кории UNIX
+Comment[th]=สภาพแวดล้อมเดสก์ทอป UNIX
+Comment[tr]=Unix Masaüstü Ortamı
+Comment[tt]=UNIX Desktop Environment
+Comment[uz]=Unix ish stoli muhiti (Unix Desktop Environment)
+Comment[uz@cyrillic]=Unix иш столи муҳити (Unix Desktop Environment)
+Comment[vi]=Môi trường Màn hình nền UNIX
+Comment[wa]=L' evironmint di scribanne Unix UDE
+Comment[zh_CN]=UNIX 桌面环境
+Comment[zh_TW]=Unix 桌面環境
diff --git a/tdm/kfrontend/sessions/vtwm.desktop b/tdm/kfrontend/sessions/vtwm.desktop
new file mode 100644
index 00000000..50af40a6
--- /dev/null
+++ b/tdm/kfrontend/sessions/vtwm.desktop
@@ -0,0 +1,72 @@
+[Desktop Entry]
+Type=XSession
+Exec=vtwm
+TryExec=vtwm
+Name=VTWM
+Name[eo]=VTFA
+Name[hi]=वीटीडबल्यूएम
+Name[te]= వి టి డబ్ల్యు ఎం
+Comment=The Virtual Tab Window Manager. TWM enhanced by virtual screens, etc.
+Comment[af]=Die virtuele tab venster bestuurder. TWM wat met virtuele skerms uitgebreik is.
+Comment[ar]=مدير نوافذ Tab الوهمي، مدير نوافذ TWM محسّن بأسطح المكتب الوهمية، إلخ.
+Comment[be]=Віртуальны кіраўнік вокнаў з укладкамі Virtual Tab Window Manager. TWM, з дадатковай падтрымкай віртуальных экранаў і інш.
+Comment[bn]=ভার্চুয়াল ট্যাব উইণ্ডো ম্যানেজার, ভার্চুয়াল স্ক্রীণ ইত্যাদি দ্বারা বর্ধিত
+Comment[bs]=Virtual Tab Window Manager. TWM proširen virtuelnim ekranima itd.
+Comment[ca]=El Virtual Tab Window Manager. TWM millorat per a pantalles virtuals, etc.
+Comment[cs]=The Virtual Tab Window Manager. TWM vylepšené o virtuální obrazovky aj.
+Comment[csb]=Virtual Tab Window Manager. TWM zbògacony ò wirtualné pùltë ëtp.
+Comment[cy]=Y Trefnydd Ffenestri Tab Rhith. TWM wedi'i wella gan sgriniau rhith, ayyb.
+Comment[da]=Virtual Tab Window Manager. TWM udvidet med virtuelle skærme osv.
+Comment[de]=Der Virtual-Tab-Fenstermanager, eine Erweiterung von TWM mit virtuellen Arbeitsflächen usw.
+Comment[el]=Ο εικονικός Tab διαχειριστής παραθύρων. Ο TWM εμπλουτισμένος με εικονικές οθόνες, κτλ.
+Comment[eo]=La Virtuala Taba Fenestroadministrilo, TFA plibonigita per virtualaj ekranoj
+Comment[es]=El Virtual Tab Window Manager, TWM mejorado con pantallas virtuales, etc.
+Comment[et]=Virtuaalsete kaartidega aknahaldur ehk TWM, mida on täiendatud virtuaalsete ekraanidega jne.
+Comment[eu]=Virtual Tab leiho kudeatzailea. Pantaila birtual eta abarrez hobetutako TWM-a
+Comment[fa]=یک مدیر پنجرۀ تب مجازی.TWM گسترش‌یافته توسط پرده‌های مجازی و غیره.
+Comment[fi]=Välilehtiä ja virtuaalityöpöytiä tukeva ikkunaohjelma, pohjautuu TWM:ään
+Comment[fr]=The Virtual Tab Window Manager. TWM avec en plus la gestion des bureaux multiples
+Comment[fy]=De firtuele Ljepper Window Manager. TWM útbreid mei firtuele buroblêden, ensfh.
+Comment[gl]=O Virtual Tab Window Manager. TWM mellorado con pantallas virtuais, etc.
+Comment[he]=The Virtual Tab Window Manager. TWM המשופר בשולחנות עבודה וירטואליים וכו'
+Comment[hi]=आभासी टैब विंडो प्रबंधक. TWM को आभासी स्क्रीन इत्यादि से बेहतर बनाया गया
+Comment[hr]=Comment=Virtual Tab Window Manager. TWM poboljšan virtualnim zaslonima itd.
+Comment[hu]=Virtual Tab Window Manager, egy TWM-változat, támogatja a virtuális képernyőkezelést
+Comment[is]=Tab gluggastjórinn endurbættur með sýndarskjám og fleiru.
+Comment[it]=Il Virtual Tab Window Manager. TWM migliorato con schermi virtuali ecc.
+Comment[ja]=仮想スクリーンなどの機能を拡張した TWM ベースの仮想タブウィンドウマネージャ
+Comment[ka]=ვირტუალური ეკრანებით აღჭურვილი TWM-ის ვარიანტი
+Comment[kk]=Virtual Tab Window Manager. TWM-негіздеген, виртуалды экрандары және т.б.с.с бар терезе менеджері.
+Comment[km]=Virtual Tab Window Manager ។ TWM ដែល​បាន​ធ្វើ​ឲ្យ​ប្រសើរ​ដោយ​អេក្រង់​និមិត្ត ជាដើម ។
+Comment[lt]=Virtualių kortelių darbastalio aplinka. TWM išplėsta virtualiais darbastaliais ir pan.
+Comment[lv]=Virtuālo tabu logu menedžeris. TWM papildināts ar virtuālajiem ekrāniem utml.
+Comment[mk]=Virtual Tab Window Manager. TWM подобрен со виртуелни површини итн.
+Comment[ms]=Pengurus Tetingkap Tab Maya. TWM dipertingkat dengan skrin maya, dsb.
+Comment[mt]=Virtual Tab Window Manager. TWM flimkien ma' desktops virtwali eċċ
+Comment[nb]=Virtual Tab vindusbehandler. TWM utvidet med virtuelle skjermer, osv.
+Comment[nds]=De "Virtual Tab Window Manager". Dat is TWM verwiedert üm virtuelle Schirmen etc.
+Comment[ne]=अवास्तविक ट्याब सञ्झ्याल प्रबन्धक । अवास्तविक पर्दाद्वारा बृद्धि गरिएको TWM, आदि
+Comment[nl]=De Virtual Tab Window Manager. TWM uitgebreid met virtuele bureaubladen, etc.
+Comment[nn]=Virtual Tab Window Manager. TWM utvida med virtuelle skjermar og anna.
+Comment[pa]=Virtual Tab Window Manager. TWM ਫਰਜ਼ੀ ਪਰਦਿਆਂ ਨਾਲ ਲੈੱਸ
+Comment[pl]=Virtual Tab Window Manager. TWM wzbogacony o wirtualne pulpity itp.
+Comment[pt]=O Virtual Tab Window Manager. Um TWM melhorado com ecrãs virtuais, etc.
+Comment[pt_BR]=O gerenciador de janelas de abas virtuais. TWM melhorado pelas telas virtuais.
+Comment[ro]=Virtual Tab Window Manager. TWM îmbunătățit cu ecrane virtuale etc.
+Comment[ru]=Вариант TWM, имеющий виртуальные экраны и т.д.
+Comment[rw]=Mugenga Dirishya y'Agafishi Itaboneka.TWM ivuguruwe na mugaragaza zitagaragara, n'ibindi.
+Comment[se]=The Virtual Tab Window Manager. TWM buoriduvvon virtuella čállinbevddiin, jna.
+Comment[sk]=The Virtual Tab Window Manager. TWM rozšírený o virtuálne obrazovky atď.
+Comment[sl]=Virtual Tab Window Manager. TWM, izboljšan z navideznimi zasloni ipd.
+Comment[sr]=„The Virtual Tab Window Manager“. TWM побољшан виртуелним екранима и сл.
+Comment[sr@Latn]=„The Virtual Tab Window Manager“. TWM poboljšan virtuelnim ekranima i sl.
+Comment[sv]=Virtuell flikfönsterhanterare. TWM utökad med virtuella skärmar, etc.
+Comment[ta]=மெய்நிகர் தத்தல் சாளர மேலாளர். TWM மெய்நிகர் திரைகளால் மேம்படுத்தப்பட்டது.
+Comment[th]=The Virtual Tab Window Manager คือ TWM ที่เพิ่มความสามารถโดยหน้าจอเสมือน และอื่นๆ
+Comment[tr]=Virtual Tab Masaüstü Yöneticisi.
+Comment[tt]=Virtual Tab Window Manager. Öställär östälengän TWM kebek.
+Comment[uk]=Virtual Tab Window Manager. TWM з підтримкою віртуальних екранів.
+Comment[vi]=Trình Quản lý Cửa sổ Thẻ Ảo. TWM cải tiến với màn hình ảo, ...
+Comment[wa]=Li Forveyou Manaedjeu di Purneas avou Linwetes (Virtual Tab Window Manager). TWM a sacwants forveyowès waitroûles, evnd.
+Comment[zh_CN]=虚拟标签式窗口管理器。用虚拟屏幕等功能增强的 TWM。
+Comment[zh_TW]=虛擬 Tab 視窗管理程式。基於 TWM 並加強虛擬螢幕等等。
diff --git a/tdm/kfrontend/sessions/w9wm.desktop b/tdm/kfrontend/sessions/w9wm.desktop
new file mode 100644
index 00000000..92633bcf
--- /dev/null
+++ b/tdm/kfrontend/sessions/w9wm.desktop
@@ -0,0 +1,74 @@
+[Desktop Entry]
+Type=XSession
+Exec=w9wm
+TryExec=w9wm
+Name=W9WM
+Name[eo]=F9FA
+Name[hi]=डबल्यू9डबल्यूएम
+Name[ta]=IceWM
+Name[te]=డబ్ల్యు 9 డబ్ల్యు ఎం
+Name[th]=ตัวจัดการหน้าต่าง W9WM
+Comment=A window manager based on 9WM, enhanced by virtual screens and keyboard bindings
+Comment[af]='n Venster bestuurder wat op 9WM gebaseer is, uitgebrei met virtuele skerms en sleutelbord bindinge
+Comment[ar]=مدير نوافذ مبني على 9WM، محسّن الشاشات الوهمية والمفاتيح المرتبطة
+Comment[be]=Кіраўнік вокнаў, заснаваны на 9WM, з дадатковай падтрымкай віртуальных экранаў і клавішных скаротаў
+Comment[bn]=9WM ভিত্তিক উইণ্ডো ম্যানেজার, ভার্চুয়াল স্ক্রীণ এবং কীবোর্ড বাইন্ডিং দ্বারা বর্ধিত
+Comment[bs]=Window manager baziran na 9WM, proširen virtuelnim ekranima i prečicama tastature
+Comment[ca]=Un gestor de finestres basat en 9WM, millorat per a pantalles virtuals i amb dreceres de teclat
+Comment[cs]=Správce oken založený na 9WM rozšířený o virtuální plochy a klávesové zkratky
+Comment[csb]=Menedżer òknów òpiarty na 9WM, zbògacony ò wirtualné ekranë ë kònfigùracëjã klawiszowëch skrodzënów
+Comment[cy]=Trefnydd ffenestri wedi'i seilio ar 9WM, wedi'i wella gan sgriniau rhith a rhwymiadau bysyll.
+Comment[da]=En vindueshåndtering baseret på 9WM, udvidet med virtuelle skærme og tastaturbindinger
+Comment[de]=Fenstermanager auf der Basis von 9WM, erweitert durch virtuelle Arbeitsflächen und Tastaturzuordnungen
+Comment[el]=Ένας διαχειριστής παραθύρων βασισμένος στον 9WM, εμπλουτισμένος με εικονικές οθόνες και συνδυασμούς πλήκτρων
+Comment[eo]=Fenestroadministrilo devenigita de 9FA, plibonigita per virtualaj ekranoj kaj klaviara uzo
+Comment[es]=Un gestor de ventanas basado en 9WM, mejorado con ventanas virtuales y accesos rápidos de teclado
+Comment[et]=Aknahaldur, mille aluseks on 9WM ja mida on täiendatud virtuaalsete ekraanide ja kiirklahvide võimalusega
+Comment[eu]=9WM-n oinarritutako leiho kudeatzailea, pantaila birtual eta laster-teklez hobetua
+Comment[fa]=یک مدیر پنجره بر اساس 9WM، گسترش‌یافته توسط ‌پرده‌های مجازی و مقیدسازیهای صفحه کلید
+Comment[fi]=9WM:ään pohjautuva ikkunaohjelma, jossa tuki virtuaalityöpöydille ja näppäimistöyhdistelmille
+Comment[fr]=Un gestionnaire de fenêtres fondé sur 9WM, avec en plus la gestion des bureaux virtuels et des raccourcis clavier
+Comment[fy]=In finstersmanager basearrre op 9WM. útbreid mei firtuele buroblêden en fluchtoetsen
+Comment[gl]=Un xestor de fiestras baseado en 9WM, mellorado polas pantallas virtuais e atallos de teclado
+Comment[he]=מנהל חלונות המבוסס על 9WM, המשופר בשולחנות עבודה וירטואליים ומיפוי מקשים
+Comment[hi]= 9डबल्यूएम आधारित विंडो प्रबंधक, आभासी स्क्रीन तथा की-बोर्ड बाइंडिंग से बेहतर बनाया गया
+Comment[hr]=Upravitelj prozora zasnovan na 9WM, unaprijeđen virtualnim zaslonima i prečacima tipkovnice
+Comment[hu]=Egy 9WM-alapú ablakkezelő, virtuális képernyőkezeléssel, konfigurálható billentyűparancsokkal
+Comment[is]=Gluggastjóri byggður á 9WM en endurbættur með sýndarskjám og lyklaborðsvörpunum
+Comment[it]=Un window manager basato su 9WM, migliorato con schermi virtuali e scorciatoie per la tastiera.
+Comment[ja]=仮想スクリーンとキーボードショートカット機能を強化した 9WM ベースのウィンドウマネージャ
+Comment[ka]=ფანჯრის მენეჯერი 9wm-ს ბაზაზე, ვირტუალური ეკრანებით და კლავიატურის შესაბამისობებით
+Comment[kk]=9WM-негіздеген, виртуалды экрандары, пернетақта тіркесімдері бар терезе менеджері
+Comment[km]=កម្មវិធី​គ្រប់គ្រង​បង្អួច​ផ្អែក​លើ 9WM ដែល​ត្រូវ​បាន​ធ្វើ​ឲ្យ​ប្រសើរ​ដោយ​អេក្រង់​និមិត្ត និង​ការ​ចង​គ្រាប់ចុច
+Comment[ko]=부분적 그놈 지원과 가상 데스크톱 지원을 사용하는 AEWM 기반 창 관리자
+Comment[lt]=Langų tvarkyklė, paremta 9WM, išplėsta virtualių ekranų ir klaviatūros greitųjų klavišų palaikymu
+Comment[lv]=Logu menedžeris bāzēts uz 9WM, papildināts ar virtuālajiem ekrāniem un tastatūras saīsnēm
+Comment[mk]=Менаџер на прозорци базиран на 9WM, подобрен со виртуелни површини и поврзувања за тастатурата
+Comment[ms]=Pengurus tetingkap berdasarkan 9WM, dipertingkat dengan skrin maya dan ikatan papan kekunci
+Comment[mt]=Window manager ibbażat fuq 9WM, flimkien ma desktops virtwali u hotkeys
+Comment[nb]=En vindusbehandler basert på 9WM, forbedret med virtuelle skjermer og hurtigtaster
+Comment[nds]=En Finsterpleger opbuut op 9WM, verwiedert üm virtuelle Schirmen un Tastkombinatschonen
+Comment[ne]=कुञ्जीपाटी बाइन्डिङ र अवास्तविक पर्दाहरूद्वारा बृद्धि गरिएको 9WM मा आधारित सञ्झ्याल प्रबन्धक
+Comment[nl]=Een windowmanager gebaseerd op 9WM. Uitgebreid met virtuele bureaubladen en sneltoetsen
+Comment[nn]=Ein vindaugssjef basert på 9WM, forbetra med virtuelle skjermar og snøggtastar
+Comment[pa]=9WM ਤੇ ਆਧਾਰਿਤ ਝਰੋਖਾ ਮੈਨੇਜਰ, ਫਰਜ਼ੀ ਪਰਦਿਆਂ ਤੇ ਕੀ-ਬੋਰਡ ਬਾਈਡਿੰਗ ਨਾਲ ਲੈੱਸ
+Comment[pl]=Menedżer okien oparty na 9WM, wzbogacony o wirtualne ekrany i konfigurowanie skrótów klawiszowych
+Comment[pt]=Um gestor de janelas baseado no 9WM, melhorado com ecrãs virtuais e atalhos de teclado
+Comment[pt_BR]=Um gerenciador de janelas baseado no 9Wm, melhorado pelas telas virtuais e atalhos de teclado
+Comment[ro]=Un manager de ferestre bazat pe 9WM, îmbunătățir cu ecrane virtuale și acceleratori de tastatură
+Comment[ru]=Оконный менеджер на основе 9wm, имеющий виртуальные экраны и привязку клавиш
+Comment[rw]=Mugenga Dirishya ishingiye kuri 9WM, ivuguruwe hakoreshejwe mugaragaza itaboneka n'amahuza mwandikisho
+Comment[sk]=Správca okien založený na 9WM, rozšírený o virtuálne obrazovkya klávesové skratky
+Comment[sl]=Okenski upravitelj na osnovi 9WM, izboljšan z navideznimi zasloni in tipkovnimi vezmi
+Comment[sr]=Менаџер прозора заснован на 9WM-у, побољшан виртуелним екранима и повезивањем тастатуре
+Comment[sr@Latn]=Menadžer prozora zasnovan na 9WM-u, poboljšan virtuelnim ekranima i povezivanjem tastature
+Comment[sv]=Fönsterhanterare baserad på 9WM, utökad med virtuella skärmar och tangentbindingar
+Comment[ta]=9WM அடிப்படையிலான மெய்நிகர் திரை மற்றும் விசைப்பலகை சேர்ப்புகளால் மேம்படுத்தப்பட்ட சாளர மேலாளார்,
+Comment[th]=ระบบจัดการหน้าต่างที่สร้างมาจาก 9WM และเพิ่มความสามารถด้วยหน้าจอเสมือนและแป้นพิมพ์ลัด
+Comment[tr]=9WM tabanlı, sanal ekranları ve klavye kısayolları ile geliştirilmiş bir masaüstü yöneticisi
+Comment[tt]=Xıyalí öställär belän töylekne totqan täräzä-idäräçe. 9WM asılında
+Comment[uk]=Менеджер вікон, заснований на 9WM, додано віртуальні екрани та прив'язки клавіш
+Comment[vi]=Trình quản lý cửa sổ dựa vào 9WM, cải tiến với màn hình ảo, tổ hợp phím
+Comment[wa]=On manaedjeu di purneas båzé so 9WM, avou sopoirt po les forveyous scribannes eyet les rascourtis di taprece.
+Comment[zh_CN]=基于 9WM 的窗口管理器,用虚拟屏幕和键盘绑定等功能增强了
+Comment[zh_TW]=一個基於 9WM 並加強虛擬螢幕及鍵盤組合鍵功能
diff --git a/tdm/kfrontend/sessions/waimea.desktop b/tdm/kfrontend/sessions/waimea.desktop
new file mode 100644
index 00000000..8981b5af
--- /dev/null
+++ b/tdm/kfrontend/sessions/waimea.desktop
@@ -0,0 +1,77 @@
+[Desktop Entry]
+Type=XSession
+Exec=waimea
+TryExec=waimea
+Name=Waimea
+Name[eo]=Vaimeo
+Name[hi]=वाईमिया
+Name[ne]=विमेआ
+Name[pa]=ਵਾਈਮਿਆ
+Name[te]=వైమెయా
+Comment=A highly customizable window manager based on Blackbox
+Comment[af]='n Hoë opstelbare venster bestuurder wat op Blackbox gebaseer is
+Comment[ar]=مدير نوافذ قابل جداً للتخصيص مبني على Blackbox
+Comment[be]=Кіраўнік вокнаў, заснаваны на Blackbox, з магчымасцю настаўлення
+Comment[bn]=ব্ল্যাকবক্স ভিত্তিক উইণ্ডো ম্যানেজার
+Comment[bs]=Visoko prilagodljiv window manager baziran na Blackbox
+Comment[ca]=Un gestor de finestres altament configurable basat en Blackbox
+Comment[cs]=Vysoce přizpůsobitelný správce oken založený na Blackboxu
+Comment[csb]=Menedżer òknów òpiartëch na Blackbox z wiôldżima mòżnotama dopasowaniô
+Comment[cy]=Trefnydd ffenestri sy'n hawdd ei ffurfweddu, wedi'i seilio ar Ddu-flwch
+Comment[da]=En meget indstillelig vindueshåndtering baseret på Blackbox
+Comment[de]=Vielfältig anpassbarer Fenstermanager, der auf Blackbox basiert
+Comment[el]=Ένας ιδιαίτερα παραμετροποιήσιμος διαχειριστής παραθύρων βασισμένος στον Blackbox
+Comment[en_GB]=A highly customisable window manager based on Blackbox
+Comment[eo]=Tre agordebla fenestroadministrilo, devenigita de Negrujo
+Comment[es]=Un gestor de ventanas muy personalizable basado en Blackbox
+Comment[et]=Väga hästi kohandatav aknahaldur, aluseks Blackbox
+Comment[eu]=Blackboxen oinarritutako leiho-kudeatzaile zeharo pertsonalizagarria
+Comment[fa]=یک مدیر پنجره با قابلیت سفارشی‌سازی بالا بر اساس Blackbox
+Comment[fi]=Blackboxiin perustuva paljon muokattavissa oleva ikkunaohjelma
+Comment[fr]=Un gestionnaire de fenêtres très configurable fondé sur Blackbox
+Comment[fy]=In tige ynstelbere finstersmanager, basearre op Blackbox
+Comment[gl]=Un xestor de fiestras moi personalizábel baseado en Blackbox
+Comment[he]=מנהל חלונות המאפשר התאמה אישית גבוהה והמבוסס על Blackbox
+Comment[hi]=ब्लेक-बाक्स आधारित, अत्यंत कस्टमाइजेबल विंडो प्रबंधक
+Comment[hr]=Vrlo prilagodljiv upravitelj prozora zasnovan na Blackboxu
+Comment[hu]=Egy sokféle beállítási lehetőséggel rendelkező ablakkezelő a Blackbox alapján
+Comment[is]=Afar stillanlegur gluggastjóri byggður á Blackbox
+Comment[it]=Un window manager molto personalizzabile basato su BlackBox
+Comment[ja]=Blackbox ベースの高度なカスタマイズが可能なウィンドウマネージャ
+Comment[ka]=კონფიგურირებადი ფანჯრის მენეჯერი Blackbox-ს ბაზაზე
+Comment[kk]=Blackbox-негіздеген, баптау жағынан бай, терезе менеджері
+Comment[km]=កម្មវិធី​គ្រប់គ្រង​បង្អួច​ដែល​អាច​ប្ដូរ​តាម​បំណង​កម្រិត​ខ្ពស់ ដោយ​ផ្អែក​លើ Blackbox
+Comment[ko]=Blackbox 기반의 사용자 정의가 가능한 관리자
+Comment[lt]=Daug konfigūravimo parinkčių turinti langų tvarkyklė, paremta Blackbox
+Comment[lv]=Plaši konfigurējams logu menedžeris bāzēts uz Blackbox
+Comment[mk]=Менаџер на прозорци базиран на Blackbox со голем број опции
+Comment[ms]=Pengurus tetingkap boleh suai berdasarkan Kotak Hitam
+Comment[mt]=Window manager konfigurabbli ibbażat fuq BlackBox
+Comment[nb]=En vindusbehandler med mange tilpasninger, basert på Blackbox
+Comment[nds]=En Finsterpleger mit mennige Instellen, opbuut op Blackbox
+Comment[ne]=कालो बाकसमा आधारित उच्च अनुकूल योग्य एक सञ्झ्याल प्रबन्धक
+Comment[nl]=Een zeer instelbare windowmanager, gebaseerd op Blackbox
+Comment[nn]=Ein vindaugssjef med mange tilpassingar, basert på Blackbox
+Comment[pa]=ਬਲੈਕਬਕਸੇ 'ਤੇ ਆਧਾਰਿਤ ਅਤਿ ਸੋਧਯਯੋਗ ਝਰੋਖਾ ਮੈਨੇਜਰ
+Comment[pl]=Menedżer okien oparty na Blackbox z dużymi możliwościami dostosowania
+Comment[pt]=Um gestor de janelas altamente configurável, baseado no Blackbox
+Comment[pt_BR]=Um gerenciador de janelas altamente personalizável, baseado no Blackbox
+Comment[ro]=Un manager de ferestre foarte configurabil bazat pe Blackbox
+Comment[ru]=Настраиваемый оконный менеджер, основанный на Blackbox
+Comment[rw]=Mugenga dirishya ihabwa imiterere yifuzwa mu buryo hejuru ishingiye ku Gasandukumukara
+Comment[sk]=Veľmi prispôsobiteľný správca okien založený na Blackbox
+Comment[sl]=Visoko nastavljiv okenski upravitelj na osnovi Blackboxa
+Comment[sr]=Врло прилагодљив менаџер прозора заснован на Blackbox-у
+Comment[sr@Latn]=Vrlo prilagodljiv menadžer prozora zasnovan na Blackbox-u
+Comment[sv]=Ytterst anpassningsbar fönsterhanterare baserad på Blackbox
+Comment[ta]=தனதாக்க வல்ல கருப்புப்பெட்டி சார்ந்த சாளர மேலாளர்
+Comment[th]=ระบบจัดการหน้าต่างที่ปรับแต่งได้อย่างละเอียด สร้างมาจาก Blackbox
+Comment[tr]=Blackbox temelli, kolayca özelleştirilebilir bir pencere yöneticisi
+Comment[tt]=Yaqşı köylänüçän täräzä-idäräçe. Blackbox asılında
+Comment[uk]=Надгнучкий менеджер вікон, заснований на Blackbox
+Comment[uz]=Blackbox asosida yaratilgan, moslab boʻladigan oyna boshqaruvchi
+Comment[uz@cyrillic]=Blackbox асосида яратилган, мослаб бўладиган ойна бошқарувчи
+Comment[vi]=Trình quản lý cửa sổ rất dễ cá nhân hoá dựa trên Blackbox
+Comment[wa]=On manaedjeu di purneas k' vos ploz pår mete da vosse båzé so Blackbox
+Comment[zh_CN]=基于 BlackBox 可高度自定义的窗口管理器
+Comment[zh_TW]=一個基於 Blackbox 且高度可客製化的視窗管理程式
diff --git a/tdm/kfrontend/sessions/wm2.desktop b/tdm/kfrontend/sessions/wm2.desktop
new file mode 100644
index 00000000..618c10bc
--- /dev/null
+++ b/tdm/kfrontend/sessions/wm2.desktop
@@ -0,0 +1,77 @@
+[Desktop Entry]
+Type=XSession
+Exec=wm2
+TryExec=wm2
+Name=WM2
+Name[eo]=Fa2
+Name[hi]=डबल्यूएम2
+Name[te]=డబ్ల్యు ఎం 2
+Name[th]=ตัวจัดการหน้าต่าง WM2
+Comment=A small, non-configurable window manager
+Comment[af]='n Klein, nie opstelbare venster bestuurder
+Comment[ar]=مدير نوافذ صغير غير قابل للإعداد
+Comment[be]=Маленькі кіраўнік вокнаў, без магчымасці настаўленняў
+Comment[bn]=একটি ছোটো উইণ্ডো ম্যানেজার
+Comment[bs]=Mali, ne-konfigurabilni window manager
+Comment[ca]=Un petit i no configurable gestor de finestres
+Comment[cs]=Malý nepřizpůsobitelný správce oken
+Comment[csb]=Môłi menedżer òknów bez mòżnotë kònfigùracëji
+Comment[cy]=Trefnydd ffenestri bach na ellir ffurfweddu
+Comment[da]=En lille, ikke-indstillelig vindueshåndtering
+Comment[de]=Kleiner, nicht einstellbarer Fenstermanager
+Comment[el]=Ένας μικρός, μη παραμετροποιήσιμος διαχειριστής παραθύρων
+Comment[eo]=Malgranda, ne agordebla fenestroadministrilo
+Comment[es]=Un gestor de ventanas pequeño y no configurable
+Comment[et]=Väike ja seadistamatu aknahaldur
+Comment[eu]=Leiho-kudeatzaile txikia, konfiguratu ezin dena
+Comment[fa]=یک مدیر پنجرۀ کوچک و غیرقابل پیکربندی
+Comment[fi]=Pieni ikkunaohjelma, jossa ei ole asetuksia
+Comment[fr]=Un gestionnaire de fenêtres petit et non configurable
+Comment[fy]=In lytse, net-ynstelbere finstersmanager
+Comment[gl]=Un xestor de fiestras pequeno non configurábel
+Comment[he]=מנהל חלונות קטן ולא ניתן להגדרה
+Comment[hi]=एक छोटा विंडो प्रबंधक जो कॉन्फ़िगर नहीं हो सकता
+Comment[hr]=Malen, nepodesiv upravitelj prozora
+Comment[hu]=Egy nagyon egyszerű ablakkezelő, beállítási lehetőségek nélkül
+Comment[is]=Lítill, einfaldur gluggastjóri sem er ekki hægt að stilla
+Comment[it]=Un window manager piccolo e non configurabile
+Comment[ja]=小さくて設定項目のないウィンドウマネージャ
+Comment[ka]=პატარა და არაკონფიგურირებადი ფანჯრის მენეჯერი
+Comment[kk]=Шағын, баптауы жоқ, терезе менеджері
+Comment[km]=កម្មវិធី​គ្រប់គ្រង​បង្អួច​តូច ហើយ​មិន​អាច​កំណត់​រចនាសម្ព័ន្ធ​បាន
+Comment[ko]=설정할 수 없는 작은 창 관리자
+Comment[lt]=Maža, nekonfigūruojama langų tvarkyklė
+Comment[lv]=Mazs, nekonfigurējams logu menedžeris
+Comment[mk]=Мал и неконфигурабилен менаџер на прозорци
+Comment[mn]=Жижиг тохируулах боломжгүй цонх удирдагч
+Comment[ms]=Pengurus tetingkap yang kecil dan tidak boleh konfigur
+Comment[mt]=Window manager żgħir u mhux konfigurabbli
+Comment[nb]=En liten vindusbehandler uten tilpasninger
+Comment[nds]=En lütte Finsterpleger ahn Instellen
+Comment[ne]=सानो, कन्फिगर गर्न नसकिने सञ्झ्याल प्रबन्धक
+Comment[nl]=Een kleine, niet-instelbare windowmanager
+Comment[nn]=Ein liten vindaugssjef utan tilpassingar
+Comment[pa]=ਇੱਕ ਹਲਕਾ ਨਾ-ਸੋਧਯੋਗ ਝਰੋਖਾ ਮੈਨੇਜਰ
+Comment[pl]=Mały menedżer okien nie podlegający konfiguracji
+Comment[pt]=Um gestor de janelas pequeno e não-configurável
+Comment[pt_BR]=Um pequeno e não-configurável gerenciador de janelas
+Comment[ro]=Un manager de ferestre mic, neconfigurabil
+Comment[ru]=Маленький, не настраиваемый оконный менеджер
+Comment[rw]=Mugenga Dirishya itabonezwa, ntoya
+Comment[se]=Unna, ii heivehahtti lásegieđahalli
+Comment[sk]=Malý, nenastaviteľný správca okien
+Comment[sl]=Majhen, nenastavljiv okenski upravitelj
+Comment[sr]=Мали, неподесиви менаџер прозора
+Comment[sr@Latn]=Mali, nepodesivi menadžer prozora
+Comment[sv]=Liten fönsterhanterare utan anpassningsmöjligheter
+Comment[ta]=சிறிய, வடிவமைக்க முடியாத சாளர மேலாளர்
+Comment[th]=ระบบจัดการหน้าที่ขนาดเล็ก ที่ไม่สามารถปรับแต่งอะไรได้
+Comment[tr]=Küçük ve yapılandırılamayan bir pencere yöneticisi
+Comment[tt]=Caylanmí torğan keçkenä täräzä-idäräçe
+Comment[uk]=Невеличкий менеджер вікон без можливості налаштування
+Comment[uz]=Kichik, moslab boʻlmaydigan oyna boshqaruvchi
+Comment[uz@cyrillic]=Кичик, мослаб бўлмайдиган ойна бошқарувчи
+Comment[vi]=Trình quản lý cửa sổ nhỏ, không cấu hình được
+Comment[wa]=On ptit, nén apontiåve, manaedjeu di purneas
+Comment[zh_CN]=小巧的不可配置的窗口管理器
+Comment[zh_TW]=一個小型且不可組態的視窗管理者
diff --git a/tdm/kfrontend/sessions/wmaker.desktop b/tdm/kfrontend/sessions/wmaker.desktop
new file mode 100644
index 00000000..fada3d3b
--- /dev/null
+++ b/tdm/kfrontend/sessions/wmaker.desktop
@@ -0,0 +1,82 @@
+[Desktop Entry]
+Type=XSession
+Exec=wmaker
+TryExec=wmaker
+Name=WindowMaker
+Name[bn]=উইণ্ডো-মেকার
+Name[cy]=GwneuthuryddFfenestri (WindowMaker)
+Name[eo]=Fenestroadministrilo
+Name[hi]=विंडोमेकर
+Name[ne]=सञ्झ्याल निर्माता
+Name[pa]=ਝਰੋਖਾ-ਨਿਰਮਾਤਾ
+Name[rw]=MukoraDirishya
+Name[sv]=Windowmaker
+Name[ta]=விண்டோஸ்மேக்கர்
+Name[te]=విండొమెకర్
+Name[tg]=Созандаи тиреза
+Comment=A simple window manager that resembles the NeXTStep look very closely
+Comment[af]='n Eenvoudige venster bestuurder wat soos NeXTStep lyk
+Comment[ar]=مدير نوافذ بسيط يمثّل مظهر NeXTStep بشكل قريب جداً
+Comment[be]=Просты кіраўнік вокнаў, які вельмі дакладна паўтарае вонкавы выгляд NeXTStep
+Comment[bn]=একটি উইণ্ডো ম্যানেজার যা ভীষণরকম NeXTStep-এর মত দেখতে
+Comment[bs]=Jednostavan window manager koji vrlo dosljedno imitira NeXTStep izgled
+Comment[ca]=Un gestor de finestres simple que s'assembla molt a l'aspecte de NeXTStep
+Comment[cs]=Jendoduchý správce oken, který se velmi podobá NeXTStep
+Comment[csb]=Prosti menedżer òknów szlachùjący za NeXTStep
+Comment[cy]=Trefnydd ffenestri syml sy'n debyg iawn i'r golwg CamNesaf
+Comment[da]=En simpel vindueshåndtering der ligner NeXTStep's udseende meget
+Comment[de]=Einfacher Fenstermanager mit starker Ähnlichkeit zu NeXTStep
+Comment[el]=Ένας απλός διαχειριστής παραθύρων που προσομοιώνει πολύ καλά το στυλ του NeXTStep
+Comment[eo]=Simpla fenestroadministrilo
+Comment[es]=Un gestor de ventanas sencillo cuyo aspecto se parece mucho al de NeXTStep
+Comment[et]=Lihtne aknahaldur, mis meenutab väga tugevasti NeXTStepi
+Comment[eu]=Leiho kudeatzaile sinplea, NeXTStep-en antz handia duena
+Comment[fa]=یک مدیر پنجرۀ ساده که خیلی شبیه گام بعدی است
+Comment[fi]=Yksinkertainen ikkunaohjelma, joka muistuttaa erittäin paljon NeXTStepiltä
+Comment[fr]=Un gestionnaire de fenêtres simple qui ressemble assez précisement à NeXTStep
+Comment[fy]=In ienfâldige finstersmanager dy it úterlik fan NeXTStep saer tichtby benaderd
+Comment[gl]=Un xestor de fiestras sinxelo que se achega moito á apariencia de NeXTStep
+Comment[he]=מנהל חלונות פשוט הדומה מאוד במראה שלו ל־NeXTStep
+Comment[hi]=नेक्स्टस्टेप की तरह दिखने वाला सादा विंडो प्रबंधक
+Comment[hr]=Jednostavan upravitelj prozora koji odražava vrlo blisko izgled NeXTStepa
+Comment[hu]=Egy egyszerű ablakkezelő, megjelenése nagyon hasonlít a NeXTStephez
+Comment[is]=Einfaldur gluggastjóri sem líkir vel eftir NeXTStep umhverfinu
+Comment[it]=Un semplice window manager che assomiglia molto a NeXTStep.
+Comment[ja]=NextStep にとてもよく似たシンプルなウィンドウマネージャ
+Comment[ka]=NeXTStep -ის მაგვარი მარტივი ფანჯრის მენეჯერი
+Comment[kk]=Қарапайым, NeXTStep-ке үқсас терезе менеджері
+Comment[km]=កម្មវិធី​គ្រប់គ្រង​បង្អួច​ធម្មតា​មួយ ដែល​ប្រហាក់ប្រហែល​នឹង​រូបរាង NeXTStep បំផុត
+Comment[lt]=Paprasta langų tvarkyklė, išvaizda labai primenanti NeXTStep
+Comment[lv]=Vienkāršs logu menedžeris, kas ir ļoti līdzīgs NeXTStep
+Comment[mk]=Едноставен менаџер на прозорци кој е многу сличен на изгледот на NeXTStep
+Comment[ms]=Pengurus tetingkap ringkas yang memasang NeXTStep dan menjadikannya tampak sangat hampir
+Comment[mt]=Window manager li jixbaħ ħafna lil NextStep
+Comment[nb]=En enkel vindusbehandler som ligner mye på NeXTStep
+Comment[nds]=En eenfache Finsterpleger, de meist utsüht as NeXTStep
+Comment[ne]=NeXTStep जस्तो देखिने साधारण सञ्झ्याल प्रबन्धक
+Comment[nl]=Een eenvoudige windowmanager die het uiterlijk van NeXTStep zeer dicht benaderd
+Comment[nn]=Ein enkel vindaugssjef som liknar mykje på NeXTStep
+Comment[pa]=ਇੱਕ ਸਧਾਰਨ ਜੋ ਕਿ NeXTStep ਵਰਗਾ ਜਾਪਦਾ ਹੈ
+Comment[pl]=Prosty menedżer okien przypominający bardzo wyglądem NeXTStep
+Comment[pt]=Um gestor de janelas simples que faz lembrar bastante o visual do NeXTStep
+Comment[pt_BR]=Um gerenciador de janelas simples, que lembra a aparência do NeXTStep
+Comment[ro]=Un manager de ferestre simplu, care amintește foarte bine de aspectul NeXTStep
+Comment[ru]=Простой оконный менеджер, воспроизводящий интерфейс NeXTStep
+Comment[rw]=Mugenga Dirishya yoroheje ihuriza hamwe imboneko IntambweIkurikira byegeranye cyane
+Comment[se]=Oktageardánis lásegieđahalli mii sulástahttá NeXTStep hui ollu
+Comment[sk]=Jednoduchý správca okien, ktorý veľmi pripojíma NeXTStep
+Comment[sl]=Preprost okenski upravitelj, ki zelo spominja na izgled NeXTStep
+Comment[sr]=Једноставан менаџер прозора који одражава врло блиско изглед NeXTStep-а
+Comment[sr@Latn]=Jednostavan menadžer prozora koji odražava vrlo blisko izgled NeXTStep-a
+Comment[sv]=Enkel fönsterhanterare som mycket nära efterliknar Nextstep-utseendet
+Comment[ta]=NeXTStep ஐ ஒத்த எளிய சாளர மேலாளார்.
+Comment[th]=ระบบจัดการหน้าต่างแบบเรียบง่าย ที่ดูคล้ายระบบ NeXTStep มากๆ
+Comment[tr]=NeXTStep'e aşırı benzeyen basit bir masaüstü yöneticisi
+Comment[tt]=NeXTStep küreneşendä ciñel täräzä-idäräçe
+Comment[uk]=Простий менеджер вікон, що дуже нагадує NeXTStep
+Comment[uz]=NeXTStep'ga juda oʻxshash oddiy oyna boshqaruvchi
+Comment[uz@cyrillic]=NeXTStep'га жуда ўхшаш оддий ойна бошқарувчи
+Comment[vi]=Trình quản lý cửa sổ giống với NeXTStep
+Comment[wa]=On simpe manaedjeu di purneas avou l' foite rivnance di NeXTStep
+Comment[zh_CN]=非常接近 NeXTStep 外观的简单窗口管理器
+Comment[zh_TW]=一個小型且與 NeXTStep 外觀很接近的視窗管理程式
diff --git a/tdm/kfrontend/sessions/xfce.desktop b/tdm/kfrontend/sessions/xfce.desktop
new file mode 100644
index 00000000..6b199228
--- /dev/null
+++ b/tdm/kfrontend/sessions/xfce.desktop
@@ -0,0 +1,73 @@
+[Desktop Entry]
+Type=XSession
+Exec=xfwm
+TryExec=xfwm
+Name=XFce
+Name[eo]=Facoj
+Name[hi]=एक्सएफसीई
+Name[sv]=Xfce
+Name[te]=ఎక్స్ ఎఫ్ సి ఈ
+Comment=The Cholesterol Free Desktop Environment. A desktop environment reminiscent of CDE
+Comment[af]=Die Cholesterol Gratis Werkskerm Omgewing. 'n Werkskerm omgewing wat op CDE gebaseer is
+Comment[ar]=بيئة سطح المكتب الخالي من الكوليسترول، بيئة سطح مكتب مليئة بذكريات CDE
+Comment[be]=XFCE - Cholesterol Free Desktop Environment. Працоўнае асяроддзе, падобнае на CDE
+Comment[bn]=দি কলেস্টরল ফ্রী ডেস্কটপ এনভায়রনমেন্ট। CDE-র কথা মনে করিয়ে দেয় এমন একটি ডেস্কটপ এনভায়রনমেন্ট
+Comment[bs]=Cholesterol Free Desktop Environment. Desktop okolina nalik na CDE
+Comment[ca]=El Cholesterol Free Desktop Environment. Un entorn d'escriptori amb reminiscències de CDE
+Comment[cs]=Svobodné grafické prostředí neobsahující cholesterol. Prostředí připomínající CDE
+Comment[csb]=Òkrãże pùltu szlachùjące za CDE
+Comment[cy]=Yr Amgylchedd Penbwrdd Di-Golesterol. Amgylchedd penbwrdd sy'n atgoffaol o CDE
+Comment[da]=Det kolesterolfrie desktopmiljø. Et desktopmiljø der minder om CDE
+Comment[de]=Cholesterol Free Desktop Environment. Graphische Arbeitsumgebung, die an CDE erinnert
+Comment[el]=Το Cholesterol Free Desktop Environment. Ένα περιβάλλον επιφάνειας εργασίας βασισμένο στο CDE
+Comment[eo]=La libera labortablo ĉirkaŭajo
+Comment[es]=El Cholesterol Free Desktop Environment, un entorno de escritorio que recuerda a CDE
+Comment[et]=Kolesteroolivaba töölaua keskkond, mis meenutab mitmeti CDE-d
+Comment[eu]=Kolesterolik gabeko mahaigain ingurunea. CDE gogorarazten duen mahaigaina
+Comment[fa]=محیط رومیزی آزاد Cholesterol. یادآور محیط رومیزی CDE
+Comment[fi]=Cholesterol Free -työpöytäympäristö. CDE:tä muistuttavatyöpöytäympäristö.
+Comment[fr]=The Cholesterol Free Desktop Environment. Un environnement de bureau rappelant CDE
+Comment[fy]=The Cholesterol Free Desktop Environment. In buroblêd omwrâld die tinken dat oan CDE
+Comment[gl]=O Cholesterol Free Desktop Environment. Un entorno de escritório reminiscente de CDE
+Comment[he]=The Cholesterol Free Desktop Environment. סביבת עבודה המזכירה את CDE
+Comment[hi]=कॉलेस्ट्रॉल रहित डेस्कटॉप माहौल. एक डेस्कटॉप माहौल जो सीडीई जैसा है
+Comment[hr]=Cholesterol Free Desktop Environment - Okruženje radne površine koje podsjeća na CDE
+Comment[hu]=Cholesterol Free Desktop Environment, egy a CDE-re emlékeztető ablakkezelő
+Comment[is]=Kólesterol-lausa skjáborðsumhverfið. Skjáborð sem líkist CDE
+Comment[it]=Il Cholesterol Free Desktop Environment. Un desktop environment che ricorda CDE
+Comment[ja]=Cholesterol Free Desktop Environment, CDE を思わせる、むだのないデスクトップ環境
+Comment[ka]=CDE-ს მაგვარი სამუშაო დაფა ქოლესტერინის გარეშე
+Comment[kk]=Cholesterol Free Desktop Environment. CDE-ге үқсас графикалық орта
+Comment[km]=Cholesterol Free Desktop Environment ។ បរិស្ថាន​ផ្ទៃតុ​ដែល​សម្អាង​លើ CDE
+Comment[lt]=Darbatalio aplinka „Be cholesterolio“. CDE primenanti darbastalio aplinka
+Comment[lv]=Darbvirsmas vide bez holesterīna. Darba virsmas vide, kas atgādina CDE
+Comment[mk]=Cholesterol Free Desktop Environment. Работна околина која потсетува на CDE
+Comment[ms]=Persekitaran Desktop Bebas Kolesterol. Mengenang kembali persekitaran desktop CDE
+Comment[mt]=Cholesterol Free Desktop Environment. Ambjent grafiku li jixbaħ lis-CDE
+Comment[nb]=Det kolesterolfrie skrivebordsmiljø. Et skrivebordsmiljø som minner om CDE
+Comment[nds]=De "Cholesterol Free Desktop Environment". En Schriefdisch-Ümgeven, de wat liek is to CDE
+Comment[ne]=कोलेस्ट्रोल रहित डेस्कटप परिवेश । CDE को स्मरणशील डेस्कटप परिवेश
+Comment[nl]=The Cholesterol Free Desktop Environment. Een desktop environment die herinnert aan CDE
+Comment[nn]=Cholesterol Free Desktop Environment. Eit skrivebordsmiljø som minner om CDE
+Comment[pa]=ਚੋਲੀਸਟੀਰੋਲ ਮੁਫਤ ਵਾਤਾਵਰਣ, ਇੱਕ CDE ਵਰਗਾ ਵਾਤਾਵਰਣ
+Comment[pl]=Środowisko pulpitu przypominające CDE
+Comment[pt]=O Cholesterol Free Desktop Environment. Um ambiente de trabalho com vestígios do CDE
+Comment[pt_BR]=Acrônimo para Cholesterol Free Desktop Environment (ou ambiente livre de colesterol), um ambiente de trabalho remanescente do CDE
+Comment[ro]=Cholesterol Free Desktop Environment. Un mediu grafic cu reminescente din CDE
+Comment[ru]="Не содержащая холестерина" рабочая среда, напоминающая CDE
+Comment[rw]=Ibikikije Ibiro Ubuntu Kolesiterole. Ibikikije ibiro nkumburwa bya CDE
+Comment[se]=The Cholesterol Free Desktop Environment. Čállinbeavdebiras mii muittuha CDE
+Comment[sk]=The Cholesterol Free Desktop Environment. Pracovné prostredie pripomínajúce CDE
+Comment[sl]=Cholesterol Free Desktop Environment. Namizno okolje, podobno okolju CDE
+Comment[sr]=„The Cholesterol Free Desktop Environment“. Радно окружење које подсећа на CDE
+Comment[sr@Latn]=„The Cholesterol Free Desktop Environment“. Radno okruženje koje podseća na CDE
+Comment[sv]=Den kolesterolfria skrivbordsmiljön. En skrivbordsmiljö som påminner om CDE
+Comment[ta]=கொலஸ்ட்ரால் இல்லாத மேல்மேசை சூழல். CDE பொருள்பொதிந்த மேல்மேசை சூழல்
+Comment[th]=สภาพแวดล้อมสำหรับเดสก์ทอปไร้คอเลสเตอรอล เป็นสภาพแวดล้อมสำหรับเดสก์ทอปที่เหลือมาจาก CDE
+Comment[tr]=Cholesterol Masaüstü Ortamı
+Comment[tt]=Holesterol Bulmağan Östäl Möxite. CDE küreneşendä
+Comment[uk]=The Cholesterol Free Desktop Environment. Графічне середовище, що нагадує CDE
+Comment[vi]=Môi trường Màn hình nền Không có Cholesterol. Một môi trường màn hình nền gợi nhớ lại CDE
+Comment[wa]=Li Libe Evironmint di Scribanne Colesterole (Cholesterol Free Desktop Environment). On evironmint d' sicribanne ki nos vént d' CDE
+Comment[zh_CN]=胆固醇自由桌面环境。CDE 桌面环境的追随者
+Comment[zh_TW]=Cholesterol 免費桌面環境。一個另人懷念的 CDE 桌面環境
diff --git a/tdm/kfrontend/sessions/xfce4.desktop b/tdm/kfrontend/sessions/xfce4.desktop
new file mode 100644
index 00000000..11b4097a
--- /dev/null
+++ b/tdm/kfrontend/sessions/xfce4.desktop
@@ -0,0 +1,72 @@
+[Desktop Entry]
+Type=XSession
+Exec=startxfce4
+TryExec=startxfce4
+Name=XFce 4
+Name[eo]=Facoj 4
+Name[hi]=एक्सएफसीई4
+Name[sv]=Xfce 4
+Name[te]=ఎక్స్ ఎఫ్ సి ఈ 4
+Comment=The Cholesterol Free Desktop Environment, version 4. A desktop environment reminiscent of CDE
+Comment[af]=Die Cholesterol Gratis Werkskerm Omgewing, weergawe 4. 'n Werkskerm omgewing wat op CDE gebaseer is
+Comment[be]=XFCE4 - Cholesterol Free Desktop Environment, version 4. Працоўнае асяроддзе, падобнае на CDE
+Comment[bn]=দি কলেস্টরল ফ্রী ডেস্কটপ এনভায়রনমেন্ট, ৪র্থ সংস্করণ। CDE-র কথা মনে করিয়ে দেয় এমন একটি ডেস্কটপ এনভায়রনমেন্ট
+Comment[bs]=Cholesterol Free Desktop Environment. Desktop okolina nalik na CDE
+Comment[ca]=L'entorn d'escriptori sense colesterol, versió 4. Un entorn d'escriptori que recorda a CDE
+Comment[cs]=Svobodné grafické prostředí neobsahující cholesterol verze 4. Prostředí připomínající CDE
+Comment[csb]=Cholesterol Free Desktop Environment, wersëjô 4 - graficzné òkrãże szlachùjące za CDE
+Comment[cy]=Yr Amgylchedd Penbwrdd Di-Golesterol, fersiwn 4. Amgylchedd penbwrdd sy'n atgoffaol o CDE
+Comment[da]=Det kolesterolfrie desktopmiljø, version 4. Et desktopmiljø der minder om CDE
+Comment[de]=Cholesterol Free Desktop Environment, Version 4. Benutzerumgebung in der Art von CDE
+Comment[el]=Το Cholesterol Free Desktop Environment, έκδοση 4. Ένα περιβάλλον επιφάνειας εργασίας βασισμένο στο CDE
+Comment[eo]=La libera labortablo ĉirkaŭajo 4
+Comment[es]=El Cholesterol Free Desktop Environment, versión 4. Un entorno de escritorio que recuerda a CDE
+Comment[et]=Kolesteroolivaba töölaua keskkond (versioon 4), mis meenutab mitmeti CDE-d
+Comment[eu]=Kolesterolik gabeko mahaigain ingurunea, 4 bertsioa. CDE gogorarazten duen mahaigaina
+Comment[fa]=محیط رومیزی آزاد Cholesterol، نسخه ۴. یادآور محیط رومیزی CDE
+Comment[fi]=Cholesterol Free -työpöytäympäristö. CDE:tä muistuttavatyöpöytäympäristö.
+Comment[fr]=The Cholesterol Free Desktop Environment, version 4. Un environnement de bureau rappelant CDE
+Comment[fy]=De Cholesterol Free Desktop Environment, ferzje 4. In buroblêd omwrâld die tinken dat oan CDE
+Comment[gl]=O Cholesterol Free Desktop Environment, versión 4. Un entorno de escritório reminiscencia de CDE
+Comment[he]=The Cholesterol Free Desktop Environment. גרסה 4, סביבת עבודה המזכירה את CDE
+Comment[hi]=कोलेस्ट्रॉल मुक्त डेस्कटॉप वातावरण, संस्करण 4. सीडीई की याद दिलाता एक डेस्कटॉप वातावरण
+Comment[hr]=Cholesterol Free Desktop Environment verzija 4 - Okruženje radne površine koje podsjeća na CDE
+Comment[hu]=The Cholesterol Free Desktop Environment, 4-es verzió. Egy CDE-szerű ablakkezelő
+Comment[is]=Kólesterol-lausa skjáborðsumhverfið, útgáfa 4. Skjáborð sem líkist CDE
+Comment[it]=Il Cholesterol Free Desktop Environment, versione 4. Un desktop environment che ricorda CDE
+Comment[ja]=Cholesterol Free Desktop Environment, version 4, CDE を思わせる、むだのないデスクトップ環境
+Comment[ka]=CDE-ს მაგვარი უქოლესტერინო სამუშაო დაფა xfce 4
+Comment[kk]=Cholesterol Free Desktop Environment, 4-нұсқа. CDE-ге ұқсас графикалық орта
+Comment[km]=Cholesterol Free Desktop Environment កំណែ 4 ។ បរិស្ថាន​ផ្ទៃតុ​ដែល​សម្អាង​លើ CDE
+Comment[lt]=Darbatalio aplinka „Be cholesterolio“ , 4 versija. CDE primenanti darbastalio aplinka
+Comment[lv]=Darbvirsmas vide bez holesterīna, versija 4. Darbavirsmas vide, kas atgādina CDE
+Comment[mk]=Cholesterol Free Desktop Environment, верзија 4. Работна околина која потсетува на CDE
+Comment[ms]=Persekitaran Desktop Bebas Kolesterol, versi 4. Mengingatkan kembali persekitaran desktop CDE
+Comment[mt]=Cholesterol Free Desktop Environment (v4). Ambjent grafiku li jixbaħ lis-CDE
+Comment[nb]=Det kolesterolfrie skrivebordet, versjon 4. Et skrivebordsmiljø som minner om CDE
+Comment[nds]=De "Cholesterol Free Desktop Environment", Verschoon 4. En Schriefdisch-Ümgeven, de wat liek is to CDE
+Comment[ne]=कोलेस्ट्रोल रहित डेस्कटप परिवेश, संस्करण ४ । CDE को स्मरणशील डेस्कटप परिवेश
+Comment[nl]=De Cholesterol Free Desktop Environment, versie 4. Een desktop environment die herinnert aan CDE
+Comment[nn]=Cholesterol Free Desktop Environment. Eit skrivebordsmiljø som minner om CDE
+Comment[pa]=ਚੋਲੀਸਟੀਰੋਲ ਮੁਫਤ ਵਾਤਾਵਰਣ, ਵਰਜਨ 4 ਇੱਕ CDE ਵਰਗਾ ਵਾਤਾਵਰਣ
+Comment[pl]=Cholesterol Free Desktop Environment, wersja 4 - środowisko graficzne podobne do CDE.
+Comment[pt]=O Cholesterol Free Desktop Environment, versão 4. Um ambiente de trabalho com vestígios do CDE
+Comment[pt_BR]=Acrônimo para Cholesterol Free Desktop Environment (ou ambiente livre de colesterol), versão 4; um ambiente de trabalho remanescente do CDE
+Comment[ro]=Cholesterol Free Desktop Environment, versiunea 4. Un mediu grafic cu reminescente din CDE
+Comment[ru]="Не содержащая холестерина" рабочая среда xfce версии 4, напоминающая CDE
+Comment[rw]=Ibikikije Ibiro Ubuntu Kolesiterole, verisiyo 4. Ibikikije ibiro nkumburwa bya CDE
+Comment[se]=The Cholesterol Free Desktop Environment, version 4. Čállinbeavdebiras mii muittuha CDE
+Comment[sk]=The Cholesterol Free Desktop Environment verzia 4. Pracovné prostredie pripomínajúce CDE
+Comment[sl]=Cholesterol Free Desktop Environment, različica 4. Namizno okolje, podobno okolju CDE
+Comment[sr]=„The Cholesterol Free Desktop Environment“ 4. издање. Радно окружење које подсећа на CDE
+Comment[sr@Latn]=„The Cholesterol Free Desktop Environment“ 4. izdanje. Radno okruženje koje podseća na CDE
+Comment[sv]=Den kolesterolfria skrivbordsmiljön, version 4. En skrivbordsmiljö som påminner om CDE
+Comment[ta]=கொலஸ்ட்ரால் இல்லாத மேல்மேசை சூழல். பதிப்பு 4. CDE பொருள்பொதிந்த மேல்மேசை சூழல்
+Comment[th]=สภาพแวดล้อมสำหรับเดสก์ทอปแบบไร้คอเลสเตอรอล เวอร์ชั่น 4 เป็นสภาพแวดล้อมสำหรับเดสก์ทอปที่เหลือมาจาก CDE
+Comment[tr]=Cholesterol Ücretsiz Masaüstü Ortamı, sürüm 4. CDE'nin benzeri olan masaüstü ortamı
+Comment[tt]=Holesterol Bulmağan Östäl Möxiteneñ 4. söreme. CDE küreneşendä
+Comment[uk]=The Cholesterol Free Desktop Environment, версія 4. Графічне середовище, що нагадує CDE
+Comment[vi]=Môi trường Màn hình nền Không có Cholesterol, phiên bản 4. Một môi trường màn hình nền gợi nhớ lại CDE
+Comment[wa]=Li Libe Evironmint di Scribanne Colesterole (Cholesterol Free Desktop Environment), modêye 4. On evironmint d' sicribanne ki nos vént d' CDE
+Comment[zh_CN]=胆固醇自由桌面环境,版本 4。CDE 桌面环境的追随者
+Comment[zh_TW]=Cholesterol 免費桌面環境,第 4 版。一個另人懷念的 CDE 桌面環境
diff --git a/tdm/kfrontend/tdm_config.c b/tdm/kfrontend/tdm_config.c
new file mode 100644
index 00000000..48f31632
--- /dev/null
+++ b/tdm/kfrontend/tdm_config.c
@@ -0,0 +1,1477 @@
+/*
+
+Read options from tdmrc
+
+Copyright (C) 2001-2005 Oswald Buddenhagen <ossi@kde.org>
+
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#include <config.h>
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include <errno.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <grp.h>
+#ifdef _POSIX_PRIORITY_SCHEDULING
+# include <sched.h>
+#endif
+
+#include <X11/X.h>
+#ifdef FamilyInternet6
+# define IPv6
+#endif
+
+#include <greet.h>
+#include <config.ci>
+
+/*
+ * Section/Entry definition structs
+ */
+
+typedef struct Ent {
+ const char *name;
+ int id;
+ void *ptr;
+ const char *def;
+} Ent;
+
+typedef struct Sect {
+ const char *name;
+ Ent *ents;
+ int numents;
+} Sect;
+
+/*
+ * Parsed ini file structs
+ */
+
+typedef struct Entry {
+ struct Entry *next;
+ const char *val;
+ Ent *ent;
+ int vallen;
+ int line;
+} Entry;
+
+typedef struct Section {
+ struct Section *next;
+ Entry *entries;
+ Sect *sect;
+ const char *name, *dname, *dhost, *dnum, *dclass;
+ int nlen, dlen, dhostl, dnuml, dclassl;
+} Section;
+
+
+/*
+ * Split up display-name/-class for fast comparison
+ */
+typedef struct DSpec {
+ const char *dhost, *dnum, *dclass;
+ int dhostl, dnuml, dclassl;
+} DSpec;
+
+
+/*
+ * Config value storage structures
+ */
+
+typedef struct Value {
+ const char *ptr;
+ int len;
+} Value;
+
+typedef struct Val {
+ Value val;
+ int id;
+} Val;
+
+typedef struct ValArr {
+ Val *ents;
+ int nents, esiz, nchars, nptrs;
+} ValArr;
+
+
+static void *Malloc( size_t size );
+static void *Realloc( void *ptr, size_t size );
+
+#define PRINT_QUOTES
+#define LOG_NAME "tdm_config"
+#define LOG_DEBUG_MASK DEBUG_CONFIG
+#define LOG_PANIC_EXIT 1
+#define STATIC static
+#include <printf.c>
+
+
+static void *
+Malloc( size_t size )
+{
+ void *ret;
+
+ if (!(ret = malloc( size )))
+ LogOutOfMem();
+ return ret;
+}
+
+static void *
+Realloc( void *ptr, size_t size )
+{
+ void *ret;
+
+ if (!(ret = realloc( ptr, size )) && size)
+ LogOutOfMem();
+ return ret;
+}
+
+
+static void
+MkDSpec( DSpec *spec, const char *dname, const char *dclass )
+{
+ spec->dhost = dname;
+ for (spec->dhostl = 0; dname[spec->dhostl] != ':'; spec->dhostl++);
+ spec->dnum = dname + spec->dhostl + 1;
+ spec->dnuml = strlen( spec->dnum );
+ spec->dclass = dclass;
+ spec->dclassl = strlen( dclass );
+}
+
+
+static int rfd, wfd;
+
+static int
+Reader( void *buf, int count )
+{
+ int ret, rlen;
+
+ for (rlen = 0; rlen < count; ) {
+ dord:
+ ret = read( rfd, (void *)((char *)buf + rlen), count - rlen );
+ if (ret < 0) {
+ if (errno == EINTR)
+ goto dord;
+ if (errno == EAGAIN)
+ break;
+ return -1;
+ }
+ if (!ret)
+ break;
+ rlen += ret;
+ }
+ return rlen;
+}
+
+static void
+GRead( void *buf, int count )
+{
+ if (Reader( buf, count ) != count)
+ LogPanic( "Can't read from core\n" );
+}
+
+static void
+GWrite( const void *buf, int count )
+{
+ if (write( wfd, buf, count ) != count)
+ LogPanic( "Can't write to core\n" );
+#ifdef _POSIX_PRIORITY_SCHEDULING
+ if ((debugLevel & DEBUG_HLPCON))
+ sched_yield();
+#endif
+}
+
+static void
+GSendInt( int val )
+{
+ GWrite( &val, sizeof(val) );
+}
+
+static void
+GSendStr( const char *buf )
+{
+ if (buf) {
+ int len = strlen( buf ) + 1;
+ GWrite( &len, sizeof(len) );
+ GWrite( buf, len );
+ } else
+ GWrite( &buf, sizeof(int));
+}
+
+static void
+GSendNStr( const char *buf, int len )
+{
+ int tlen = len + 1;
+ GWrite( &tlen, sizeof(tlen) );
+ GWrite( buf, len );
+ GWrite( "", 1 );
+}
+
+#ifdef XDMCP
+static void
+GSendArr( int len, const char *data )
+{
+ GWrite( &len, sizeof(len) );
+ GWrite( data, len );
+}
+#endif
+
+static int
+GRecvCmd( int *val )
+{
+ if (Reader( val, sizeof(*val) ) != sizeof(*val))
+ return 0;
+ return 1;
+}
+
+static int
+GRecvInt()
+{
+ int val;
+
+ GRead( &val, sizeof(val) );
+ return val;
+}
+
+static char *
+GRecvStr()
+{
+ int len;
+ char *buf;
+
+ len = GRecvInt();
+ if (!len)
+ return 0;
+ if (!(buf = malloc( len )))
+ LogPanic( "No memory for read buffer" );
+ GRead( buf, len );
+ return buf;
+}
+
+
+/* #define WANT_CLOSE 1 */
+
+typedef struct File {
+ char *buf, *eof, *cur;
+#if defined(HAVE_MMAP) && defined(WANT_CLOSE)
+ int ismapped;
+#endif
+} File;
+
+static int
+readFile( File *file, const char *fn, const char *what )
+{
+ int fd;
+ off_t flen;
+
+ if ((fd = open( fn, O_RDONLY )) < 0) {
+ LogInfo( "Cannot open %s file %s\n", what, fn );
+ return 0;
+ }
+
+ flen = lseek( fd, 0, SEEK_END );
+#ifdef HAVE_MMAP
+# ifdef WANT_CLOSE
+ file->ismapped = 0;
+# endif
+ file->buf = mmap( 0, flen + 1, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0 );
+# ifdef WANT_CLOSE
+ if (file->buf)
+ file->ismapped = 1;
+ else
+# else
+ if (!file->buf)
+# endif
+#endif
+ {
+ if (!(file->buf = Malloc( flen + 1 ))) {
+ close( fd );
+ return 0;
+ }
+ lseek( fd, 0, SEEK_SET );
+ if (read( fd, file->buf, flen ) != flen) {
+ free( file->buf );
+ LogError( "Cannot read %s file %s\n", what, fn );
+ close( fd );
+ return 0;
+ }
+ }
+ file->eof = (file->cur = file->buf) + flen;
+ close( fd );
+ return 1;
+}
+
+#ifdef WANT_CLOSE
+static void
+freeBuf( File *file )
+{
+# ifdef HAVE_MMAP
+ if (file->ismapped)
+ munmap( file->buf, file->eof - file->buf + 1 );
+ else
+# endif
+ free( file->buf );
+}
+#endif
+
+CONF_READ_VARS
+
+#define C_MTYPE_MASK 0x30000000
+# define C_PATH 0x10000000 /* C_TYPE_STR is a path spec */
+# define C_BOOL 0x10000000 /* C_TYPE_INT is a boolean */
+# define C_ENUM 0x20000000 /* C_TYPE_INT is an enum (option) */
+# define C_GRP 0x30000000 /* C_TYPE_INT is a group spec */
+#define C_INTERNAL 0x40000000 /* don't expose to core */
+#define C_CONFIG 0x80000000 /* process only for finding deps */
+
+#ifdef XDMCP
+static int
+PrequestPort( Value *retval )
+{
+ if (!VxdmcpEnable.ptr) {
+ retval->ptr = (char *)0;
+ return 1;
+ }
+ return 0;
+}
+#endif
+
+static Value
+ emptyStr = { "", 1 },
+ nullValue = { 0, 0 },
+ emptyArgv = { (char *)&nullValue, 0 };
+
+static int
+PnoPassUsers( Value *retval )
+{
+ if (!VnoPassEnable.ptr) {
+ *retval = emptyArgv;
+ return 1;
+ }
+ return 0;
+}
+
+static int
+PautoLoginX( Value *retval )
+{
+ if (!VautoLoginEnable.ptr) {
+ *retval = emptyStr;
+ return 1;
+ }
+ return 0;
+}
+
+CONF_READ_ENTRIES
+
+static const char *tdmrc = TDMCONF "/tdmrc";
+static const char *tdmrc_dist = TDMCONF "/tdmdistrc";
+
+static Section *rootsec;
+
+static void
+ReadConf()
+{
+ const char *nstr, *dstr, *cstr, *dhost, *dnum, *dclass;
+ char *s, *e, *st, *en, *ek, *sl, *pt;
+ Section *cursec;
+ Entry *curent;
+ Ent *ce;
+ int nlen, dlen, clen, dhostl, dnuml, dclassl;
+ int i, line, sectmoan, restl;
+ File file;
+ static int confread;
+
+ if (confread)
+ return;
+ confread = 1;
+
+ Debug( "reading config %s ...\n", tdmrc_dist );
+ if (!readFile( &file, tdmrc_dist, "master configuration" )) {
+ Debug( "reading config %s ...\n", tdmrc );
+ if (!readFile( &file, tdmrc, "master configuration" ))
+ return;
+ }
+ else {
+ tdmrc = tdmrc_dist;
+ }
+
+ for (s = file.buf, line = 0, cursec = 0, sectmoan = 1; s < file.eof; s++) {
+ line++;
+
+ while ((s < file.eof) && isspace( *s ) && (*s != '\n'))
+ s++;
+
+ if ((s < file.eof) && ((*s == '\n') || (*s == '#'))) {
+ sktoeol:
+ while ((s < file.eof) && (*s != '\n'))
+ s++;
+ continue;
+ }
+ sl = s;
+
+ if (*s == '[') {
+ sectmoan = 0;
+ while ((s < file.eof) && (*s != '\n'))
+ s++;
+ e = s - 1;
+ while ((e > sl) && isspace( *e ))
+ e--;
+ if (*e != ']') {
+ cursec = 0;
+ LogError( "Invalid section header at %s:%d\n", tdmrc, line );
+ continue;
+ }
+ nstr = sl + 1;
+ nlen = e - nstr;
+ for (cursec = rootsec; cursec; cursec = cursec->next)
+ if (nlen == cursec->nlen &&
+ !memcmp( nstr, cursec->name, nlen ))
+ {
+ LogInfo( "Multiple occurrences of section [%.*s] in %s. "
+ "Consider merging them.\n", nlen, nstr, tdmrc );
+ goto secfnd;
+ }
+ if (nstr[0] == 'X' && nstr[1] == '-') {
+ cstr = nstr + nlen;
+ clen = 0;
+ while (++clen, *--cstr != '-');
+ if (cstr == nstr + 1)
+ goto illsec;
+ dstr = nstr + 2;
+ dlen = nlen - clen - 2;
+ dhost = dstr;
+ dhostl = 0;
+ for (restl = dlen; restl; restl--) {
+ if (dhost[dhostl] == ':') {
+ dnum = dhost + dhostl + 1;
+ dnuml = 0;
+ for (restl--; restl; restl--) {
+ if (dnum[dnuml] == '_') {
+ dclass = dnum + dnuml + 1;
+ dclassl = restl;
+ goto gotall;
+ }
+ dnuml++;
+ }
+ goto gotnum;
+ }
+ dhostl++;
+ }
+ dnum = "*";
+ dnuml = 1;
+ gotnum:
+ dclass = "*";
+ dclassl = 1;
+ gotall: ;
+ } else {
+ if (nstr[0] == '-')
+ goto illsec;
+ dstr = 0;
+ dlen = 0;
+ dhost = 0;
+ dhostl = 0;
+ dnum = 0;
+ dnuml = 0;
+ dclass = 0;
+ dclassl = 0;
+ cstr = nstr;
+ clen = nlen;
+ }
+ for (i = 0; i < as(allSects); i++)
+ if ((int)strlen( allSects[i]->name ) == clen &&
+ !memcmp( allSects[i]->name, cstr, clen ))
+ goto newsec;
+ illsec:
+ cursec = 0;
+ LogError( "Unrecognized section name [%.*s] at %s:%d\n",
+ nlen, nstr, tdmrc, line );
+ continue;
+ newsec:
+ if (!(cursec = Malloc( sizeof(*cursec) )))
+ return;
+ cursec->name = nstr;
+ cursec->nlen = nlen;
+ cursec->dname = dstr;
+ cursec->dlen = dlen;
+ cursec->dhost = dhost;
+ cursec->dhostl = dhostl;
+ cursec->dnum = dnum;
+ cursec->dnuml = dnuml;
+ cursec->dclass = dclass;
+ cursec->dclassl = dclassl;
+ cursec->sect = allSects[i];
+ cursec->entries = 0;
+ cursec->next = rootsec;
+ rootsec = cursec;
+ /*Debug( "now in section [%.*s], dpy '%.*s', core '%.*s'\n",
+ nlen, nstr, dlen, dstr, clen, cstr );*/
+ secfnd:
+ continue;
+ }
+
+ if (!cursec) {
+ if (sectmoan) {
+ sectmoan = 0;
+ LogError( "Entry outside any section at %s:%d", tdmrc, line );
+ }
+ goto sktoeol;
+ }
+
+ for (; (s < file.eof) && (*s != '\n'); s++)
+ if (*s == '=')
+ goto haveeq;
+ LogError( "Invalid entry (missing '=') at %s:%d\n", tdmrc, line );
+ continue;
+
+ haveeq:
+ for (ek = s - 1; ; ek--) {
+ if (ek < sl) {
+ LogError( "Invalid entry (empty key) at %s:%d\n", tdmrc, line );
+ goto sktoeol;
+ }
+ if (!isspace( *ek ))
+ break;
+ }
+
+ s++;
+ while ((s < file.eof) && isspace( *s ) && (*s != '\n'))
+ s++;
+ for (pt = st = en = s; s < file.eof && *s != '\n'; s++) {
+ if (*s == '\\') {
+ s++;
+ if (s >= file.eof || *s == '\n') {
+ LogError( "Trailing backslash at %s:%d\n", tdmrc, line );
+ break;
+ }
+ switch (*s) {
+ case 's': *pt++ = ' '; break;
+ case 't': *pt++ = '\t'; break;
+ case 'n': *pt++ = '\n'; break;
+ case 'r': *pt++ = '\r'; break;
+ case '\\': *pt++ = '\\'; break;
+ default: *pt++ = '\\'; *pt++ = *s; break;
+ }
+ en = pt;
+ } else {
+ *pt++ = *s;
+ if (*s != ' ' && *s != '\t')
+ en = pt;
+ }
+ }
+
+ nstr = sl;
+ nlen = ek - sl + 1;
+ /*Debug( "read entry '%.*s'='%.*s'\n", nlen, nstr, en - st, st );*/
+ for (i = 0; i < cursec->sect->numents; i++) {
+ ce = cursec->sect->ents + i;
+ if ((int)strlen( ce->name ) == nlen &&
+ !memcmp( ce->name, nstr, nlen ))
+ goto keyok;
+ }
+ LogError( "Unrecognized key '%.*s' in section [%.*s] at %s:%d\n",
+ nlen, nstr, cursec->nlen, cursec->name, tdmrc, line );
+ continue;
+ keyok:
+ for (curent = cursec->entries; curent; curent = curent->next)
+ if (ce == curent->ent) {
+ LogError( "Multiple occurrences of key '%s' in section [%.*s]"
+ " of %s\n",
+ ce->name, cursec->nlen, cursec->name, tdmrc );
+ goto keyfnd;
+ }
+ if (!(curent = Malloc( sizeof(*curent) )))
+ return;
+ curent->ent = ce;
+ curent->line = line;
+ curent->val = st;
+ curent->vallen = en - st;
+ curent->next = cursec->entries;
+ cursec->entries = curent;
+ keyfnd:
+ continue;
+ }
+}
+
+static Entry *
+FindGEnt( int id )
+{
+ Section *cursec;
+ Entry *curent;
+
+ for (cursec = rootsec; cursec; cursec = cursec->next)
+ if (!cursec->dname)
+ for (curent = cursec->entries; curent; curent = curent->next)
+ if (curent->ent->id == id) {
+ Debug( "line %d: %s = %'.*s\n",
+ curent->line, curent->ent->name,
+ curent->vallen, curent->val );
+ return curent;
+ }
+ return 0;
+}
+
+/* Display name match scoring:
+ * - class (any/exact) -> 0/1
+ * - number (any/exact) -> 0/2
+ * - host (any/nonempty/trail/exact) -> 0/4/8/12
+ */
+static Entry *
+FindDEnt( int id, DSpec *dspec )
+{
+ Section *cursec, *bestsec;
+ Entry *curent, *bestent;
+ int score, bestscore;
+
+ bestscore = -1, bestent = 0;
+ for (cursec = rootsec; cursec; cursec = cursec->next)
+ if (cursec->dname) {
+ score = 0;
+ if (cursec->dclassl != 1 || cursec->dclass[0] != '*') {
+ if (cursec->dclassl == dspec->dclassl &&
+ !memcmp( cursec->dclass, dspec->dclass, dspec->dclassl ))
+ score = 1;
+ else
+ continue;
+ }
+ if (cursec->dnuml != 1 || cursec->dnum[0] != '*') {
+ if (cursec->dnuml == dspec->dnuml &&
+ !memcmp( cursec->dnum, dspec->dnum, dspec->dnuml ))
+ score += 2;
+ else
+ continue;
+ }
+ if (cursec->dhostl != 1 || cursec->dhost[0] != '*') {
+ if (cursec->dhostl == 1 && cursec->dhost[0] == '+') {
+ if (dspec->dhostl)
+ score += 4;
+ else
+ continue;
+ } else if (cursec->dhost[0] == '.') {
+ if (cursec->dhostl < dspec->dhostl &&
+ !memcmp( cursec->dhost,
+ dspec->dhost + dspec->dhostl - cursec->dhostl,
+ cursec->dhostl ))
+ score += 8;
+ else
+ continue;
+ } else {
+ if (cursec->dhostl == dspec->dhostl &&
+ !memcmp( cursec->dhost, dspec->dhost, dspec->dhostl ))
+ score += 12;
+ else
+ continue;
+ }
+ }
+ if (score > bestscore) {
+ for (curent = cursec->entries; curent; curent = curent->next)
+ if (curent->ent->id == id) {
+ bestent = curent;
+ bestsec = cursec;
+ bestscore = score;
+ break;
+ }
+ }
+ }
+ if (bestent)
+ Debug( "line %d: %.*s:%.*s_%.*s/%s = %'.*s\n", bestent->line,
+ bestsec->dhostl, bestsec->dhost,
+ bestsec->dnuml, bestsec->dnum,
+ bestsec->dclassl, bestsec->dclass,
+ bestent->ent->name, bestent->vallen, bestent->val );
+ return bestent;
+}
+
+static const char *
+CvtValue( Ent *et, Value *retval, int vallen, const char *val, char **eopts )
+{
+ Value *ents;
+ int i, b, e, tlen, nents, esiz;
+ char buf[80];
+
+ switch (et->id & C_TYPE_MASK) {
+ case C_TYPE_INT:
+ for (i = 0; i < vallen && i < (int)sizeof(buf) - 1; i++)
+ buf[i] = tolower( val[i] );
+ buf[i] = 0;
+ if ((et->id & C_MTYPE_MASK) == C_BOOL) {
+ if (!strcmp( buf, "true" ) ||
+ !strcmp( buf, "on" ) ||
+ !strcmp( buf, "yes" ) ||
+ !strcmp( buf, "1" ))
+ retval->ptr = (char *)1;
+ else if (!strcmp( buf, "false" ) ||
+ !strcmp( buf, "off" ) ||
+ !strcmp( buf, "no" ) ||
+ !strcmp( buf, "0" ))
+ retval->ptr = (char *)0;
+ else
+ return "boolean";
+ return 0;
+ } else if ((et->id & C_MTYPE_MASK) == C_ENUM) {
+ for (i = 0; eopts[i]; i++)
+ if (!memcmp( eopts[i], val, vallen ) && !eopts[i][vallen]) {
+ retval->ptr = (char *)i;
+ return 0;
+ }
+ return "option";
+ } else if ((et->id & C_MTYPE_MASK) == C_GRP) {
+ struct group *ge;
+ if ((ge = getgrnam( buf ))) {
+ retval->ptr = (char *)ge->gr_gid;
+ return 0;
+ }
+ }
+ retval->ptr = 0;
+ if (sscanf( buf, "%li", &retval->ptr ) != 1)
+ return "integer";
+ return 0;
+ case C_TYPE_STR:
+ retval->ptr = val;
+ retval->len = vallen + 1;
+ if ((et->id & C_MTYPE_MASK) == C_PATH)
+ if (vallen && val[vallen-1] == '/')
+ retval->len--;
+ return 0;
+ case C_TYPE_ARGV:
+ if (!(ents = Malloc( sizeof(Value) * (esiz = 10) )))
+ return 0;
+ for (nents = 0, tlen = 0, i = 0; ; i++) {
+ for (; i < vallen && isspace( val[i] ); i++);
+ for (b = i; i < vallen && val[i] != ','; i++);
+ if (b == i)
+ break;
+ for (e = i; e > b && isspace( val[e - 1] ); e--);
+ if (esiz < nents + 2) {
+ Value *entsn = Realloc( ents,
+ sizeof(Value) * (esiz = esiz * 2 + 1) );
+ if (!nents)
+ break;
+ ents = entsn;
+ }
+ ents[nents].ptr = val + b;
+ ents[nents].len = e - b;
+ nents++;
+ tlen += e - b + 1;
+ }
+ ents[nents].ptr = 0;
+ retval->ptr = (char *)ents;
+ retval->len = tlen;
+ return 0;
+ default:
+ LogError( "Internal error: unknown value type in id %#x\n", et->id );
+ return 0;
+ }
+}
+
+static void
+GetValue( Ent *et, DSpec *dspec, Value *retval, char **eopts )
+{
+ Entry *ent;
+ const char *errs;
+
+/* Debug( "Getting value %#x\n", et->id );*/
+ if (dspec)
+ ent = FindDEnt( et->id, dspec );
+ else
+ ent = FindGEnt( et->id );
+ if (ent) {
+ if (!(errs = CvtValue( et, retval, ent->vallen, ent->val, eopts )))
+ return;
+ LogError( "Invalid %s value '%.*s' at %s:%d\n",
+ errs, ent->vallen, ent->val, tdmrc, ent->line );
+ }
+ Debug( "default: %s = %'s\n", et->name, et->def );
+ if ((errs = CvtValue( et, retval, strlen( et->def ), et->def, eopts )))
+ LogError( "Internal error: invalid default %s value '%s' for key %s\n",
+ errs, et->def, et->name );
+}
+
+static int
+AddValue( ValArr *va, int id, Value *val )
+{
+ int nu;
+
+/* Debug( "Addig value %#x\n", id );*/
+ if (va->nents == va->esiz) {
+ va->ents = Realloc( va->ents, sizeof(Val) * (va->esiz += 50) );
+ if (!va->ents)
+ return 0;
+ }
+ va->ents[va->nents].id = id;
+ va->ents[va->nents].val = *val;
+ va->nents++;
+ switch (id & C_TYPE_MASK) {
+ case C_TYPE_INT:
+ break;
+ case C_TYPE_STR:
+ va->nchars += val->len;
+ break;
+ case C_TYPE_ARGV:
+ va->nchars += val->len;
+ for (nu = 0; ((Value *)val->ptr)[nu++].ptr; );
+ va->nptrs += nu;
+ break;
+ }
+ return 1;
+}
+
+static void
+CopyValues( ValArr *va, Sect *sec, DSpec *dspec, int isconfig )
+{
+ Value val;
+ int i;
+
+ Debug( "getting values for section class [%s]\n", sec->name );
+ for (i = 0; i < sec->numents; i++) {
+/*Debug ("value %#x\n", sec->ents[i].id);*/
+ if ((sec->ents[i].id & (int)C_CONFIG) != isconfig)
+ ;
+ else if (sec->ents[i].id & C_INTERNAL) {
+ GetValue( sec->ents + i, dspec, ((Value *)sec->ents[i].ptr), 0 );
+ } else {
+ if (((sec->ents[i].id & C_MTYPE_MASK) == C_ENUM) ||
+ !sec->ents[i].ptr ||
+ !((int (*)( Value * ))sec->ents[i].ptr)(&val)) {
+ GetValue( sec->ents + i, dspec, &val,
+ (char **)sec->ents[i].ptr );
+ }
+ if (!AddValue( va, sec->ents[i].id, &val ))
+ break;
+ }
+ }
+ return;
+}
+
+static void
+SendValues( ValArr *va )
+{
+ Value *cst;
+ int i, nu;
+
+ GSendInt( va->nents );
+ GSendInt( va->nptrs );
+ GSendInt( 0/*va->nints*/ );
+ GSendInt( va->nchars );
+ for (i = 0; i < va->nents; i++) {
+ GSendInt( va->ents[i].id & ~C_PRIVATE );
+ switch (va->ents[i].id & C_TYPE_MASK) {
+ case C_TYPE_INT:
+ GSendInt( (int)va->ents[i].val.ptr );
+ break;
+ case C_TYPE_STR:
+ GSendNStr( va->ents[i].val.ptr, va->ents[i].val.len - 1 );
+ break;
+ case C_TYPE_ARGV:
+ cst = (Value *)va->ents[i].val.ptr;
+ for (nu = 0; cst[nu].ptr; nu++);
+ GSendInt( nu );
+ for (; cst->ptr; cst++)
+ GSendNStr( cst->ptr, cst->len );
+ break;
+ }
+ }
+}
+
+
+#ifdef XDMCP
+static char *
+ReadWord( File *file, int *len, int EOFatEOL )
+{
+ char *wordp, *wordBuffer;
+ int quoted;
+ char c;
+
+ rest:
+ wordp = wordBuffer = file->cur;
+ mloop:
+ quoted = 0;
+ qloop:
+ if (file->cur == file->eof) {
+ doeow:
+ if (wordp == wordBuffer)
+ return 0;
+ retw:
+ *wordp = '\0';
+ *len = wordp - wordBuffer;
+ return wordBuffer;
+ }
+ c = *file->cur++;
+ switch (c) {
+ case '#':
+ if (quoted)
+ break;
+ do {
+ if (file->cur == file->eof)
+ goto doeow;
+ c = *file->cur++;
+ } while (c != '\n');
+ case '\0':
+ case '\n':
+ if (EOFatEOL && !quoted) {
+ file->cur--;
+ goto doeow;
+ }
+ if (wordp != wordBuffer) {
+ file->cur--;
+ goto retw;
+ }
+ goto rest;
+ case ' ':
+ case '\t':
+ if (wordp != wordBuffer)
+ goto retw;
+ goto rest;
+ case '\\':
+ if (!quoted) {
+ quoted = 1;
+ goto qloop;
+ }
+ break;
+ }
+ *wordp++ = c;
+ goto mloop;
+}
+
+#define ALIAS_CHARACTER '%'
+#define EQUAL_CHARACTER '='
+#define NEGATE_CHARACTER '!'
+#define CHOOSER_STRING "CHOOSER"
+#define BROADCAST_STRING "BROADCAST"
+#define NOBROADCAST_STRING "NOBROADCAST"
+#define LISTEN_STRING "LISTEN"
+#define WILDCARD_STRING "*"
+
+typedef struct hostEntry {
+ struct hostEntry *next;
+ int type;
+ union _hostOrAlias {
+ char *aliasPattern;
+ char *hostPattern;
+ struct _display {
+ int connectionType;
+ int hostAddrLen;
+ char *hostAddress;
+ } displayAddress;
+ } entry;
+} HostEntry;
+
+typedef struct listenEntry {
+ struct listenEntry *next;
+ int iface;
+ int mcasts;
+ int nmcasts;
+} ListenEntry;
+
+typedef struct aliasEntry {
+ struct aliasEntry *next;
+ char *name;
+ HostEntry **pHosts;
+ int hosts;
+ int nhosts;
+ int hasBad;
+} AliasEntry;
+
+typedef struct aclEntry {
+ struct aclEntry *next;
+ HostEntry **pEntries;
+ int entries;
+ int nentries;
+ HostEntry **pHosts;
+ int hosts;
+ int nhosts;
+ int flags;
+} AclEntry;
+
+
+static int
+HasGlobCharacters( char *s )
+{
+ for (;;)
+ switch (*s++) {
+ case '?':
+ case '*':
+ return 1;
+ case '\0':
+ return 0;
+ }
+}
+
+#define PARSE_ALL 0
+#define PARSE_NO_BCAST 1
+#define PARSE_NO_PAT 2
+#define PARSE_NO_ALIAS 4
+
+static int
+ParseHost( int *nHosts, HostEntry ***hostPtr, int *nChars,
+ char *hostOrAlias, int len, int parse )
+{
+#if defined(IPv6) && defined(AF_INET6)
+ struct addrinfo *ai;
+#else
+ struct hostent *hostent;
+#endif
+ void *addr;
+ int addr_type, addr_len;
+
+ if (!(**hostPtr = (HostEntry *)Malloc( sizeof(HostEntry))))
+ return 0;
+ if (!(parse & PARSE_NO_BCAST) && !strcmp( hostOrAlias, BROADCAST_STRING ))
+ {
+ (**hostPtr)->type = HOST_BROADCAST;
+ }
+ else if (!(parse & PARSE_NO_ALIAS) && *hostOrAlias == ALIAS_CHARACTER)
+ {
+ (**hostPtr)->type = HOST_ALIAS;
+ (**hostPtr)->entry.aliasPattern = hostOrAlias + 1;
+ *nChars += len;
+ }
+ else if (!(parse & PARSE_NO_PAT) && HasGlobCharacters( hostOrAlias ))
+ {
+ (**hostPtr)->type = HOST_PATTERN;
+ (**hostPtr)->entry.hostPattern = hostOrAlias;
+ *nChars += len + 1;
+ }
+ else
+ {
+ (**hostPtr)->type = HOST_ADDRESS;
+#if defined(IPv6) && defined(AF_INET6)
+ if (getaddrinfo( hostOrAlias, NULL, NULL, &ai ))
+#else
+ if (!(hostent = gethostbyname( hostOrAlias )))
+#endif
+ {
+ LogWarn( "XDMCP ACL: unresolved host %'s\n", hostOrAlias );
+ free( (char *)(**hostPtr) );
+ return 0;
+ }
+#if defined(IPv6) && defined(AF_INET6)
+ addr_type = ai->ai_addr->sa_family;
+ if (ai->ai_family == AF_INET) {
+ addr = &((struct sockaddr_in *)ai->ai_addr)->sin_addr;
+ addr_len = sizeof(struct in_addr);
+ } else /*if (ai->ai_addr->sa_family == AF_INET6)*/ {
+ addr = &((struct sockaddr_in6 *)ai->ai_addr)->sin6_addr;
+ addr_len = sizeof(struct in6_addr);
+ }
+#else
+ addr_type = hostent->h_addrtype;
+ addr = hostent->h_addr;
+ addr_len = hostent->h_length;
+#endif
+ if (!((**hostPtr)->entry.displayAddress.hostAddress =
+ Malloc( addr_len )))
+ {
+#if defined(IPv6) && defined(AF_INET6)
+ freeaddrinfo( ai );
+#endif
+ free( (char *)(**hostPtr) );
+ return 0;
+ }
+ memcpy( (**hostPtr)->entry.displayAddress.hostAddress, addr, addr_len );
+ *nChars += addr_len;
+ (**hostPtr)->entry.displayAddress.hostAddrLen = addr_len;
+ (**hostPtr)->entry.displayAddress.connectionType = addr_type;
+#if defined(IPv6) && defined(AF_INET6)
+ freeaddrinfo( ai );
+#endif
+ }
+ *hostPtr = &(**hostPtr)->next;
+ (*nHosts)++;
+ return 1;
+}
+
+/* Returns non-0 if string is matched by pattern. Does case folding. */
+static int
+patternMatch( const char *string, const char *pattern )
+{
+ int p, s;
+
+ if (!string)
+ string = "";
+
+ for (;;) {
+ s = *string++;
+ switch (p = *pattern++) {
+ case '*':
+ if (!*pattern)
+ return 1;
+ for (string--; *string; string++)
+ if (patternMatch( string, pattern ))
+ return 1;
+ return 0;
+ case '?':
+ if (s == '\0')
+ return 0;
+ break;
+ case '\0':
+ return s == '\0';
+ case '\\':
+ p = *pattern++;
+ /* fall through */
+ default:
+ if (tolower( p ) != tolower( s ))
+ return 0;
+ }
+ }
+}
+
+#define MAX_DEPTH 32
+
+#define CHECK_NOT 1
+#define CHECK_NO_PAT 2
+
+static int
+checkHostlist( HostEntry **hosts, int nh, AliasEntry *aliases, int na,
+ int depth, int flags )
+{
+ HostEntry *h;
+ AliasEntry *a;
+ int hn, an, am;
+
+ for (h = *hosts, hn = 0; hn < nh; hn++, h = h->next)
+ if (h->type == HOST_ALIAS) {
+ if (depth == MAX_DEPTH) {
+ LogError( "XDMCP ACL: alias recursion involving %%%s\n",
+ h->entry.aliasPattern );
+ return 1;
+ }
+ for (a = aliases, an = 0, am = 0; an < na; an++, a = a->next)
+ if (patternMatch( a->name, h->entry.aliasPattern )) {
+ am = 1;
+ if ((flags & CHECK_NOT) && a->hasBad) {
+ LogError( "XDMCP ACL: alias %%%s with unresolved hosts "
+ "in denying rule\n", a->name );
+ return 1;
+ }
+ if (checkHostlist( a->pHosts, a->nhosts, aliases, na,
+ depth + 1, flags ))
+ return 1;
+ }
+ if (!am) {
+ if (flags & CHECK_NOT) {
+ LogError( "XDMCP ACL: unresolved alias pattern %%%s "
+ "in denying rule\n", h->entry.aliasPattern );
+ return 1;
+ } else
+ LogWarn( "XDMCP ACL: unresolved alias pattern %%%s\n",
+ h->entry.aliasPattern );
+ }
+ } else if (h->type == HOST_PATTERN && (flags & CHECK_NO_PAT))
+ LogWarn( "XDMCP ACL: wildcarded pattern %'s in host-only context\n",
+ h->entry.hostPattern );
+ return 0;
+}
+
+static void
+ReadAccessFile( const char *fname )
+{
+ HostEntry *hostList, **hostPtr = &hostList;
+ AliasEntry *aliasList, **aliasPtr = &aliasList;
+ AclEntry *acList, **acPtr = &acList, *acl;
+ ListenEntry *listenList, **listenPtr = &listenList;
+ char *displayOrAlias, *hostOrAlias;
+ File file;
+ int nHosts, nAliases, nAcls, nListens, nChars, error, bad;
+ int i, len;
+
+ nHosts = nAliases = nAcls = nListens = nChars = error = 0;
+ if (!readFile( &file, fname, "XDMCP access control" ))
+ goto sendacl;
+ while ((displayOrAlias = ReadWord( &file, &len, FALSE ))) {
+ if (*displayOrAlias == ALIAS_CHARACTER)
+ {
+ if (!(*aliasPtr = (AliasEntry *)Malloc( sizeof(AliasEntry)))) {
+ error = 1;
+ break;
+ }
+ (*aliasPtr)->name = displayOrAlias + 1;
+ nChars += len;
+ (*aliasPtr)->hosts = nHosts;
+ (*aliasPtr)->pHosts = hostPtr;
+ (*aliasPtr)->nhosts = 0;
+ (*aliasPtr)->hasBad = 0;
+ while ((hostOrAlias = ReadWord( &file, &len, TRUE ))) {
+ if (ParseHost( &nHosts, &hostPtr, &nChars, hostOrAlias, len,
+ PARSE_NO_BCAST ))
+ (*aliasPtr)->nhosts++;
+ else
+ (*aliasPtr)->hasBad = 1;
+ }
+ aliasPtr = &(*aliasPtr)->next;
+ nAliases++;
+ }
+ else if (!strcmp( displayOrAlias, LISTEN_STRING ))
+ {
+ if (!(*listenPtr = (ListenEntry *)Malloc( sizeof(ListenEntry)))) {
+ error = 1;
+ break;
+ }
+ (*listenPtr)->iface = nHosts;
+ if (!(hostOrAlias = ReadWord( &file, &len, TRUE )) ||
+ !strcmp( hostOrAlias, WILDCARD_STRING ) ||
+ !ParseHost( &nHosts, &hostPtr, &nChars, hostOrAlias, len,
+ PARSE_NO_BCAST|PARSE_NO_PAT|PARSE_NO_ALIAS ))
+ {
+ (*listenPtr)->iface = -1;
+ }
+ (*listenPtr)->mcasts = nHosts;
+ (*listenPtr)->nmcasts = 0;
+ while ((hostOrAlias = ReadWord( &file, &len, TRUE ))) {
+ if (ParseHost( &nHosts, &hostPtr, &nChars, hostOrAlias, len,
+ PARSE_NO_BCAST|PARSE_NO_PAT|PARSE_NO_ALIAS ))
+ (*listenPtr)->nmcasts++;
+ }
+ listenPtr = &(*listenPtr)->next;
+ nListens++;
+ }
+ else
+ {
+ if (!(*acPtr = (AclEntry *)Malloc( sizeof(AclEntry)))) {
+ error = 1;
+ break;
+ }
+ (*acPtr)->flags = 0;
+ if (*displayOrAlias == NEGATE_CHARACTER) {
+ (*acPtr)->flags |= a_notAllowed;
+ displayOrAlias++;
+ } else if (*displayOrAlias == EQUAL_CHARACTER)
+ displayOrAlias++;
+ (*acPtr)->entries = nHosts;
+ (*acPtr)->pEntries = hostPtr;
+ (*acPtr)->nentries = 1;
+ if (!ParseHost( &nHosts, &hostPtr, &nChars, displayOrAlias, len,
+ PARSE_NO_BCAST ))
+ {
+ bad = 1;
+ if ((*acPtr)->flags & a_notAllowed) {
+ LogError( "XDMCP ACL: unresolved host in denying rule\n" );
+ error = 1;
+ }
+ } else
+ bad = 0;
+ (*acPtr)->hosts = nHosts;
+ (*acPtr)->pHosts = hostPtr;
+ (*acPtr)->nhosts = 0;
+ while ((hostOrAlias = ReadWord( &file, &len, TRUE ))) {
+ if (!strcmp( hostOrAlias, CHOOSER_STRING ))
+ (*acPtr)->flags |= a_useChooser;
+ else if (!strcmp( hostOrAlias, NOBROADCAST_STRING ))
+ (*acPtr)->flags |= a_notBroadcast;
+ else {
+ if (ParseHost( &nHosts, &hostPtr, &nChars,
+ hostOrAlias, len, PARSE_NO_PAT ))
+ (*acPtr)->nhosts++;
+ }
+ }
+ if (!bad) {
+ acPtr = &(*acPtr)->next;
+ nAcls++;
+ }
+ }
+ }
+
+ if (!nListens) {
+ if (!(*listenPtr = (ListenEntry *)Malloc( sizeof(ListenEntry))))
+ error = 1;
+ else {
+ (*listenPtr)->iface = -1;
+ (*listenPtr)->mcasts = nHosts;
+ (*listenPtr)->nmcasts = 0;
+#if defined(IPv6) && defined(AF_INET6) && defined(XDM_DEFAULT_MCAST_ADDR6)
+ if (ParseHost( &nHosts, &hostPtr, &nChars,
+ XDM_DEFAULT_MCAST_ADDR6,
+ sizeof(XDM_DEFAULT_MCAST_ADDR6)-1,
+ PARSE_ALL ))
+ (*listenPtr)->nmcasts++;
+#endif
+ nListens++;
+ }
+ }
+
+ for (acl = acList, i = 0; i < nAcls; i++, acl = acl->next)
+ if (checkHostlist( acl->pEntries, acl->nentries, aliasList, nAliases,
+ 0, (acl->flags & a_notAllowed) ? CHECK_NOT : 0 ) ||
+ checkHostlist( acl->pHosts, acl->nhosts, aliasList, nAliases,
+ 0, CHECK_NO_PAT ))
+ error = 1;
+
+ if (error) {
+ nHosts = nAliases = nAcls = nListens = nChars = 0;
+ sendacl:
+ LogError( "No XDMCP requests will be granted\n" );
+ }
+ GSendInt( nHosts );
+ GSendInt( nListens );
+ GSendInt( nAliases );
+ GSendInt( nAcls );
+ GSendInt( nChars );
+ for (i = 0; i < nHosts; i++, hostList = hostList->next) {
+ GSendInt( hostList->type );
+ switch (hostList->type) {
+ case HOST_ALIAS:
+ GSendStr( hostList->entry.aliasPattern );
+ break;
+ case HOST_PATTERN:
+ GSendStr( hostList->entry.hostPattern );
+ break;
+ case HOST_ADDRESS:
+ GSendArr( hostList->entry.displayAddress.hostAddrLen,
+ hostList->entry.displayAddress.hostAddress );
+ GSendInt( hostList->entry.displayAddress.connectionType );
+ break;
+ }
+ }
+ for (i = 0; i < nListens; i++, listenList = listenList->next) {
+ GSendInt( listenList->iface );
+ GSendInt( listenList->mcasts );
+ GSendInt( listenList->nmcasts );
+ }
+ for (i = 0; i < nAliases; i++, aliasList = aliasList->next) {
+ GSendStr( aliasList->name );
+ GSendInt( aliasList->hosts );
+ GSendInt( aliasList->nhosts );
+ }
+ for (i = 0; i < nAcls; i++, acList = acList->next) {
+ GSendInt( acList->entries );
+ GSendInt( acList->nentries );
+ GSendInt( acList->hosts );
+ GSendInt( acList->nhosts );
+ GSendInt( acList->flags );
+ }
+}
+#endif
+
+
+int main( int argc ATTR_UNUSED, char **argv )
+{
+ DSpec dspec;
+ ValArr va;
+ char *ci, *disp, *dcls, *cfgfile;
+ int what;
+
+ if (!(ci = getenv( "CONINFO" ))) {
+ fprintf( stderr, "This program is part of tdm and should not be run manually.\n" );
+ return 1;
+ }
+ if (sscanf( ci, "%d %d", &rfd, &wfd ) != 2)
+ return 1;
+
+ InitLog();
+
+ if ((debugLevel = GRecvInt()) & DEBUG_WCONFIG)
+ sleep( 100 );
+
+/* Debug ("parsing command line\n");*/
+ if (**++argv)
+ tdmrc_dist = tdmrc = *argv;
+/*
+ while (*++argv) {
+ }
+*/
+
+ for (;;) {
+/* Debug ("Awaiting command ...\n");*/
+ if (!GRecvCmd( &what ))
+ break;
+ switch (what) {
+ case GC_Files:
+/* Debug ("GC_Files\n");*/
+ ReadConf();
+ CopyValues( 0, &secGeneral, 0, C_CONFIG );
+#ifdef XDMCP
+ CopyValues( 0, &secXdmcp, 0, C_CONFIG );
+ GSendInt( 2 );
+#else
+ GSendInt( 1 );
+#endif
+ GSendStr( tdmrc );
+ GSendInt( -1 );
+#ifdef XDMCP
+ GSendNStr( VXaccess.ptr, VXaccess.len - 1 );
+ GSendInt( 0 );
+#endif
+ for (; (what = GRecvInt()) != -1; )
+ switch (what) {
+ case GC_gGlobal:
+ case GC_gDisplay:
+ GSendInt( 0 );
+ break;
+#ifdef XDMCP
+ case GC_gXaccess:
+ GSendInt( 1 );
+ break;
+#endif
+ default:
+ GSendInt( -1 );
+ break;
+ }
+ break;
+ case GC_GetConf:
+/* Debug( "GC_GetConf\n" );*/
+ memset( &va, 0, sizeof(va) );
+ what = GRecvInt();
+ cfgfile = GRecvStr();
+ switch (what) {
+ case GC_gGlobal:
+/* Debug( "GC_gGlobal\n" );*/
+ Debug( "getting global config\n" );
+ ReadConf();
+ CopyValues( &va, &secGeneral, 0, 0 );
+#ifdef XDMCP
+ CopyValues( &va, &secXdmcp, 0, 0 );
+#endif
+ CopyValues( &va, &secShutdown, 0, 0 );
+ SendValues( &va );
+ break;
+ case GC_gDisplay:
+/* Debug( "GC_gDisplay\n" );*/
+ disp = GRecvStr();
+/* Debug( " Display %s\n", disp );*/
+ dcls = GRecvStr();
+/* Debug( " Class %s\n", dcls );*/
+ Debug( "getting config for display %s, class %s\n", disp, dcls );
+ MkDSpec( &dspec, disp, dcls ? dcls : "" );
+ ReadConf();
+ CopyValues( &va, &sec_Core, &dspec, 0 );
+ CopyValues( &va, &sec_Greeter, &dspec, 0 );
+ free( disp );
+ if (dcls)
+ free( dcls );
+ SendValues( &va );
+ break;
+#ifdef XDMCP
+ case GC_gXaccess:
+ ReadAccessFile( cfgfile );
+ break;
+#endif
+ default:
+ Debug( "Unsupported config category %#x\n", what );
+ }
+ free( cfgfile );
+ break;
+ default:
+ Debug( "Unknown config command %#x\n", what );
+ }
+ }
+
+/* Debug( "Config reader exiting ..." );*/
+ return EX_NORMAL;
+}
diff --git a/tdm/kfrontend/tdm_greet.c b/tdm/kfrontend/tdm_greet.c
new file mode 100644
index 00000000..f74c2410
--- /dev/null
+++ b/tdm/kfrontend/tdm_greet.c
@@ -0,0 +1,787 @@
+/*
+
+KDE Greeter module for xdm
+
+Copyright (C) 2001-2003 Oswald Buddenhagen <ossi@kde.org>
+
+This file contains code from the old xdm core,
+Copyright 1988, 1998 Keith Packard, MIT X Consortium/The Open Group
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#include <config.h>
+
+#include "tdm_greet.h"
+#include "tdmconfig.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdarg.h>
+#include <string.h>
+#include <signal.h>
+#include <setjmp.h>
+#include <ctype.h>
+#include <time.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#ifdef _POSIX_PRIORITY_SCHEDULING
+# include <sched.h>
+#endif
+
+# include <X11/Xlib.h>
+#if defined(HAVE_XTEST) || defined(HAVE_XKB)
+# include <X11/keysym.h>
+#endif
+
+#ifdef HAVE_XTEST
+# include <X11/extensions/XTest.h>
+#endif
+
+#ifdef HAVE_XKB
+# include <X11/XKBlib.h>
+#endif
+
+extern void LogOutOfMem( void );
+
+static void *
+Realloc( void *ptr, size_t size )
+{
+ void *ret;
+
+ if (!(ret = realloc( ptr, size )) && size)
+ LogOutOfMem();
+ return ret;
+}
+
+#define PRINT_QUOTES
+#define PRINT_ARRAYS
+#define LOG_NAME "tdm_greet"
+#define LOG_DEBUG_MASK DEBUG_GREET
+#define LOG_PANIC_EXIT 1
+#define STATIC
+#include <printf.c>
+
+static void
+GDebug( const char *fmt, ... )
+{
+ va_list args;
+
+ if (debugLevel & DEBUG_HLPCON) {
+ va_start( args, fmt );
+ Logger( DM_DEBUG, fmt, args );
+ va_end( args );
+ }
+}
+
+
+char *dname;
+
+int rfd;
+static int wfd, mrfd, mwfd, srfd, swfd;
+static const char *who;
+
+void
+GSet( int master )
+{
+ if (master)
+ rfd = mrfd, wfd = mwfd, who = "core (master)";
+ else
+ rfd = srfd, wfd = swfd, who = "core";
+
+}
+
+static int
+Reader( void *buf, int count )
+{
+ int ret, rlen;
+
+ for (rlen = 0; rlen < count; ) {
+ dord:
+ ret = read( rfd, (void *)((char *)buf + rlen), count - rlen );
+ if (ret < 0) {
+ if (errno == EINTR)
+ goto dord;
+ if (errno == EAGAIN)
+ break;
+ return -1;
+ }
+ if (!ret)
+ break;
+ rlen += ret;
+ }
+ return rlen;
+}
+
+static void
+GRead( void *buf, int count )
+{
+ if (Reader( buf, count ) != count)
+ LogPanic( "Can't read from %s\n", who );
+}
+
+static void
+GWrite( const void *buf, int count )
+{
+ if (write( wfd, buf, count ) != count)
+ LogPanic( "Can't write to %s\n", who );
+#ifdef _POSIX_PRIORITY_SCHEDULING
+ if ((debugLevel & DEBUG_HLPCON))
+ sched_yield();
+#endif
+}
+
+void
+GSendInt( int val )
+{
+ GDebug( "Sending int %d (%#x) to %s\n", val, val, who );
+ GWrite( &val, sizeof(val) );
+}
+
+void
+GSendStr( const char *buf )
+{
+ int len = buf ? strlen( buf ) + 1 : 0;
+ GDebug( "Sending string %'s to %s\n", buf, who );
+ GWrite( &len, sizeof(len) );
+ GWrite( buf, len );
+}
+
+/*
+static void
+GSendNStr( const char *buf, int len )
+{
+ int tlen = len + 1;
+ GDebug( "Sending string %'.*s to %s\n", len, buf, who );
+ GWrite( &tlen, sizeof(tlen) );
+ GWrite( buf, len );
+ GWrite( "", 1 );
+}
+*/
+
+void
+GSendArr( int len, const char *buf )
+{
+ GDebug( "Sending array %02[:*hhx to %s\n", len, buf, who );
+ GWrite( &len, sizeof(len) );
+ GWrite( buf, len );
+}
+
+int
+GRecvInt()
+{
+ int val;
+
+ GDebug( "Receiving int from %s ...\n", who );
+ GRead( &val, sizeof(val) );
+ GDebug( " -> %d (%#x)\n", val, val );
+ return val;
+}
+
+static char *
+iGRecvArr( int *rlen )
+{
+ int len;
+ char *buf;
+
+ GRead( &len, sizeof(len) );
+ *rlen = len;
+ GDebug( " -> %d bytes\n", len );
+ if (!len)
+ return (char *)0;
+ if (!(buf = malloc( len )))
+ LogPanic( "No memory for read buffer\n" );
+ GRead( buf, len );
+ return buf;
+}
+
+char *
+GRecvStr()
+{
+ int len;
+ char *buf;
+
+ GDebug( "Receiving string from %s ...\n", who );
+ buf = iGRecvArr( &len );
+ GDebug( " -> %'.*s\n", len, buf );
+ return buf;
+}
+
+char **
+GRecvStrArr( int *rnum )
+{
+ int num;
+ char **argv, **cargv;
+
+ GDebug( "Receiving string array from %s ...\n", who );
+ GRead( &num, sizeof(num) );
+ GDebug( " -> %d strings\n", num );
+ if (rnum)
+ *rnum = num;
+ if (!num)
+ return (char **)0;
+ if (!(argv = malloc( num * sizeof(char *))))
+ LogPanic( "No memory for read buffer\n" );
+ for (cargv = argv; --num >= 0; cargv++)
+ *cargv = GRecvStr();
+ return argv;
+}
+
+char *
+GRecvArr( int *num )
+{
+ char *arr;
+
+ GDebug( "Receiving array from %s ...\n", who );
+ GRead( num, sizeof(*num) );
+ GDebug( " -> %d bytes\n", *num );
+ if (!*num)
+ return (char *)0;
+ if (!(arr = malloc( *num )))
+ LogPanic( "No memory for read buffer\n" );
+ GRead( arr, *num );
+ GDebug( " -> %02[*hhx\n", *num, arr );
+ return arr;
+}
+
+static void
+ReqCfg( int id )
+{
+ GSendInt( G_GetCfg );
+ GSendInt( id );
+ switch (GRecvInt()) {
+ case GE_NoEnt:
+ LogPanic( "Config value %#x not available\n", id );
+ case GE_BadType:
+ LogPanic( "Core does not know type of config value %#x\n", id );
+ }
+}
+
+int
+GetCfgInt( int id )
+{
+ ReqCfg( id );
+ return GRecvInt();
+}
+
+char *
+GetCfgStr( int id )
+{
+ ReqCfg( id );
+ return GRecvStr();
+}
+
+char **
+GetCfgStrArr( int id, int *len )
+{
+ ReqCfg( id );
+ return GRecvStrArr( len );
+}
+
+static void
+disposeSession( dpySpec *sess )
+{
+ free( sess->display );
+ free( sess->from );
+ if (sess->user)
+ free( sess->user );
+ if (sess->session)
+ free( sess->session );
+}
+
+dpySpec *
+fetchSessions( int flags )
+{
+ dpySpec *sess, *sessions = 0, tsess;
+
+ GSet( 1 );
+ GSendInt( G_List );
+ GSendInt( flags );
+ next:
+ while ((tsess.display = GRecvStr())) {
+ tsess.from = GRecvStr();
+#ifdef HAVE_VTS
+ tsess.vt = GRecvInt();
+#endif
+ tsess.user = GRecvStr();
+ tsess.session = GRecvStr();
+ tsess.flags = GRecvInt();
+ if ((tsess.flags & isTTY) && *tsess.from)
+ for (sess = sessions; sess; sess = sess->next)
+ if (sess->user && !strcmp( sess->user, tsess.user ) &&
+ !strcmp( sess->from, tsess.from ))
+ {
+ sess->count++;
+ disposeSession( &tsess );
+ goto next;
+ }
+ if (!(sess = malloc( sizeof(*sess) )))
+ LogPanic( "Out of memory\n" );
+ tsess.count = 1;
+ tsess.next = sessions;
+ *sess = tsess;
+ sessions = sess;
+ }
+ GSet( 0 );
+ return sessions;
+}
+
+void
+disposeSessions( dpySpec *sess )
+{
+ while (sess) {
+ dpySpec *nsess = sess->next;
+ disposeSession( sess );
+ free( sess );
+ sess = nsess;
+ }
+}
+
+void
+freeStrArr( char **arr )
+{
+ char **tarr;
+
+ if (arr) {
+ for (tarr = arr; *tarr; tarr++)
+ free( *tarr );
+ free( arr );
+ }
+}
+
+
+static int
+ignoreErrors( Display *dpy ATTR_UNUSED, XErrorEvent *event ATTR_UNUSED )
+{
+ Debug( "ignoring X error\n" );
+ return 0;
+}
+
+/*
+ * this is mostly bogus -- but quite useful. I wish the protocol
+ * had some way of enumerating and identifying clients, that way
+ * this code wouldn't have to be this kludgy.
+ */
+
+static void
+killWindows( Display *dpy, Window window )
+{
+ Window root, parent, *children;
+ unsigned child, nchildren = 0;
+
+ while (XQueryTree( dpy, window, &root, &parent, &children, &nchildren )
+ && nchildren > 0)
+ {
+ for (child = 0; child < nchildren; child++) {
+ Debug( "XKillClient 0x%lx\n", (unsigned long)children[child] );
+ XKillClient( dpy, children[child] );
+ }
+ XFree( (char *)children );
+ }
+}
+
+static jmp_buf resetJmp;
+
+static void
+abortReset( int n ATTR_UNUSED )
+{
+ longjmp (resetJmp, 1);
+}
+
+/*
+ * this display connection better not have any windows...
+ */
+
+static void
+pseudoReset( Display *dpy )
+{
+ int screen;
+
+ if (setjmp( resetJmp )) {
+ LogError( "pseudoReset timeout\n" );
+ } else {
+ (void)signal( SIGALRM, abortReset );
+ (void)alarm( 30 );
+ XSetErrorHandler( ignoreErrors );
+ for (screen = 0; screen < ScreenCount( dpy ); screen++) {
+ Debug( "pseudoReset screen %d\n", screen );
+ killWindows( dpy, RootWindow( dpy, screen ) );
+ }
+ Debug( "before XSync\n" );
+ XSync( dpy, False );
+ (void)alarm( 0 );
+ }
+ signal( SIGALRM, SIG_DFL );
+ XSetErrorHandler( (XErrorHandler)0 );
+ Debug( "pseudoReset done\n" );
+}
+
+
+static jmp_buf syncJump;
+
+static void
+syncTimeout( int n ATTR_UNUSED )
+{
+ longjmp( syncJump, 1 );
+}
+
+void
+SecureDisplay( Display *dpy )
+{
+ Debug( "SecureDisplay %s\n", dname );
+ (void)signal( SIGALRM, syncTimeout );
+ if (setjmp( syncJump )) {
+ LogError( "Display %s could not be secured\n", dname );
+ exit( EX_RESERVER_DPY );
+ }
+ (void)alarm( (unsigned)_grabTimeout );
+ Debug( "Before XGrabServer %s\n", dname );
+ XGrabServer( dpy );
+ Debug( "XGrabServer succeeded %s\n", dname );
+ if (XGrabKeyboard( dpy, DefaultRootWindow( dpy ), True, GrabModeAsync,
+ GrabModeAsync, CurrentTime ) != GrabSuccess)
+ {
+ (void)alarm( 0 );
+ (void)signal( SIGALRM, SIG_DFL );
+ LogError( "Keyboard on display %s could not be secured\n", dname );
+ sleep( 10 );
+ exit( EX_RESERVER_DPY );
+ }
+ (void)alarm( 0 );
+ (void)signal( SIGALRM, SIG_DFL );
+ pseudoReset( dpy );
+ if (!_grabServer)
+ {
+ XUngrabServer( dpy );
+ XSync( dpy, 0 );
+ }
+ Debug( "done secure %s\n", dname );
+#ifdef HAVE_XKBSETPERCLIENTCONTROLS
+ /*
+ * Activate the correct mapping for modifiers in XKB extension as
+ * grabbed keyboard has its own mapping by default
+ */
+ {
+ int opcode, evbase, errbase, majret, minret;
+ unsigned int value = XkbPCF_GrabsUseXKBStateMask;
+ if (XkbQueryExtension( dpy, &opcode, &evbase,
+ &errbase, &majret, &minret ))
+ XkbSetPerClientControls( dpy, value, &value );
+ }
+#endif
+}
+
+void
+UnsecureDisplay( Display *dpy )
+{
+ Debug( "Unsecure display %s\n", dname );
+ if (_grabServer) {
+ XUngrabServer( dpy );
+ XSync( dpy, 0 );
+ }
+}
+
+static jmp_buf pingTime;
+
+static int
+PingLostIOErr( Display *dpy ATTR_UNUSED )
+{
+ longjmp( pingTime, 1 );
+}
+
+static void
+PingLostSig( int n ATTR_UNUSED )
+{
+ longjmp( pingTime, 1 );
+}
+
+int
+PingServer( Display *dpy )
+{
+ int (*oldError)( Display * );
+ void (*oldSig)( int );
+ int oldAlarm;
+
+ oldError = XSetIOErrorHandler( PingLostIOErr );
+ oldAlarm = alarm( 0 );
+ oldSig = signal( SIGALRM, PingLostSig );
+ (void)alarm( _pingTimeout * 60 );
+ if (!setjmp( pingTime )) {
+ Debug( "Ping server\n" );
+ XSync( dpy, 0 );
+ } else {
+ Debug( "Server dead\n" );
+ (void)alarm( 0 );
+ (void)signal( SIGALRM, SIG_DFL );
+ XSetIOErrorHandler( oldError );
+ return 0;
+ }
+ (void)alarm( 0 );
+ (void)signal( SIGALRM, oldSig );
+ (void)alarm( oldAlarm );
+ Debug( "Server alive\n" );
+ XSetIOErrorHandler( oldError );
+ return 1;
+}
+
+/*
+ * Modifier changing code based on tdebase/kxkb/kcmmisc.cpp
+ *
+ * XTest part: Copyright (C) 2000-2001 Lubos Lunak <l.lunak@kde.org>
+ * XKB part: Copyright (C) 2001-2002 Oswald Buddenhagen <ossi@kde.org>
+ *
+ */
+
+#ifdef HAVE_XKB
+static int
+xkb_init( Display *dpy )
+{
+ int xkb_opcode, xkb_event, xkb_error;
+ int xkb_lmaj = XkbMajorVersion;
+ int xkb_lmin = XkbMinorVersion;
+ return XkbLibraryVersion( &xkb_lmaj, &xkb_lmin ) &&
+ XkbQueryExtension( dpy, &xkb_opcode, &xkb_event,
+ &xkb_error, &xkb_lmaj, &xkb_lmin );
+}
+
+static unsigned int
+xkb_modifier_mask_work( XkbDescPtr xkb, const char *name )
+{
+ int i;
+
+ if (!xkb->names)
+ return 0;
+ for (i = 0; i < XkbNumVirtualMods; i++) {
+ char *modStr = XGetAtomName( xkb->dpy, xkb->names->vmods[i] );
+ if (modStr != NULL && strcmp( name, modStr ) == 0) {
+ unsigned int mask;
+ XkbVirtualModsToReal( xkb, 1 << i, &mask );
+ return mask;
+ }
+ }
+ return 0;
+}
+
+static unsigned int
+xkb_modifier_mask( Display *dpy, const char *name )
+{
+ XkbDescPtr xkb;
+
+ if ((xkb = XkbGetKeyboard( dpy, XkbAllComponentsMask, XkbUseCoreKbd ))) {
+ unsigned int mask = xkb_modifier_mask_work( xkb, name );
+ XkbFreeKeyboard( xkb, 0, True );
+ return mask;
+ }
+ return 0;
+}
+
+static int
+xkb_get_modifier_state( Display *dpy, const char *name )
+{
+ unsigned int mask;
+ XkbStateRec state;
+
+ if (!(mask = xkb_modifier_mask( dpy, name )))
+ return 0;
+ XkbGetState( dpy, XkbUseCoreKbd, &state );
+ return (mask & state.locked_mods) != 0;
+}
+
+static int
+xkb_set_modifier( Display *dpy, const char *name, int sts )
+{
+ unsigned int mask;
+
+ if (!(mask = xkb_modifier_mask( dpy, name )))
+ return 0;
+ XkbLockModifiers( dpy, XkbUseCoreKbd, mask, sts ? mask : 0 );
+ return 1;
+}
+#endif /* HAVE_XKB */
+
+#ifdef HAVE_XTEST
+static int
+xtest_get_modifier_state( Display *dpy, int key )
+{
+ XModifierKeymap *map;
+ KeyCode modifier_keycode;
+ unsigned int i, mask;
+ Window dummy1, dummy2;
+ int dummy3, dummy4, dummy5, dummy6;
+
+ if ((modifier_keycode = XKeysymToKeycode( dpy, key )) == NoSymbol)
+ return 0;
+ map = XGetModifierMapping( dpy );
+ for (i = 0; i < 8; ++i)
+ if (map->modifiermap[map->max_keypermod * i] == modifier_keycode) {
+ XFreeModifiermap( map );
+ XQueryPointer( dpy, DefaultRootWindow( dpy ),
+ &dummy1, &dummy2, &dummy3, &dummy4, &dummy5, &dummy6,
+ &mask );
+ return (mask & (1 << i)) != 0;
+ }
+ XFreeModifiermap( map );
+ return 0;
+}
+
+static void
+xtest_fake_keypress( Display *dpy, int key )
+{
+ XTestFakeKeyEvent( dpy, XKeysymToKeycode( dpy, key ), True, CurrentTime );
+ XTestFakeKeyEvent( dpy, XKeysymToKeycode( dpy, key ), False, CurrentTime );
+}
+#endif /* HAVE_XTEST */
+
+#ifdef HAVE_XKB
+static int havexkb;
+#endif
+static int nummodified, oldnumstate, newnumstate;
+static Display *dpy;
+
+void
+setup_modifiers( Display *mdpy, int numlock )
+{
+ if (numlock == 2)
+ return;
+ newnumstate = numlock;
+ nummodified = 1;
+ dpy = mdpy;
+#ifdef HAVE_XKB
+ if (xkb_init( mdpy )) {
+ havexkb = 1;
+ oldnumstate = xkb_get_modifier_state( mdpy, "NumLock" );
+ xkb_set_modifier( mdpy, "NumLock", numlock );
+ return;
+ }
+#endif
+#ifdef HAVE_XTEST
+ oldnumstate = xtest_get_modifier_state( mdpy, XK_Num_Lock );
+ if (oldnumstate != numlock)
+ xtest_fake_keypress( mdpy, XK_Num_Lock );
+#endif
+}
+
+void
+restore_modifiers( void )
+{
+#ifdef HAVE_XTEST
+ int numstat;
+#endif
+
+ if (!nummodified)
+ return;
+#ifdef HAVE_XKB
+ if (havexkb) {
+ if (xkb_get_modifier_state( dpy, "NumLock" ) == newnumstate)
+ xkb_set_modifier( dpy, "NumLock", oldnumstate );
+ return;
+ }
+#endif
+#ifdef HAVE_XTEST
+ numstat = xtest_get_modifier_state( dpy, XK_Num_Lock );
+ if (numstat == newnumstate && newnumstate != oldnumstate)
+ xtest_fake_keypress( dpy, XK_Num_Lock );
+#endif
+}
+
+void
+setCursor( Display *mdpy, int window, int shape )
+{
+ Cursor xcursor;
+
+ if ((xcursor = XCreateFontCursor( mdpy, shape ))) {
+ XDefineCursor( mdpy, window, xcursor );
+ XFreeCursor( mdpy, xcursor );
+ XFlush( mdpy );
+ }
+}
+
+static void
+sigterm( int n ATTR_UNUSED )
+{
+ exit( EX_NORMAL );
+}
+
+static char *savhome;
+
+static void
+cleanup( void )
+{
+ char buf[128];
+
+ if (strcmp( savhome, getenv( "HOME" ) ) || memcmp( savhome, "/tmp/", 5 ))
+ LogError( "Internal error: memory corruption detected\n" ); /* no panic: recursion */
+ else {
+ sprintf( buf, "rm -rf %s", savhome );
+ system( buf );
+ }
+}
+
+extern void kg_main( const char *argv0 );
+
+int
+main( int argc ATTR_UNUSED, char **argv )
+{
+ char *ci;
+ int i;
+ char qtrc[40];
+
+ if (!(ci = getenv( "CONINFO" ))) {
+ fprintf( stderr, "This program is part of tdm and should not be run manually.\n" );
+ return 1;
+ }
+ if (sscanf( ci, "%d %d %d %d", &srfd, &swfd, &mrfd, &mwfd ) != 4)
+ return 1;
+ fcntl( srfd, F_SETFD, FD_CLOEXEC );
+ fcntl( swfd, F_SETFD, FD_CLOEXEC );
+ fcntl( mrfd, F_SETFD, FD_CLOEXEC );
+ fcntl( mwfd, F_SETFD, FD_CLOEXEC );
+ GSet( 0 );
+
+ InitLog();
+
+ if ((debugLevel = GRecvInt()) & DEBUG_WGREET)
+ sleep( 100 );
+
+ signal( SIGTERM, sigterm );
+
+ dname = getenv( "DISPLAY" );
+
+ init_config();
+
+ /* for TQSettings */
+ srand( time( 0 ) );
+ for (i = 0; i < 10000; i++) {
+ sprintf( qtrc, "/tmp/%010d", rand() );
+ if (!mkdir( qtrc, 0700 ))
+ goto okay;
+ }
+ LogPanic( "Cannot create $HOME\n" );
+ okay:
+ if (setenv( "HOME", qtrc, 1 ))
+ LogPanic( "Cannot set $HOME\n" );
+ if (!(savhome = strdup( qtrc )))
+ LogPanic( "Cannot save $HOME\n" );
+ atexit( cleanup );
+
+ setenv( "LC_ALL", _language, 1 );
+
+ kg_main( argv[0] );
+
+ return EX_NORMAL;
+}
diff --git a/tdm/kfrontend/tdm_greet.h b/tdm/kfrontend/tdm_greet.h
new file mode 100644
index 00000000..9f7e3bd6
--- /dev/null
+++ b/tdm/kfrontend/tdm_greet.h
@@ -0,0 +1,91 @@
+/*
+
+KDE Greeter module for xdm
+
+Copyright (C) 2001-2003 Oswald Buddenhagen <ossi@kde.org>
+
+This file contains code from the old xdm core,
+Copyright 1988, 1998 Keith Packard, MIT X Consortium/The Open Group
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#ifndef _TDM_GREET_H_
+#define _TDM_GREET_H_
+
+#include <greet.h> /* for the ATTR_ defines */
+#include <config.ci> /* for the HAVE_VTS define */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void GSet( int master );
+void GSendInt( int val );
+void GSendStr( const char *buf );
+/*void GSendNStr( const char *buf, int len );*/
+void GSendArr( int len, const char *buf );
+int GRecvInt( void );
+char *GRecvStr( void );
+char **GRecvStrArr( int *len );
+char *GRecvArr( int *len );
+
+int GetCfgInt( int id );
+char *GetCfgStr( int id );
+char **GetCfgStrArr( int id, int *len );
+
+typedef struct dpySpec {
+ struct dpySpec *next;
+ char *display, *from, *user, *session;
+#ifdef HAVE_VTS
+ int vt;
+#endif
+ int flags;
+ int count;
+} dpySpec;
+
+dpySpec *fetchSessions( int flags );
+void disposeSessions( dpySpec *sess );
+
+void freeStrArr( char **arr );
+
+void Debug( const char *fmt, ... );
+void LogInfo( const char *fmt, ... );
+void LogWarn( const char *fmt, ... );
+void LogError( const char *fmt, ... );
+void LogPanic( const char *fmt, ... ) ATTR_NORETURN;
+
+struct _XDisplay;
+
+void SecureDisplay( struct _XDisplay *dpy );
+void UnsecureDisplay( struct _XDisplay *dpy );
+int PingServer( struct _XDisplay *dpy );
+
+void setup_modifiers( struct _XDisplay *mdpy, int numlock );
+void restore_modifiers( void );
+
+void setCursor( struct _XDisplay *mdpy, int window, int shape );
+
+
+extern int rfd; /* for select() loops */
+
+extern char *dname; /* d->name */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _TDM_GREET_H_ */
diff --git a/tdm/kfrontend/tdmadmindialog.cpp b/tdm/kfrontend/tdmadmindialog.cpp
new file mode 100644
index 00000000..6486eb3d
--- /dev/null
+++ b/tdm/kfrontend/tdmadmindialog.cpp
@@ -0,0 +1,176 @@
+ /*
+
+ Admin dialog
+
+ Copyright (C) 1997, 1998, 2000 Steffen Hansen <hansen@kde.org>
+ Copyright (C) 2000-2003 Oswald Buddenhagen <ossi@kde.org>
+
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ */
+
+#include "tdmadmindialog.h"
+#include "tdmconfig.h"
+#include "kgdialog.h"
+#include "tdm_greet.h"
+#include <stdlib.h>
+
+#include <kapplication.h>
+#include <kseparator.h>
+#include <klocale.h>
+#include <kpushbutton.h>
+#include <kstdguiitem.h>
+
+#include <tqcombobox.h>
+#include <tqvbuttongroup.h>
+#include <tqstyle.h>
+#include <tqlayout.h>
+#include <tqaccel.h>
+#include <tqpopupmenu.h>
+
+int TDMAdmin::curPlugin = -1;
+PluginList TDMAdmin::pluginList;
+
+TDMAdmin::TDMAdmin( const TQString &user, TQWidget *_parent )
+ : inherited( _parent )
+ , verify( 0 ), curUser(user)
+{
+ TQSizePolicy fp( TQSizePolicy::Fixed, TQSizePolicy::Fixed );
+
+ TQVBoxLayout *box = new TQVBoxLayout( this, 10 );
+
+ TQHBoxLayout *hlay = new TQHBoxLayout( box );
+
+ GSendInt( G_ReadDmrc );
+ GSendStr( "root" );
+ GRecvInt(); // ignore status code ...
+
+ if (curPlugin < 0) {
+ curPlugin = 0;
+ pluginList = KGVerify::init( "classic" );
+ }
+ verify = new KGStdVerify( this, this,
+ this, "root",
+ pluginList, KGreeterPlugin::Authenticate,
+ KGreeterPlugin::Shutdown );
+ verify->selectPlugin( curPlugin );
+ box->addLayout( verify->getLayout() );
+ TQAccel *accel = new TQAccel( this );
+ accel->insertItem( ALT+Key_A, 0 );
+ connect( accel, TQT_SIGNAL(activated(int)), TQT_SLOT(slotActivatePlugMenu()) );
+
+ box->addWidget( new KSeparator( KSeparator::HLine, this ) );
+
+ okButton = new KPushButton( KStdGuiItem::ok(), this );
+ okButton->setSizePolicy( fp );
+ okButton->setDefault( true );
+ cancelButton = new KPushButton( KStdGuiItem::cancel(), this );
+ cancelButton->setSizePolicy( fp );
+
+ hlay = new TQHBoxLayout( box );
+ hlay->addStretch( 1 );
+ hlay->addWidget( okButton );
+ hlay->addStretch( 1 );
+ hlay->addWidget( cancelButton );
+ hlay->addStretch( 1 );
+
+ connect( okButton, TQT_SIGNAL(clicked()), TQT_SLOT(accept()) );
+ connect( cancelButton, TQT_SIGNAL(clicked()), TQT_SLOT(reject()) );
+
+ slotWhenChanged();
+}
+
+TDMAdmin::~TDMAdmin()
+{
+ hide();
+ delete verify;
+}
+
+void
+TDMAdmin::slotActivatePlugMenu()
+{
+ TQPopupMenu *cmnu = verify->getPlugMenu();
+ TQSize sh( cmnu->sizeHint() / 2 );
+ cmnu->exec( geometry().center() - TQPoint( sh.width(), sh.height() ) );
+}
+
+void
+TDMAdmin::accept()
+{
+ verify->accept();
+}
+
+void
+TDMAdmin::slotWhenChanged()
+{
+ verify->abort();
+ verify->setEnabled( 1 );
+ verify->start();
+}
+
+void
+TDMAdmin::bye_bye()
+{
+ GSendInt( G_GetDmrc );
+ GSendStr( "Session" );
+ char *sess = GRecvStr();
+ if (sess && strcmp(sess, "admin")) {
+ GSendInt( G_PutDmrc );
+ GSendStr( "OrigSession");
+ GSendStr( sess);
+ free(sess);
+ }
+
+ GSendInt( G_PutDmrc );
+ GSendStr( "Session" );
+ GSendStr( "admin" );
+ inherited::accept();
+}
+
+void
+TDMAdmin::verifyPluginChanged( int id )
+{
+ curPlugin = id;
+ adjustSize();
+}
+
+void
+TDMAdmin::verifyOk()
+{
+ bye_bye();
+}
+
+void
+TDMAdmin::verifyFailed()
+{
+ okButton->setEnabled( false );
+ cancelButton->setEnabled( false );
+}
+
+void
+TDMAdmin::verifyRetry()
+{
+ okButton->setEnabled( true );
+ cancelButton->setEnabled( true );
+}
+
+void
+TDMAdmin::verifySetUser( const TQString & )
+{
+}
+
+
+#include "tdmadmindialog.moc"
diff --git a/tdm/kfrontend/tdmadmindialog.h b/tdm/kfrontend/tdmadmindialog.h
new file mode 100644
index 00000000..e5a68fbb
--- /dev/null
+++ b/tdm/kfrontend/tdmadmindialog.h
@@ -0,0 +1,70 @@
+ /*
+
+ Shutdown dialog
+
+ Copyright (C) 1997, 1998 Steffen Hansen <hansen@kde.org>
+ Copyright (C) 2000-2003 Oswald Buddenhagen <ossi@kde.org>
+
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ */
+
+
+#ifndef TDMADMIN_H
+#define TDMADMIN_H
+
+#include "kgverify.h"
+
+#include <tqradiobutton.h>
+
+class LiloInfo;
+class TQLabel;
+class KPushButton;
+class TQButtonGroup;
+class TQComboBox;
+
+class TDMAdmin : public FDialog, public KGVerifyHandler {
+ Q_OBJECT
+ typedef FDialog inherited;
+
+public:
+ TDMAdmin( const TQString &user, TQWidget *_parent = 0 );
+ ~TDMAdmin();
+
+public slots:
+ void accept();
+ void slotWhenChanged();
+ void slotActivatePlugMenu();
+
+private:
+ void bye_bye();
+
+ KPushButton *okButton, *cancelButton;
+ KGStdVerify *verify;
+ TQString curUser;
+
+ static int curPlugin;
+ static PluginList pluginList;
+
+public: // from KGVerifyHandler
+ virtual void verifyPluginChanged( int id );
+ virtual void verifyOk();
+ virtual void verifyFailed();
+ virtual void verifyRetry();
+ virtual void verifySetUser( const TQString &user );
+};
+
+#endif
diff --git a/tdm/kfrontend/tdmclock.cpp b/tdm/kfrontend/tdmclock.cpp
new file mode 100644
index 00000000..2b2a99ce
--- /dev/null
+++ b/tdm/kfrontend/tdmclock.cpp
@@ -0,0 +1,176 @@
+/*
+
+clock module for tdm
+
+Copyright (C) 2000 Espen Sand, espen@kde.org
+ Based on work by NN(yet to be determined)
+flicker free code by Remi Guyomarch <rguyom@mail.dotcom.fr>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#include "tdmclock.h"
+
+//#include <kapplication.h>
+//#include <kconfig.h>
+
+#include <tqdatetime.h>
+#include <tqpixmap.h>
+#include <tqpainter.h>
+#include <tqtimer.h>
+
+KdmClock::KdmClock( TQWidget *parent, const char *name )
+ : inherited( parent, name )
+{
+ // start timer
+ TQTimer *timer = new TQTimer( this );
+ connect( timer, TQT_SIGNAL(timeout()), TQT_SLOT(timeout()) );
+ timer->start( 1000 );
+
+ // reading rc file
+ //KConfig *config = kapp->config();
+
+ //config->setGroup( "Option" );
+ mDate = false;//config->readNumEntry( "date", FALSE );
+ mSecond = true;//config->readNumEntry( "second", TRUE );
+ mDigital = false;//config->readNumEntry( "digital", FALSE );
+ mBorder = false;//config->readNumEntry( "border", FALSE );
+
+ //config->setGroup( "Font" );
+ mFont.setFamily( TQString::fromLatin1("Utopia")/*config->readEntry( "Family", "Utopia")*/ );
+ mFont.setPointSize( 51/*config->readNumEntry( "Point Size", 51)*/ );
+ mFont.setWeight( 75/*config->readNumEntry( "Weight", 75)*/ );
+ mFont.setItalic( TRUE/*config->readNumEntry( "Italic",TRUE )*/ );
+ mFont.setBold( TRUE/*config->readNumEntry( "Bold",TRUE )*/ );
+
+ setFixedSize( 100, 100 );
+
+ if (mBorder) {
+ setLineWidth( 1 );
+ setFrameStyle( Box|Plain );
+ //setFrameStyle( WinPanel|Sunken );
+ }
+
+/*
+ if (!mDigital) {
+ if (height() < width())
+ resize( height(), height() );
+ else
+ resize( width() ,width() );
+ }
+*/
+
+ //setBackgroundOrigin( WindowOrigin );
+ mBackgroundBrush = backgroundBrush();
+ setBackgroundMode( NoBackground );
+ repaint();
+}
+
+
+void KdmClock::showEvent( TQShowEvent * )
+{
+ repaint();
+}
+
+
+void KdmClock::timeout()
+{
+ repaint();
+}
+
+void KdmClock::paintEvent( TQPaintEvent * )
+{
+ if (!isVisible())
+ return;
+
+ TQPainter p( this );
+ drawFrame( &p );
+
+ TQPixmap pm( contentsRect().size() );
+ TQPainter paint;
+ paint.begin( &pm );
+ paint.fillRect( contentsRect(), mBackgroundBrush );
+
+ // get current time
+ TQTime time = TQTime::currentTime();
+
+/*
+ if (mDigital) {
+ TQString buf;
+ if (mSecond)
+ buf.sprintf( "%02d:%02d:%02d", time.hour(), time.minute(),
+ time.second() );
+ else
+ buf.sprintf( "%02d:%02d", time.hour(), time.minute() );
+ mFont.setPointSize( QMIN( (int)(width()/buf.length()*1.5),height() ) );
+ paint.setFont( mFont );
+ paint.setPen( backgroundColor() );
+ paint.drawText( contentsRect(),AlignHCenter|AlignVCenter, buf,-1,0,0 );
+ } else {
+*/
+ TQPointArray pts;
+ TQPoint cp = contentsRect().center() - TQPoint( 2,2 );
+ int d = QMIN( contentsRect().width()-15,contentsRect().height()-15 );
+ paint.setPen( foregroundColor() );
+ paint.setBrush( foregroundColor() );
+
+ TQWMatrix matrix;
+ matrix.translate( cp.x(), cp.y() );
+ matrix.scale( d/1000.0F, d/1000.0F );
+
+ // Hour
+ float h_angle = 30*(time.hour()%12-3) + time.minute()/2;
+ matrix.rotate( h_angle );
+ paint.setWorldMatrix( matrix );
+ pts.setPoints( 4, -20,0, 0,-20, 300,0, 0,20 );
+ paint.drawPolygon( pts );
+ matrix.rotate( -h_angle );
+
+ // Minute
+ float m_angle = (time.minute()-15)*6;
+ matrix.rotate( m_angle );
+ paint.setWorldMatrix( matrix );
+ pts.setPoints( 4, -10,0, 0,-10, 400,0, 0,10 );
+ paint.drawPolygon( pts );
+ matrix.rotate( -m_angle );
+
+ // Second
+ float s_angle = (time.second()-15)*6;
+ matrix.rotate( s_angle );
+ paint.setWorldMatrix( matrix );
+ pts.setPoints( 4,0,0,0,0,400,0,0,0 );
+ if (mSecond)
+ paint.drawPolygon( pts );
+ matrix.rotate( -s_angle );
+
+ // quadrante
+ for (int i=0 ; i < 60 ; i++) {
+ paint.setWorldMatrix( matrix );
+ if ((i % 5) == 0)
+ paint.drawLine( 450,0, 500,0 ); // draw hour lines
+ else
+ paint.drawPoint( 480,0 ); // draw second lines
+ matrix.rotate( 6 );
+ }
+
+// } // if (mDigital)
+ paint.end();
+
+ // flicker free code by Remi Guyomarch <rguyom@mail.dotcom.fr>
+ bitBlt( this, contentsRect().topLeft(), &pm );
+}
+
+#include "tdmclock.moc"
diff --git a/tdm/kfrontend/tdmclock.h b/tdm/kfrontend/tdmclock.h
new file mode 100644
index 00000000..89a48eb8
--- /dev/null
+++ b/tdm/kfrontend/tdmclock.h
@@ -0,0 +1,52 @@
+/*
+
+clock module for tdm
+
+Copyright (C) 2000 Espen Sand, espen@kde.org
+ Based on work by NN (yet to be determined)
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#ifndef _TDM_CLOCK_H_
+#define _TDM_CLOCK_H_
+
+#include <tqframe.h>
+
+class KdmClock : public TQFrame {
+ Q_OBJECT
+ typedef TQFrame inherited;
+
+ public:
+ KdmClock( TQWidget *parent=0, const char *name=0 );
+
+ protected:
+ virtual void showEvent( TQShowEvent * );
+ virtual void paintEvent( TQPaintEvent * );
+
+ private slots:
+ void timeout();
+
+ private:
+ TQBrush mBackgroundBrush;
+ TQFont mFont;
+ bool mSecond;
+ bool mDigital;
+ bool mDate;
+ bool mBorder;
+};
+
+#endif
diff --git a/tdm/kfrontend/tdmconfig.cpp b/tdm/kfrontend/tdmconfig.cpp
new file mode 100644
index 00000000..5b57a637
--- /dev/null
+++ b/tdm/kfrontend/tdmconfig.cpp
@@ -0,0 +1,179 @@
+/*
+
+Config for tdm
+
+Copyright (C) 1997, 1998 Steffen Hansen <hansen@kde.org>
+Copyright (C) 2000-2003 Oswald Buddenhagen <ossi@kde.org>
+
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#include "tdmconfig.h"
+#include "tdm_greet.h"
+
+#include <kapplication.h>
+#include <klocale.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/utsname.h>
+
+struct timeval st = {0, 0};
+
+CONF_GREET_DEFS
+
+TQString _stsFile;
+bool _isLocal;
+bool _authorized;
+
+static TQString
+GetCfgQStr( int id )
+{
+ char *tmp = GetCfgStr( id );
+ TQString qs = TQString::fromUtf8( tmp );
+ free( tmp );
+ return qs;
+}
+
+static TQStringList
+GetCfgQStrList( int id )
+{
+ int i, len;
+ char **tmp = GetCfgStrArr( id, &len );
+ TQStringList qsl;
+ for (i = 0; i < len - 1; i++) {
+ qsl.append( TQString::fromUtf8( tmp[i] ) );
+ free( tmp[i] );
+ }
+ free( tmp );
+ return qsl;
+}
+
+// Based on kconfigbase.cpp
+static TQFont
+Str2Font( const TQString &aValue )
+{
+ uint nFontBits;
+ TQFont aRetFont;
+ TQString chStr;
+
+ TQStringList sl = TQStringList::split( TQString::fromLatin1(","), aValue );
+
+ if (sl.count() == 1) {
+ /* X11 font spec */
+ aRetFont = TQFont( aValue );
+ aRetFont.setRawMode( true );
+ } else if (sl.count() == 10) {
+ /* qt3 font spec */
+ aRetFont.fromString( aValue );
+ } else if (sl.count() == 6) {
+ /* backward compatible kde2 font spec */
+ aRetFont = TQFont( sl[0], sl[1].toInt(), sl[4].toUInt() );
+
+ aRetFont.setStyleHint( (TQFont::StyleHint)sl[2].toUInt() );
+
+ nFontBits = sl[5].toUInt();
+ aRetFont.setItalic( (nFontBits & 0x01) != 0 );
+ aRetFont.setUnderline( (nFontBits & 0x02) != 0 );
+ aRetFont.setStrikeOut( (nFontBits & 0x04) != 0 );
+ aRetFont.setFixedPitch( (nFontBits & 0x08) != 0 );
+ aRetFont.setRawMode( (nFontBits & 0x20) != 0 );
+ }
+ aRetFont.setStyleStrategy( (TQFont::StyleStrategy)
+ (TQFont::PreferMatch |
+ (_antiAliasing ? TQFont::PreferAntialias : TQFont::NoAntialias)) );
+
+ return aRetFont;
+}
+
+extern "C"
+void init_config( void )
+{
+ CONF_GREET_INIT
+
+ _isLocal = GetCfgInt( C_isLocal );
+ _hasConsole = _hasConsole && _isLocal && GetCfgInt( C_hasConsole );
+ _authorized = GetCfgInt( C_isAuthorized );
+
+ _stsFile = _dataDir + "/tdmsts";
+
+ // Greet String
+ char hostname[256], *ptr;
+ hostname[0] = '\0';
+ if (!gethostname( hostname, sizeof(hostname) ))
+ hostname[sizeof(hostname)-1] = '\0';
+ struct utsname tuname;
+ uname( &tuname );
+ TQString gst = _greetString;
+ _greetString = TQString::null;
+ int i, j, l = gst.length();
+ for (i = 0; i < l; i++) {
+ if (gst[i] == '%') {
+ switch (gst[++i].cell()) {
+ case '%': _greetString += gst[i]; continue;
+ case 'd': ptr = dname; break;
+ case 'h': ptr = hostname; break;
+ case 'n': ptr = tuname.nodename;
+ for (j = 0; ptr[j]; j++)
+ if (ptr[j] == '.') {
+ ptr[j] = 0;
+ break;
+ }
+ break;
+ case 's': ptr = tuname.sysname; break;
+ case 'r': ptr = tuname.release; break;
+ case 'm': ptr = tuname.machine; break;
+ default: _greetString += i18n("[fix tdmrc!]"); continue;
+ }
+ _greetString += TQString::fromLocal8Bit( ptr );
+ } else
+ _greetString += gst[i];
+ }
+}
+
+
+/* out-of-place utility function */
+void
+decodeSess( dpySpec *sess, TQString &user, TQString &loc )
+{
+ if (sess->flags & isTTY) {
+ user =
+ i18n( "%1: TTY login", "%1: %n TTY logins", sess->count )
+ .arg( sess->user );
+ loc =
+#ifdef HAVE_VTS
+ sess->vt ?
+ TQString("vt%1").arg( sess->vt ) :
+#endif
+ TQString::fromLatin1( *sess->from ? sess->from : sess->display );
+ } else {
+ user =
+ !sess->user ?
+ i18n("Unused") :
+ *sess->user ?
+ i18n("user: session type", "%1: %2")
+ .arg( sess->user ).arg( sess->session ) :
+ i18n("... host", "X login on %1").arg( sess->session );
+ loc =
+#ifdef HAVE_VTS
+ sess->vt ?
+ TQString("%1, vt%2").arg( sess->display ).arg( sess->vt ) :
+#endif
+ TQString::fromLatin1( sess->display );
+ }
+}
diff --git a/tdm/kfrontend/tdmconfig.h b/tdm/kfrontend/tdmconfig.h
new file mode 100644
index 00000000..275cafa1
--- /dev/null
+++ b/tdm/kfrontend/tdmconfig.h
@@ -0,0 +1,69 @@
+/*
+
+Configuration for tdm
+
+Copyright (C) 1997, 1998, 2000 Steffen Hansen <hansen@kde.org>
+Copyright (C) 2000-2003 Oswald Buddenhagen <ossi@kde.org>
+
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+
+#ifndef TDMCONFIG_H
+#define TDMCONFIG_H
+
+#include <config.h>
+
+#include "config.ci"
+
+#ifdef __cplusplus
+
+#include <tqstring.h>
+#include <tqstringlist.h>
+#include <tqfont.h>
+#include <sys/time.h>
+
+extern TQString _stsFile;
+extern bool _isLocal;
+extern bool _authorized;
+
+CONF_GREET_CPP_DECLS
+
+// this file happens to be included everywhere, so just put it here
+struct dpySpec;
+void decodeSess( dpySpec *sess, TQString &user, TQString &loc );
+
+extern struct timeval st;
+
+inline TQString timestamp() {
+ struct timeval nst;
+ gettimeofday(&nst, 0);
+ if (!st.tv_sec)
+ gettimeofday(&st, 0);
+
+ TQString ret;
+ ret.sprintf("[%07ld]", (nst.tv_sec - st.tv_sec) * 1000 + (nst.tv_usec - st.tv_usec) / 1000);
+ return ret;
+}
+
+extern "C"
+#endif
+void init_config( void );
+
+CONF_GREET_C_DECLS
+
+#endif /* TDMCONFIG_H */
diff --git a/tdm/kfrontend/tdmctl.c b/tdm/kfrontend/tdmctl.c
new file mode 100644
index 00000000..d6abe959
--- /dev/null
+++ b/tdm/kfrontend/tdmctl.c
@@ -0,0 +1,234 @@
+/*
+
+TDM remote control application
+
+Copyright (C) 2004 Oswald Buddenhagen <ossi@kde.org>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <ctype.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+static int
+openctl( int fd, int err, const char *ctl, const char *dpy )
+{
+ struct sockaddr_un sa;
+
+ sa.sun_family = AF_UNIX;
+ if (dpy)
+ snprintf( sa.sun_path, sizeof(sa.sun_path),
+ "%s/dmctl-%s/socket", ctl, dpy );
+ else
+ snprintf( sa.sun_path, sizeof(sa.sun_path),
+ "%s/dmctl/socket", ctl );
+ if (!connect( fd, (struct sockaddr *)&sa, sizeof(sa) ))
+ return 1;
+ if (err)
+ fprintf( stderr, "Cannot connect socket '%s'.\n", sa.sun_path );
+ return 0;
+}
+
+static const char *
+readcfg( const char *cfg )
+{
+ FILE *fp;
+ const char *ctl;
+ char *ptr, *ptr2;
+ char buf[1024];
+
+ if (!(fp = fopen( cfg, "r" ))) {
+ fprintf( stderr,
+ "Cannot open tdm config file '%s'.\n",
+ cfg );
+ return 0;
+ }
+ ctl = "/var/run/xdmctl";
+ while (fgets( buf, sizeof(buf), fp ))
+ if (!strncmp( buf, "FifoDir", 7 )) {
+ ptr = buf + 7;
+ while (*ptr && isspace( *ptr ))
+ ptr++;
+ if (*ptr++ != '=')
+ continue;
+ while (*ptr && isspace( *ptr ))
+ ptr++;
+ for (ptr2 = buf + strlen( buf );
+ ptr2 > ptr && isspace( *(ptr2 - 1) );
+ ptr2--);
+ *ptr2 = 0;
+ ctl = strdup( ptr );
+ break;
+ }
+ fclose( fp );
+ return ctl;
+}
+
+static int
+exe( int fd, const char *in, int len )
+{
+ char buf[4096];
+
+ if (write( fd, in, len ) != len) {
+ fprintf( stderr, "Cannot send command\n" );
+ return 1;
+ }
+ do {
+ if ((len = read(fd, buf, sizeof(buf))) <= 0) {
+ fprintf(stderr, "Cannot receive reply\n");
+ return 1;
+ }
+ fwrite(buf, 1, len, stdout);
+ } while (buf[len - 1] != '\n');
+ return 0;
+}
+
+static int
+run( int fd, char **argv )
+{
+ unsigned len, l;
+ char buf[1024];
+
+ if (!*argv)
+ return exe( fd, "caps\n", 5 );
+ if (!strcmp( *argv, "-" )) {
+ for (;;) {
+ if (isatty( 0 )) {
+ fputs( "> ", stdout );
+ fflush( stdout );
+ }
+ if (!fgets( buf, sizeof(buf), stdin ))
+ return 0;
+ if (exe( fd, buf, strlen( buf ) ))
+ return 1;
+ }
+ } else {
+ len = strlen( *argv );
+ if (len >= sizeof(buf))
+ goto bad;
+ memcpy( buf, *argv, len );
+ while (*++argv) {
+ l = strlen( *argv );
+ if (len + l + 1 >= sizeof(buf))
+ goto bad;
+ buf[len++] = '\t';
+ memcpy( buf + len, *argv, l );
+ len += l;
+ }
+ buf[len++] = '\n';
+ return exe( fd, buf, len );
+ bad:
+ fprintf( stderr, "Command too long\n" );
+ return 1;
+ }
+}
+
+int
+main( int argc, char **argv )
+{
+ char *dpy = getenv( "DISPLAY" );
+ const char *ctl = getenv( "DM_CONTROL" );
+ const char *cfg = KDE_CONFDIR "/tdm/tdmrc";
+ char *ptr;
+ int fd;
+
+ (void)argc;
+ while (*++argv) {
+ ptr = *argv;
+ if (*ptr != '-' || !*(ptr + 1))
+ break;
+ ptr++;
+ if (*ptr == '-')
+ ptr++;
+ if (!strcmp( ptr, "h" ) || !strcmp( ptr, "help" )) {
+ puts(
+"Usage: tdmctl [options] [command [command arguments]]\n"
+"\n"
+"Options are:\n"
+" -h -help This help message.\n"
+" -g -global Use global control socket even if $DISPLAY is set\n"
+" -d -display Override $DISPLAY\n"
+" -s -sockets Override $DM_CONTROL\n"
+" -c -config Use alternative tdm config file\n"
+"\n"
+"The directory in which the sockets are located is determined this way:\n"
+"- the -s option is examined\n"
+"- the $DM_CONTROL variable is examined\n"
+"- the tdm config file is searched for the FifoDir key\n"
+"- /var/run/xdmctl and /var/run are tried\n"
+"\n"
+"If $DISPLAY is set (or -d was specified) and -g was not specified, the\n"
+"display-specific control socket will be used, otherwise the global one.\n"
+"\n"
+"Tokens in the command and the reply are tab-separated.\n"
+"Command arguments can be specified as separate command line parameters,\n"
+"in which case they are simply concatenated with tabs in between.\n"
+"\n"
+"If the command is '-', tdmctl reads commands from stdin.\n"
+"The default command is 'caps'.\n"
+ );
+ return 0;
+ } else if (!strcmp( ptr, "g" ) || !strcmp( ptr, "global" ))
+ dpy = 0;
+ else if (!strcmp( ptr, "d" ) || !strcmp( ptr, "display" )) {
+ if (!argv[1])
+ goto needarg;
+ dpy = *++argv;
+ } else if (!strcmp( ptr, "s" ) || !strcmp( ptr, "sockets" )) {
+ if (!argv[1])
+ goto needarg;
+ ctl = *++argv;
+ } else if (!strcmp( ptr, "c" ) || !strcmp( ptr, "config" )) {
+ if (!argv[1]) {
+ needarg:
+ fprintf( stderr, "Option '%s' needs argument.\n",
+ ptr );
+ return 1;
+ }
+ cfg = *++argv;
+ } else {
+ fprintf( stderr, "Unknown option '%s'.\n", ptr );
+ return 1;
+ }
+ }
+ if ((!ctl || !*ctl) && *cfg)
+ ctl = readcfg( cfg );
+ if ((fd = socket( PF_UNIX, SOCK_STREAM, 0 )) < 0) {
+ fprintf( stderr, "Cannot create UNIX socket\n" );
+ return 1;
+ }
+ if (dpy && (ptr = strchr( dpy, ':' )) && (ptr = strchr( ptr, '.' )))
+ *ptr = 0;
+ if (ctl && *ctl) {
+ if (!openctl( fd, 1, ctl, dpy ))
+ return 1;
+ } else {
+ if (!openctl( fd, 0, "/var/run/xdmctl", dpy ) &&
+ !openctl( fd, 0, "/var/run", dpy ))
+ {
+ fprintf( stderr, "No command socket found.\n" );
+ return 1;
+ }
+ }
+ return run( fd, argv );
+}
diff --git a/tdm/kfrontend/tdmshutdown.cpp b/tdm/kfrontend/tdmshutdown.cpp
new file mode 100644
index 00000000..e546f62b
--- /dev/null
+++ b/tdm/kfrontend/tdmshutdown.cpp
@@ -0,0 +1,925 @@
+/*
+
+Shutdown dialog
+
+Copyright (C) 1997, 1998, 2000 Steffen Hansen <hansen@kde.org>
+Copyright (C) 2000-2003,2005 Oswald Buddenhagen <ossi@kde.org>
+
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#include "tdmshutdown.h"
+#include "tdm_greet.h"
+
+#include <kapplication.h>
+#include <kseparator.h>
+#include <klocale.h>
+#include <kpushbutton.h>
+#include <kstdguiitem.h>
+#include <kprocio.h>
+#include <kdialog.h>
+#include <kstandarddirs.h>
+#include <kuser.h>
+#include <kconfig.h>
+#include <kiconloader.h>
+
+#include <tqcombobox.h>
+#include <tqvbuttongroup.h>
+#include <tqstyle.h>
+#include <tqlayout.h>
+#include <tqaccel.h>
+#include <tqpopupmenu.h>
+#include <tqcheckbox.h>
+#include <tqlineedit.h>
+#include <tqlabel.h>
+#include <tqdatetime.h>
+#include <tqlistview.h>
+#include <tqheader.h>
+#include <tqdatetime.h>
+#include <tqregexp.h>
+
+#define KDmh KDialog::marginHint()
+#define KDsh KDialog::spacingHint()
+
+#include <stdlib.h>
+
+extern bool has_twin;
+
+int TDMShutdownBase::curPlugin = -1;
+PluginList TDMShutdownBase::pluginList;
+
+TDMShutdownBase::TDMShutdownBase( int _uid, TQWidget *_parent )
+ : inherited( _parent )
+ , box( new TQVBoxLayout( this, KDmh, KDsh ) )
+#ifdef HAVE_VTS
+ , willShut( true )
+#endif
+ , mayNuke( false )
+ , doesNuke( false )
+ , mayOk( true )
+ , maySched( false )
+ , rootlab( 0 )
+ , verify( 0 )
+ , needRoot( -1 )
+ , uid( _uid )
+{
+}
+
+TDMShutdownBase::~TDMShutdownBase()
+{
+ hide();
+ delete verify;
+}
+
+void
+TDMShutdownBase::complete( TQWidget *prevWidget )
+{
+ TQSizePolicy fp( TQSizePolicy::Fixed, TQSizePolicy::Fixed );
+
+ if (uid &&
+ ((willShut && _allowShutdown == SHUT_ROOT) ||
+ (mayNuke && _allowNuke == SHUT_ROOT)))
+ {
+ rootlab = new TQLabel( i18n("Root authorization required."), this );
+ box->addWidget( rootlab );
+ if (curPlugin < 0) {
+ curPlugin = 0;
+ pluginList = KGVerify::init( _pluginsShutdown );
+ }
+ verify = new KGStdVerify( this, this,
+ prevWidget, "root",
+ pluginList, KGreeterPlugin::Authenticate,
+ KGreeterPlugin::Shutdown );
+ verify->selectPlugin( curPlugin );
+ box->addLayout( verify->getLayout() );
+ TQAccel *accel = new TQAccel( this );
+ accel->insertItem( ALT+Key_A, 0 );
+ connect( accel, TQT_SIGNAL(activated( int )), TQT_SLOT(slotActivatePlugMenu()) );
+ }
+
+ box->addWidget( new KSeparator( KSeparator::HLine, this ) );
+
+ TQBoxLayout *hlay = new TQHBoxLayout( box, KDsh );
+ hlay->addStretch( 1 );
+ if (mayOk) {
+ okButton = new KPushButton( KStdGuiItem::ok(), this );
+ okButton->setSizePolicy( fp );
+ okButton->setDefault( true );
+ hlay->addWidget( okButton );
+ hlay->addStretch( 1 );
+ connect( okButton, TQT_SIGNAL(clicked()), TQT_SLOT(accept()) );
+ }
+ if (maySched) {
+ KPushButton *schedButton =
+ new KPushButton( KGuiItem( i18n("&Schedule...") ), this );
+ schedButton->setSizePolicy( fp );
+ hlay->addWidget( schedButton );
+ hlay->addStretch( 1 );
+ connect( schedButton, TQT_SIGNAL(clicked()), TQT_SLOT(slotSched()) );
+ }
+ cancelButton = new KPushButton( KStdGuiItem::cancel(), this );
+ cancelButton->setSizePolicy( fp );
+ if (!mayOk)
+ cancelButton->setDefault( true );
+ hlay->addWidget( cancelButton );
+ hlay->addStretch( 1 );
+ connect( cancelButton, TQT_SIGNAL(clicked()), TQT_SLOT(reject()) );
+
+ updateNeedRoot();
+}
+
+void
+TDMShutdownBase::slotActivatePlugMenu()
+{
+ if (needRoot) {
+ TQPopupMenu *cmnu = verify->getPlugMenu();
+ if (!cmnu)
+ return;
+ TQSize sh( cmnu->sizeHint() / 2 );
+ cmnu->exec( geometry().center() - TQPoint( sh.width(), sh.height() ) );
+ }
+}
+
+void
+TDMShutdownBase::accept()
+{
+ if (needRoot == 1)
+ verify->accept();
+ else
+ accepted();
+}
+
+void
+TDMShutdownBase::slotSched()
+{
+ done( Schedule );
+}
+
+void
+TDMShutdownBase::updateNeedRoot()
+{
+ int nNeedRoot = uid &&
+ (((willShut && _allowShutdown == SHUT_ROOT) ||
+ (_allowNuke == SHUT_ROOT && doesNuke)));
+ if (verify && nNeedRoot != needRoot) {
+ if (needRoot == 1)
+ verify->abort();
+ needRoot = nNeedRoot;
+ rootlab->setEnabled( needRoot );
+ verify->setEnabled( needRoot );
+ if (needRoot)
+ verify->start();
+ }
+}
+
+void
+TDMShutdownBase::accepted()
+{
+ inherited::done( needRoot ? (int)Authed : (int)Accepted );
+}
+
+void
+TDMShutdownBase::verifyPluginChanged( int id )
+{
+ curPlugin = id;
+ adjustSize();
+}
+
+void
+TDMShutdownBase::verifyOk()
+{
+ accepted();
+}
+
+void
+TDMShutdownBase::verifyFailed()
+{
+ okButton->setEnabled( false );
+ cancelButton->setEnabled( false );
+}
+
+void
+TDMShutdownBase::verifyRetry()
+{
+ okButton->setEnabled( true );
+ cancelButton->setEnabled( true );
+}
+
+void
+TDMShutdownBase::verifySetUser( const TQString & )
+{
+}
+
+
+static void
+doShutdown( int type, const char *os )
+{
+ GSet( 1 );
+ GSendInt( G_Shutdown );
+ GSendInt( type );
+ GSendInt( 0 );
+ GSendInt( 0 );
+ GSendInt( SHUT_FORCE );
+ GSendInt( 0 ); /* irrelevant, will timeout immediately anyway */
+ GSendStr( os );
+ GSet( 0 );
+}
+
+
+
+TDMShutdown::TDMShutdown( int _uid, TQWidget *_parent )
+ : inherited( _uid, _parent )
+{
+ setCaption(i18n("Shutdown TDE"));
+
+ TQSizePolicy fp( TQSizePolicy::Fixed, TQSizePolicy::Fixed );
+
+ TQHBoxLayout *hlay = new TQHBoxLayout( box, KDsh );
+
+ howGroup = new TQVButtonGroup( i18n("Shutdown Type"), this );
+ hlay->addWidget( howGroup, 0, AlignTop );
+
+ TQRadioButton *rb;
+ rb = new TDMRadioButton( i18n("&Turn off computer"), howGroup );
+ rb->setChecked( true );
+ rb->setFocus();
+
+ restart_rb = new TDMRadioButton( i18n("&Restart computer"), howGroup );
+
+ connect( rb, TQT_SIGNAL(doubleClicked()), TQT_SLOT(accept()) );
+ connect( restart_rb, TQT_SIGNAL(doubleClicked()), TQT_SLOT(accept()) );
+
+ GSet( 1 );
+ GSendInt( G_ListBootOpts );
+ if (GRecvInt() == BO_OK) { /* XXX show dialog on failure */
+ char **tlist = GRecvStrArr( 0 );
+ int defaultTarget = GRecvInt();
+ oldTarget = GRecvInt();
+ TQWidget *hlp = new TQWidget( howGroup );
+ targets = new TQComboBox( hlp );
+ for (int i = 0; tlist[i]; i++)
+ targets->insertItem( TQString(TQString::fromLocal8Bit( tlist[i] )) );
+ freeStrArr( tlist );
+ targets->setCurrentItem( oldTarget == -1 ? defaultTarget : oldTarget );
+ TQHBoxLayout *hb = new TQHBoxLayout( hlp, 0, KDsh );
+ int spc = kapp->style().pixelMetric( TQStyle::PM_ExclusiveIndicatorWidth )
+ + howGroup->insideSpacing();
+ hb->addSpacing( spc );
+ hb->addWidget( targets );
+ connect( targets, TQT_SIGNAL(activated( int )), TQT_SLOT(slotTargetChanged()) );
+ }
+ GSet( 0 );
+
+ howGroup->setSizePolicy( fp );
+
+ schedGroup = new TQGroupBox( i18n("Scheduling"), this );
+ hlay->addWidget( schedGroup, 0, AlignTop );
+
+ le_start = new TQLineEdit( schedGroup );
+ TQLabel *lab1 = new TQLabel( le_start, i18n("&Start:"), schedGroup );
+
+ le_timeout = new TQLineEdit( schedGroup );
+ TQLabel *lab2 = new TQLabel( le_timeout, i18n("T&imeout:"), schedGroup );
+
+ cb_force = new TQCheckBox( i18n("&Force after timeout"), schedGroup );
+ if (_allowNuke != SHUT_NONE) {
+ connect( cb_force, TQT_SIGNAL(clicked()), TQT_SLOT(slotWhenChanged()) );
+ mayNuke = true;
+ } else
+ cb_force->setEnabled( false );
+
+ TQGridLayout *grid = new TQGridLayout( schedGroup, 0, 0, KDmh, KDsh );
+ grid->addRowSpacing( 0, schedGroup->fontMetrics().height() - 5 );
+ grid->addWidget( lab1, 1, 0, Qt::AlignRight );
+ grid->addWidget( le_start, 1, 1 );
+ grid->addWidget( lab2, 2, 0, Qt::AlignRight );
+ grid->addWidget( le_timeout, 2, 1 );
+ grid->addMultiCellWidget( cb_force, 3,3, 0,1 );
+
+ schedGroup->setSizePolicy( fp );
+
+ le_start->setText( "0" );
+ if (_defSdMode == SHUT_SCHEDULE)
+ le_timeout->setText( "-1" );
+ else {
+ le_timeout->setText( "0" );
+ if (_defSdMode == SHUT_FORCENOW && cb_force->isEnabled())
+ cb_force->setChecked( true );
+ }
+
+ complete( schedGroup );
+}
+
+static int
+get_date( const char *str )
+{
+ KProcIO prc;
+ prc << "/bin/date" << "+%s" << "-d" << str;
+ prc.start( KProcess::Block, false );
+ TQString dstr;
+ if (prc.readln( dstr, false, 0 ) < 0)
+ return -1;
+ return dstr.toInt();
+}
+
+void
+TDMShutdown::accept()
+{
+ if (le_start->text() == "0" || le_start->text() == "now")
+ sch_st = time( 0 );
+ else if (le_start->text()[0] == '+')
+ sch_st = time( 0 ) + le_start->text().toInt();
+ else if ((sch_st = get_date( le_start->text().latin1() )) < 0) {
+ MsgBox( errorbox, i18n("Entered start date is invalid.") );
+ le_start->setFocus();
+ return;
+ }
+ if (le_timeout->text() == "-1" || le_timeout->text().startsWith( "inf" ))
+ sch_to = TO_INF;
+ else if (le_timeout->text()[0] == '+')
+ sch_to = sch_st + le_timeout->text().toInt();
+ else if ((sch_to = get_date( le_timeout->text().latin1() )) < 0) {
+ MsgBox( errorbox, i18n("Entered timeout date is invalid.") );
+ le_timeout->setFocus();
+ return;
+ }
+
+ inherited::accept();
+}
+
+void
+TDMShutdown::slotTargetChanged()
+{
+ restart_rb->setChecked( true );
+}
+
+void
+TDMShutdown::slotWhenChanged()
+{
+ doesNuke = cb_force->isChecked();
+ updateNeedRoot();
+}
+
+void
+TDMShutdown::accepted()
+{
+ GSet( 1 );
+ GSendInt( G_Shutdown );
+ GSendInt( restart_rb->isChecked() ? SHUT_REBOOT : SHUT_HALT );
+ GSendInt( sch_st );
+ GSendInt( sch_to );
+ GSendInt( cb_force->isChecked() ? SHUT_FORCE : SHUT_CANCEL );
+ GSendInt( _allowShutdown == SHUT_ROOT ? 0 : -2 );
+ GSendStr( (restart_rb->isChecked() &&
+ targets && targets->currentItem() != oldTarget) ?
+ targets->currentText().local8Bit().data() : 0 );
+ GSet( 0 );
+ inherited::accepted();
+}
+
+void
+TDMShutdown::scheduleShutdown( TQWidget *_parent )
+{
+ GSet( 1 );
+ GSendInt( G_QueryShutdown );
+ int how = GRecvInt();
+ int start = GRecvInt();
+ int timeout = GRecvInt();
+ int force = GRecvInt();
+ int uid = GRecvInt();
+ char *os = GRecvStr();
+ GSet( 0 );
+ if (how) {
+ int ret =
+ TDMCancelShutdown( how, start, timeout, force, uid, os,
+ _parent ).exec();
+ if (!ret)
+ return;
+ doShutdown( 0, 0 );
+ uid = ret == Authed ? 0 : -1;
+ } else
+ uid = -1;
+ if (os)
+ free( os );
+ TDMShutdown( uid, _parent ).exec();
+}
+
+
+TDMRadioButton::TDMRadioButton( const TQString &label, TQWidget *parent )
+ : inherited( label, parent )
+{
+}
+
+void
+TDMRadioButton::mouseDoubleClickEvent( TQMouseEvent * )
+{
+ emit doubleClicked();
+}
+
+
+TDMDelayedPushButton::TDMDelayedPushButton( const KGuiItem &item,
+ TQWidget *parent,
+ const char *name )
+ : inherited( item, parent, name )
+ , pop( 0 )
+{
+ connect( this, TQT_SIGNAL(pressed()), TQT_SLOT(slotPressed()) );
+ connect( this, TQT_SIGNAL(released()), TQT_SLOT(slotReleased()) );
+ connect( &popt, TQT_SIGNAL(timeout()), TQT_SLOT(slotTimeout()) );
+}
+
+void TDMDelayedPushButton::setPopup( TQPopupMenu *p )
+{
+ pop = p;
+ setIsMenuButton( p != 0 );
+}
+
+void TDMDelayedPushButton::slotPressed()
+{
+ if (pop)
+ popt.start( TQApplication::startDragTime() );
+}
+
+void TDMDelayedPushButton::slotReleased()
+{
+ popt.stop();
+}
+
+void TDMDelayedPushButton::slotTimeout()
+{
+ popt.stop();
+ pop->popup( mapToGlobal( rect().bottomLeft() ) );
+ setDown( false );
+}
+
+TDMSlimShutdown::TDMSlimShutdown( TQWidget *_parent )
+ : inherited( _parent )
+ , targetList( 0 )
+{
+ setCaption(i18n("Shutdown TDE"));
+
+ bool doUbuntuLogout = KConfigGroup(KGlobal::config(), "Shutdown").readBoolEntry("doUbuntuLogout", false);
+
+ TQFrame* lfrm = new TQFrame( this );
+ TQHBoxLayout* hbuttonbox;
+
+ if(doUbuntuLogout)
+ {
+ TQVBoxLayout* vbox = new TQVBoxLayout( this );
+ if (has_twin)
+ lfrm->setFrameStyle( TQFrame::NoFrame );
+ else
+ lfrm->setFrameStyle( TQFrame::StyledPanel | TQFrame::Raised );
+ lfrm->setLineWidth( style().pixelMetric( TQStyle::PM_DefaultFrameWidth, lfrm ) );
+ // we need to set the minimum size for the logout box, since it
+ // gets too small if there all options are not available
+ lfrm->setMinimumSize(300,120);
+ vbox->addWidget( lfrm );
+ vbox = new TQVBoxLayout( lfrm, 2 * KDialog::marginHint(),
+ 2 * KDialog::spacingHint() );
+
+ // first line of buttons
+ hbuttonbox = new TQHBoxLayout( vbox, 8 * KDialog::spacingHint() );
+ hbuttonbox->setAlignment( Qt::AlignHCenter );
+
+ // Reboot
+ FlatButton* btnReboot = new FlatButton( lfrm );
+ btnReboot->setTextLabel( i18n("&Restart"), false );
+ btnReboot->setPixmap( DesktopIcon( "reload") );
+ int i = btnReboot->textLabel().find( TQRegExp("\\&"), 0 ); // i == 1
+ btnReboot->setAccel( "ALT+" + btnReboot->textLabel().lower()[i+1] ) ;
+ hbuttonbox->addWidget ( btnReboot);
+ connect(btnReboot, TQT_SIGNAL(clicked()), TQT_SLOT(slotReboot()));
+
+ // Copied completely from the standard restart/shutdown dialog
+ GSet( 1 );
+ GSendInt( G_ListBootOpts );
+ if (GRecvInt() == BO_OK) {
+ targetList = GRecvStrArr( 0 );
+ /*int def =*/ GRecvInt();
+ int cur = GRecvInt();
+ TQPopupMenu *targets = new TQPopupMenu( this );
+ btnReboot->setPopupDelay(300); // visually add dropdown
+ for (int i = 0; targetList[i]; i++) {
+ TQString t( TQString::fromLocal8Bit( targetList[i] ) );
+ targets->insertItem( i == cur ?
+ i18n("current option in boot loader",
+ "%1 (current)").arg( t ) :
+ t, i );
+ }
+ btnReboot->setPopup( targets );</