mirror of
https://github.com/beard7n/bsdports.git
synced 2026-04-10 10:31:20 +02:00
939 lines
29 KiB
Plaintext
939 lines
29 KiB
Plaintext
--- const.h.orig 2014-08-12 18:08:28.000000000 +0200
|
|
+++ const.h 2014-08-12 18:09:20.000000000 +0200
|
|
@@ -24,9 +24,6 @@
|
|
#define HIDE 0
|
|
#define SHOW 1
|
|
|
|
-#define GET_NAME 0
|
|
-#define GET_PASSWD 1
|
|
-
|
|
#define OK_EXIT 0
|
|
#define ERR_EXIT 1
|
|
|
|
--- main.cpp.orig 2014-08-12 18:08:28.000000000 +0200
|
|
+++ main.cpp 2014-08-12 18:09:20.000000000 +0200
|
|
@@ -16,6 +16,8 @@
|
|
|
|
int main(int argc, char** argv)
|
|
{
|
|
+ // We need to set the locale to get the input encoded in UTF-8
|
|
+ setlocale (LC_ALL, "");
|
|
LoginApp = new App(argc, argv);
|
|
LoginApp->Run();
|
|
return 0;
|
|
--- panel.cpp.orig 2014-08-12 18:08:28.000000000 +0200
|
|
+++ panel.cpp 2014-08-12 18:09:20.000000000 +0200
|
|
@@ -13,6 +13,7 @@
|
|
#include <poll.h>
|
|
#include <X11/extensions/Xrandr.h>
|
|
#include "panel.h"
|
|
+#include "util.h"
|
|
|
|
using namespace std;
|
|
|
|
@@ -78,6 +79,15 @@
|
|
XftColorAllocName(Dpy, visual, colormap,
|
|
cfg->getOption("session_shadow_color").c_str(), &sessionshadowcolor);
|
|
|
|
+ /* Build XIC and XIM to be able to get unicode string from keyboard events */
|
|
+ char classname = 0;
|
|
+ displayIc = NULL;
|
|
+ displayIm = XOpenIM(Dpy, NULL, &classname, &classname);
|
|
+ if(displayIm) {
|
|
+ displayIc = XCreateIC(displayIm, XNInputStyle, XIMPreeditNothing | XIMStatusNothing,
|
|
+ XNResourceName, &classname,
|
|
+ XNResourceClass, &classname, NULL);
|
|
+ }
|
|
/* Load properties from config / theme */
|
|
input_name_x = cfg->getIntOption("input_name_x");
|
|
input_name_y = cfg->getIntOption("input_name_y");
|
|
@@ -91,6 +101,8 @@
|
|
input_pass_y = input_name_y;
|
|
}
|
|
|
|
+ Reset();
|
|
+
|
|
/* Load panel and background image */
|
|
string panelpng = "";
|
|
panelpng = panelpng + themedir +"/panel.png";
|
|
@@ -210,6 +222,12 @@
|
|
Visual* visual = DefaultVisual(Dpy, Scr);
|
|
Colormap colormap = DefaultColormap(Dpy, Scr);
|
|
|
|
+ if(displayIc) {
|
|
+ XDestroyIC(displayIc);
|
|
+ }
|
|
+ if(displayIm) {
|
|
+ XCloseIM(displayIm);
|
|
+ }
|
|
XftColorFree(Dpy, visual, colormap, &inputcolor);
|
|
XftColorFree(Dpy, visual, colormap, &inputshadowcolor);
|
|
XftColorFree(Dpy, visual, colormap, &welcomecolor);
|
|
@@ -289,7 +307,8 @@
|
|
|
|
XftDraw *draw = XftDrawCreate(Dpy, Win,
|
|
DefaultVisual(Dpy, Scr), DefaultColormap(Dpy, Scr));
|
|
- XftTextExtents8(Dpy, msgfont, reinterpret_cast<const XftChar8*>(message.c_str()),
|
|
+
|
|
+ XftTextExtentsUtf8(Dpy, msgfont, reinterpret_cast<const XftChar8*>(message.c_str()),
|
|
message.length(), &extents);
|
|
|
|
string cfgX = cfg->getOption("passwd_feedback_x");
|
|
@@ -300,7 +319,7 @@
|
|
int msg_y = Cfg::absolutepos(cfgY, XHeightOfScreen(ScreenOfDisplay(Dpy, Scr)), extents.height);
|
|
|
|
OnExpose();
|
|
- SlimDrawString8(draw, &msgcolor, msgfont, msg_x, msg_y, message,
|
|
+ SlimDrawStringUtf8(draw, &msgcolor, msgfont, msg_x, msg_y, message,
|
|
&msgshadowcolor, shadowXOffset, shadowYOffset);
|
|
|
|
if (cfg->getOption("bell") == "1")
|
|
@@ -312,7 +331,7 @@
|
|
OnExpose();
|
|
// The message should stay on the screen even after the password field is
|
|
// cleared, methinks. I don't like this solution, but it works.
|
|
- SlimDrawString8(draw, &msgcolor, msgfont, msg_x, msg_y, message,
|
|
+ SlimDrawStringUtf8(draw, &msgcolor, msgfont, msg_x, msg_y, message,
|
|
&msgshadowcolor, shadowXOffset, shadowYOffset);
|
|
XSync(Dpy, True);
|
|
XftDrawDestroy(draw);
|
|
@@ -330,9 +349,8 @@
|
|
draw = XftDrawCreate(Dpy, Root,
|
|
DefaultVisual(Dpy, Scr), DefaultColormap(Dpy, Scr));
|
|
|
|
- XftTextExtents8(Dpy, msgfont,
|
|
- reinterpret_cast<const XftChar8*>(text.c_str()),
|
|
- text.length(), &extents);
|
|
+ XftTextExtentsUtf8(Dpy, msgfont,
|
|
+ reinterpret_cast<const XftChar8*>(text.c_str()), text.length(), &extents);
|
|
cfgX = cfg->getOption("msg_x");
|
|
cfgY = cfg->getOption("msg_y");
|
|
int shadowXOffset = cfg->getIntOption("msg_shadow_xoffset");
|
|
@@ -347,9 +365,8 @@
|
|
msg_y = Cfg::absolutepos(cfgY, XHeightOfScreen(ScreenOfDisplay(Dpy, Scr)), extents.height);
|
|
}
|
|
|
|
- SlimDrawString8 (draw, &msgcolor, msgfont, msg_x, msg_y,
|
|
- text,
|
|
- &msgshadowcolor,
|
|
+ SlimDrawStringUtf8(draw, &msgcolor, msgfont, msg_x, msg_y,
|
|
+ text, &msgshadowcolor,
|
|
shadowXOffset, shadowYOffset);
|
|
XFlush(Dpy);
|
|
XftDrawDestroy(draw);
|
|
@@ -383,24 +400,27 @@
|
|
}
|
|
|
|
void Panel::Cursor(int visible) {
|
|
- const char* text = NULL;
|
|
- int xx = 0, yy = 0, y2 = 0, cheight = 0;
|
|
+ const uint16_t* text = NULL;
|
|
+ int xx = 0, yy = 0, y2 = 0, cheight = 0, textLen = 0;
|
|
const char* txth = "Wj"; /* used to get cursor height */
|
|
|
|
if (mode == Mode_Lock) {
|
|
- text = HiddenPasswdBuffer.c_str();
|
|
+ text = hiddenPasswdBuffer;
|
|
+ textLen = passwdBufferLen;
|
|
xx = input_pass_x;
|
|
yy = input_pass_y;
|
|
} else {
|
|
switch(field) {
|
|
case Get_Passwd:
|
|
- text = HiddenPasswdBuffer.c_str();
|
|
+ text = hiddenPasswdBuffer;
|
|
+ textLen = passwdBufferLen;
|
|
xx = input_pass_x;
|
|
yy = input_pass_y;
|
|
break;
|
|
|
|
case Get_Name:
|
|
- text = NameBuffer.c_str();
|
|
+ text = nameBuffer;
|
|
+ textLen = nameBufferLen;
|
|
xx = input_name_x;
|
|
yy = input_name_y;
|
|
break;
|
|
@@ -411,7 +431,7 @@
|
|
XftTextExtents8(Dpy, font, (XftChar8*)txth, strlen(txth), &extents);
|
|
cheight = extents.height;
|
|
y2 = yy - extents.y + extents.height;
|
|
- XftTextExtents8(Dpy, font, (XftChar8*)text, strlen(text), &extents);
|
|
+ XftTextExtents16(Dpy, font, (XftChar16*)text, textLen, &extents);
|
|
xx += extents.width;
|
|
|
|
if(visible == SHOW) {
|
|
@@ -478,27 +498,25 @@
|
|
XClearWindow(Dpy, Win);
|
|
|
|
if (input_pass_x != input_name_x || input_pass_y != input_name_y){
|
|
- SlimDrawString8 (draw, &inputcolor, font, input_name_x, input_name_y,
|
|
- NameBuffer,
|
|
- &inputshadowcolor,
|
|
+ SlimDrawString16(draw, &inputcolor, font, input_name_x, input_name_y,
|
|
+ nameBuffer, nameBufferLen, &inputshadowcolor,
|
|
inputShadowXOffset, inputShadowYOffset);
|
|
- SlimDrawString8 (draw, &inputcolor, font, input_pass_x, input_pass_y,
|
|
- HiddenPasswdBuffer,
|
|
- &inputshadowcolor,
|
|
+ SlimDrawString16(draw, &inputcolor, font, input_pass_x, input_pass_y,
|
|
+ hiddenPasswdBuffer, passwdBufferLen, &inputshadowcolor,
|
|
inputShadowXOffset, inputShadowYOffset);
|
|
} else { /*single input mode */
|
|
switch(field) {
|
|
case Get_Passwd:
|
|
- SlimDrawString8 (draw, &inputcolor, font,
|
|
+ SlimDrawString16(draw, &inputcolor, font,
|
|
input_pass_x, input_pass_y,
|
|
- HiddenPasswdBuffer,
|
|
+ hiddenPasswdBuffer, passwdBufferLen,
|
|
&inputshadowcolor,
|
|
inputShadowXOffset, inputShadowYOffset);
|
|
break;
|
|
case Get_Name:
|
|
- SlimDrawString8 (draw, &inputcolor, font,
|
|
+ SlimDrawString16(draw, &inputcolor, font,
|
|
input_name_x, input_name_y,
|
|
- NameBuffer,
|
|
+ nameBuffer, nameBufferLen,
|
|
&inputshadowcolor,
|
|
inputShadowXOffset, inputShadowYOffset);
|
|
break;
|
|
@@ -510,35 +528,105 @@
|
|
ShowText();
|
|
}
|
|
|
|
-void Panel::EraseLastChar(string &formerString) {
|
|
+int Panel::FieldEraseLastChar(const uint16_t **buf, int *len) {
|
|
+
|
|
+ static const uint16_t emptyBuf = 0;
|
|
+ int formerTextBufferLen = 0;
|
|
+
|
|
switch(field) {
|
|
- case GET_NAME:
|
|
- if (! NameBuffer.empty()) {
|
|
- formerString=NameBuffer;
|
|
- NameBuffer.erase(--NameBuffer.end());
|
|
+ case Get_Name:
|
|
+ formerTextBufferLen = nameBufferLen;
|
|
+ if (nameBufferLen > 0) {
|
|
+ nameBufferLen--;
|
|
}
|
|
+ *buf = nameBuffer;
|
|
+ *len = nameBufferLen;
|
|
break;
|
|
|
|
- case GET_PASSWD:
|
|
- if (!PasswdBuffer.empty()) {
|
|
- formerString=HiddenPasswdBuffer;
|
|
- PasswdBuffer.erase(--PasswdBuffer.end());
|
|
- HiddenPasswdBuffer.erase(--HiddenPasswdBuffer.end());
|
|
+ case Get_Passwd:
|
|
+ formerTextBufferLen = passwdBufferLen;
|
|
+ if (passwdBufferLen > 0) {
|
|
+ passwdBufferLen--;
|
|
+ passwdBuffer[passwdBufferLen] = 0;
|
|
}
|
|
+ *buf = hiddenPasswdBuffer;
|
|
+ *len = passwdBufferLen;
|
|
+ break;
|
|
+
|
|
+ default:
|
|
+ *buf = &emptyBuf;
|
|
+ *len = 0;
|
|
break;
|
|
}
|
|
+ return formerTextBufferLen;
|
|
}
|
|
|
|
+int Panel::FieldClear(const uint16_t **buf, int *len) {
|
|
+
|
|
+ static const uint16_t emptyBuf = 0;
|
|
+ int formerTextBufferLen = 0;
|
|
+
|
|
+ switch(field) {
|
|
+ case Get_Name:
|
|
+ formerTextBufferLen = nameBufferLen;
|
|
+ nameBufferLen = 0;
|
|
+ *buf = nameBuffer;
|
|
+ *len = nameBufferLen;
|
|
+ break;
|
|
+
|
|
+ case Get_Passwd:
|
|
+ formerTextBufferLen = passwdBufferLen;
|
|
+ memset(passwdBuffer, 0, sizeof(passwdBuffer));
|
|
+ passwdBufferLen = 0;
|
|
+ *buf = hiddenPasswdBuffer;
|
|
+ *len = passwdBufferLen;
|
|
+ break;
|
|
+
|
|
+ default:
|
|
+ *buf = &emptyBuf;
|
|
+ *len = 0;
|
|
+ break;
|
|
+ }
|
|
+ return formerTextBufferLen;
|
|
+}
|
|
+
|
|
+/* Check if the input character is allowed */
|
|
+bool Panel::isUtf16CharAllowed(uint16_t c) {
|
|
+ return ((0x020 <= c && c <= 0x07E) || (0x0A0 <= c && c != 0x0AD));
|
|
+}
|
|
+
|
|
+#define SIZE_BUFFER_KEY_PRESS 64
|
|
+
|
|
bool Panel::OnKeyPress(XEvent& event) {
|
|
- char ascii;
|
|
+ int formerTextBufferLen = -1;
|
|
+ int textBufferLen = -1;
|
|
+ const uint16_t *textBuffer = NULL;
|
|
KeySym keysym;
|
|
+ int nbReadBuf = -1;
|
|
+ uint16_t utf16buf[SIZE_BUFFER_KEY_PRESS];
|
|
+ if(displayIc)
|
|
+ {
|
|
+ Status status;
|
|
+ char databuf[SIZE_BUFFER_KEY_PRESS];
|
|
+ nbReadBuf = Xutf8LookupString(displayIc, &event.xkey, databuf,
|
|
+ SIZE_BUFFER_KEY_PRESS, &keysym, &status);
|
|
+ if(nbReadBuf > 0) {
|
|
+ nbReadBuf = Util::utf8ToUtf16(databuf, nbReadBuf,
|
|
+ utf16buf, SIZE_BUFFER_KEY_PRESS);
|
|
+ }
|
|
+ }
|
|
+ else
|
|
+ {
|
|
XComposeStatus compstatus;
|
|
- int xx = 0;
|
|
- int yy = 0;
|
|
- string text;
|
|
- string formerString = "";
|
|
+ char databuf[SIZE_BUFFER_KEY_PRESS];
|
|
+ nbReadBuf = XLookupString(&event.xkey, databuf,
|
|
+ SIZE_BUFFER_KEY_PRESS, &keysym, &compstatus);
|
|
+ if(nbReadBuf > 0) {
|
|
+ nbReadBuf = Util::utf8ToUtf16(databuf, nbReadBuf,
|
|
+ utf16buf, SIZE_BUFFER_KEY_PRESS);
|
|
+ }
|
|
+ }
|
|
|
|
- XLookupString(&event.xkey, &ascii, 1, &keysym, &compstatus);
|
|
switch(keysym){
|
|
case XK_F1:
|
|
SwitchSession();
|
|
@@ -553,17 +641,17 @@
|
|
case XK_KP_Enter:
|
|
if (field==Get_Name){
|
|
/* Don't allow an empty username */
|
|
- if (NameBuffer.empty()) return true;
|
|
+ if (nameBufferLen <= 0) return true;
|
|
|
|
- if (NameBuffer==CONSOLE_STR){
|
|
+ if (Util::utf16EqualToAscii(CONSOLE_STR, nameBuffer, nameBufferLen)) {
|
|
action = Console;
|
|
- } else if (NameBuffer==HALT_STR){
|
|
+ } else if (Util::utf16EqualToAscii(HALT_STR, nameBuffer, nameBufferLen)) {
|
|
action = Halt;
|
|
- } else if (NameBuffer==REBOOT_STR){
|
|
+ } else if (Util::utf16EqualToAscii(REBOOT_STR, nameBuffer, nameBufferLen)) {
|
|
action = Reboot;
|
|
- } else if (NameBuffer==SUSPEND_STR){
|
|
+ } else if (Util::utf16EqualToAscii(SUSPEND_STR, nameBuffer, nameBufferLen)) {
|
|
action = Suspend;
|
|
- } else if (NameBuffer==EXIT_STR){
|
|
+ } else if (Util::utf16EqualToAscii(EXIT_STR, nameBuffer, nameBufferLen)) {
|
|
action = Exit;
|
|
} else{
|
|
if (mode == Mode_DM)
|
|
@@ -581,80 +669,80 @@
|
|
switch(keysym){
|
|
case XK_Delete:
|
|
case XK_BackSpace:
|
|
- EraseLastChar(formerString);
|
|
+ formerTextBufferLen = FieldEraseLastChar(&textBuffer, &textBufferLen);
|
|
break;
|
|
|
|
case XK_w:
|
|
case XK_u:
|
|
if (reinterpret_cast<XKeyEvent&>(event).state & ControlMask) {
|
|
- switch(field) {
|
|
- case Get_Passwd:
|
|
- formerString = HiddenPasswdBuffer;
|
|
- HiddenPasswdBuffer.clear();
|
|
- PasswdBuffer.clear();
|
|
- break;
|
|
- case Get_Name:
|
|
- formerString = NameBuffer;
|
|
- NameBuffer.clear();
|
|
- break;
|
|
- }
|
|
+ formerTextBufferLen = FieldClear(&textBuffer, &textBufferLen);
|
|
break;
|
|
}
|
|
case XK_h:
|
|
if (reinterpret_cast<XKeyEvent&>(event).state & ControlMask) {
|
|
- EraseLastChar(formerString);
|
|
+ formerTextBufferLen = FieldEraseLastChar(&textBuffer, &textBufferLen);
|
|
break;
|
|
}
|
|
/* Deliberate fall-through */
|
|
|
|
default:
|
|
- if (isprint(ascii) && (keysym < XK_Shift_L || keysym > XK_Hyper_R)){
|
|
+ if(nbReadBuf > 0) {
|
|
switch(field) {
|
|
- case GET_NAME:
|
|
- formerString=NameBuffer;
|
|
- if (NameBuffer.length() < INPUT_MAXLENGTH_NAME-1){
|
|
- NameBuffer.append(&ascii,1);
|
|
- };
|
|
+ case Get_Name:
|
|
+ formerTextBufferLen = nameBufferLen;
|
|
+ for(int i = 0; i < nbReadBuf &&
|
|
+ nameBufferLen < INPUT_MAXLENGTH_NAME; i++) {
|
|
+
|
|
+ if(isUtf16CharAllowed(utf16buf[i])) {
|
|
+ nameBuffer[nameBufferLen++] = utf16buf[i];
|
|
+ }
|
|
+ }
|
|
+ textBuffer = nameBuffer;
|
|
+ textBufferLen = nameBufferLen;
|
|
break;
|
|
- case GET_PASSWD:
|
|
- formerString=HiddenPasswdBuffer;
|
|
- if (PasswdBuffer.length() < INPUT_MAXLENGTH_PASSWD-1){
|
|
- PasswdBuffer.append(&ascii,1);
|
|
- HiddenPasswdBuffer.append("*");
|
|
- };
|
|
+
|
|
+ case Get_Passwd:
|
|
+ formerTextBufferLen = passwdBufferLen;
|
|
+ for(int i = 0; i < nbReadBuf &&
|
|
+ passwdBufferLen < INPUT_MAXLENGTH_PASSWD; i++) {
|
|
+
|
|
+ if(isUtf16CharAllowed(utf16buf[i])) {
|
|
+ passwdBuffer[passwdBufferLen] = utf16buf[i];
|
|
+ hiddenPasswdBuffer[passwdBufferLen++] = (uint16_t)'*';
|
|
+ }
|
|
+ }
|
|
+ textBuffer = hiddenPasswdBuffer;
|
|
+ textBufferLen = passwdBufferLen;
|
|
break;
|
|
- };
|
|
- };
|
|
+ }
|
|
+ }
|
|
break;
|
|
};
|
|
|
|
- XGlyphInfo extents;
|
|
- XftDraw *draw = XftDrawCreate(Dpy, Win,
|
|
- DefaultVisual(Dpy, Scr), DefaultColormap(Dpy, Scr));
|
|
+ int xx = 0, yy = 0;
|
|
+ if (formerTextBufferLen > 0 || textBufferLen > 0) {
|
|
|
|
switch(field) {
|
|
case Get_Name:
|
|
- text = NameBuffer;
|
|
xx = input_name_x;
|
|
yy = input_name_y;
|
|
break;
|
|
|
|
case Get_Passwd:
|
|
- text = HiddenPasswdBuffer;
|
|
xx = input_pass_x;
|
|
yy = input_pass_y;
|
|
break;
|
|
}
|
|
+ }
|
|
|
|
- if (!formerString.empty()){
|
|
+ if (formerTextBufferLen > 0) {
|
|
+ XGlyphInfo extents;
|
|
const char* txth = "Wj"; /* get proper maximum height ? */
|
|
XftTextExtents8(Dpy, font,
|
|
reinterpret_cast<const XftChar8*>(txth), strlen(txth), &extents);
|
|
int maxHeight = extents.height;
|
|
|
|
- XftTextExtents8(Dpy, font,
|
|
- reinterpret_cast<const XftChar8*>(formerString.c_str()),
|
|
- formerString.length(), &extents);
|
|
+ XftTextExtents16(Dpy, font, (XftChar16*)textBuffer, formerTextBufferLen, &extents);
|
|
int maxLength = extents.width;
|
|
|
|
if (mode == Mode_Lock)
|
|
@@ -666,14 +754,15 @@
|
|
maxLength + 6, maxHeight + 6, false);
|
|
}
|
|
|
|
- if (!text.empty()) {
|
|
- SlimDrawString8 (draw, &inputcolor, font, xx, yy,
|
|
- text,
|
|
- &inputshadowcolor,
|
|
- inputShadowXOffset, inputShadowYOffset);
|
|
+ if(textBufferLen > 0) {
|
|
+ XftDraw *draw = XftDrawCreate(Dpy, Win, DefaultVisual(Dpy, Scr), DefaultColormap(Dpy, Scr));
|
|
+ if(draw != NULL) {
|
|
+ SlimDrawString16(draw, &inputcolor, font, xx, yy, textBuffer, textBufferLen,
|
|
+ &inputshadowcolor, inputShadowXOffset, inputShadowYOffset);
|
|
+ XftDrawDestroy(draw);
|
|
+ }
|
|
}
|
|
|
|
- XftDrawDestroy (draw);
|
|
Cursor(SHOW);
|
|
return true;
|
|
}
|
|
@@ -690,7 +779,7 @@
|
|
XftDraw *draw = XftDrawCreate(Dpy, Win,
|
|
DefaultVisual(Dpy, Scr), DefaultColormap(Dpy, Scr));
|
|
/* welcome message */
|
|
- XftTextExtents8(Dpy, welcomefont, (XftChar8*)welcome_message.c_str(),
|
|
+ XftTextExtentsUtf8(Dpy, welcomefont, (XftChar8*)welcome_message.c_str(),
|
|
strlen(welcome_message.c_str()), &extents);
|
|
cfgX = cfg->getOption("welcome_x");
|
|
cfgY = cfg->getOption("welcome_y");
|
|
@@ -700,9 +789,8 @@
|
|
welcome_x = Cfg::absolutepos(cfgX, image->Width(), extents.width);
|
|
welcome_y = Cfg::absolutepos(cfgY, image->Height(), extents.height);
|
|
if (welcome_x >= 0 && welcome_y >= 0) {
|
|
- SlimDrawString8 (draw, &welcomecolor, welcomefont,
|
|
- welcome_x, welcome_y,
|
|
- welcome_message,
|
|
+ SlimDrawStringUtf8(draw, &welcomecolor, welcomefont,
|
|
+ welcome_x, welcome_y, welcome_message,
|
|
&welcomeshadowcolor, shadowXOffset, shadowYOffset);
|
|
}
|
|
|
|
@@ -710,7 +798,7 @@
|
|
string msg;
|
|
if ((!singleInputMode|| field == Get_Passwd) && mode == Mode_DM) {
|
|
msg = cfg->getOption("password_msg");
|
|
- XftTextExtents8(Dpy, enterfont, (XftChar8*)msg.c_str(),
|
|
+ XftTextExtentsUtf8(Dpy, enterfont, (XftChar8*)msg.c_str(),
|
|
strlen(msg.c_str()), &extents);
|
|
cfgX = cfg->getOption("password_x");
|
|
cfgY = cfg->getOption("password_y");
|
|
@@ -719,14 +807,14 @@
|
|
password_x = Cfg::absolutepos(cfgX, image->Width(), extents.width);
|
|
password_y = Cfg::absolutepos(cfgY, image->Height(), extents.height);
|
|
if (password_x >= 0 && password_y >= 0){
|
|
- SlimDrawString8 (draw, &entercolor, enterfont, password_x, password_y,
|
|
+ SlimDrawStringUtf8(draw, &entercolor, enterfont, password_x, password_y,
|
|
msg, &entershadowcolor, shadowXOffset, shadowYOffset);
|
|
}
|
|
}
|
|
|
|
if (!singleInputMode|| field == Get_Name) {
|
|
msg = cfg->getOption("username_msg");
|
|
- XftTextExtents8(Dpy, enterfont, (XftChar8*)msg.c_str(),
|
|
+ XftTextExtentsUtf8(Dpy, enterfont, (XftChar8*)msg.c_str(),
|
|
strlen(msg.c_str()), &extents);
|
|
cfgX = cfg->getOption("username_x");
|
|
cfgY = cfg->getOption("username_y");
|
|
@@ -735,7 +823,7 @@
|
|
username_x = Cfg::absolutepos(cfgX, image->Width(), extents.width);
|
|
username_y = Cfg::absolutepos(cfgY, image->Height(), extents.height);
|
|
if (username_x >= 0 && username_y >= 0){
|
|
- SlimDrawString8 (draw, &entercolor, enterfont, username_x, username_y,
|
|
+ SlimDrawStringUtf8(draw, &entercolor, enterfont, username_x, username_y,
|
|
msg, &entershadowcolor, shadowXOffset, shadowYOffset);
|
|
}
|
|
}
|
|
@@ -776,7 +864,7 @@
|
|
|
|
XftDraw *draw = XftDrawCreate(Dpy, Root,
|
|
DefaultVisual(Dpy, Scr), DefaultColormap(Dpy, Scr));
|
|
- XftTextExtents8(Dpy, sessionfont, reinterpret_cast<const XftChar8*>(currsession.c_str()),
|
|
+ XftTextExtentsUtf8(Dpy, sessionfont, reinterpret_cast<const XftChar8*>(currsession.c_str()),
|
|
currsession.length(), &extents);
|
|
msg_x = cfg->getOption("session_x");
|
|
msg_y = cfg->getOption("session_y");
|
|
@@ -785,16 +873,37 @@
|
|
int shadowXOffset = cfg->getIntOption("session_shadow_xoffset");
|
|
int shadowYOffset = cfg->getIntOption("session_shadow_yoffset");
|
|
|
|
- SlimDrawString8(draw, &sessioncolor, sessionfont, x, y,
|
|
- currsession,
|
|
- &sessionshadowcolor,
|
|
- shadowXOffset, shadowYOffset);
|
|
+ SlimDrawStringUtf8(draw, &sessioncolor, sessionfont, x, y,
|
|
+ currsession, &sessionshadowcolor, shadowXOffset, shadowYOffset);
|
|
XFlush(Dpy);
|
|
XftDrawDestroy(draw);
|
|
}
|
|
|
|
+void Panel::SlimDrawString16(XftDraw *d, XftColor *color, XftFont *font,
|
|
+ int x, int y, const uint16_t *str, int strLen,
|
|
+ XftColor* shadowColor, int xOffset, int yOffset)
|
|
+{
|
|
+ int calc_x = 0;
|
|
+ int calc_y = 0;
|
|
+ if (mode == Mode_Lock) {
|
|
+ calc_x = viewport.x;
|
|
+ calc_y = viewport.y;
|
|
+ }
|
|
+
|
|
+ if (xOffset && yOffset) {
|
|
+ XftDrawString16(d, shadowColor, font,
|
|
+ x + xOffset + calc_x,
|
|
+ y + yOffset + calc_y,
|
|
+ (XftChar16*)str, strLen);
|
|
+ }
|
|
+
|
|
+ XftDrawString16(d, color, font,
|
|
+ x + calc_x,
|
|
+ y + calc_y,
|
|
+ (XftChar16*)str, strLen);
|
|
+}
|
|
|
|
-void Panel::SlimDrawString8(XftDraw *d, XftColor *color, XftFont *font,
|
|
+void Panel::SlimDrawStringUtf8(XftDraw *d, XftColor *color, XftFont *font,
|
|
int x, int y, const string& str,
|
|
XftColor* shadowColor,
|
|
int xOffset, int yOffset)
|
|
@@ -831,28 +940,31 @@
|
|
}
|
|
|
|
void Panel::ResetName(void){
|
|
- NameBuffer.clear();
|
|
+ nameBufferLen = 0;
|
|
+ memset(nameBuffer, 0, sizeof(nameBuffer));
|
|
}
|
|
|
|
void Panel::ResetPasswd(void){
|
|
- PasswdBuffer.clear();
|
|
- HiddenPasswdBuffer.clear();
|
|
+ passwdBufferLen = 0;
|
|
+ memset(passwdBuffer, 0, sizeof(passwdBuffer));
|
|
+ memset(hiddenPasswdBuffer, 0, sizeof(hiddenPasswdBuffer));
|
|
}
|
|
|
|
void Panel::SetName(const string& name){
|
|
- NameBuffer=name;
|
|
+ nameBufferLen = Util::utf8ToUtf16(name.c_str(), name.length(),
|
|
+ nameBuffer, INPUT_MAXLENGTH_NAME);
|
|
if (mode == Mode_DM)
|
|
action = Login;
|
|
else
|
|
action = Lock;
|
|
}
|
|
|
|
-const string& Panel::GetName(void) const{
|
|
- return NameBuffer;
|
|
+const string Panel::GetName(void) const{
|
|
+ return Util::utf16BufToUtf8String(nameBuffer, nameBufferLen);
|
|
}
|
|
|
|
-const string& Panel::GetPasswd(void) const{
|
|
- return PasswdBuffer;
|
|
+const string Panel::GetPasswd(void) const{
|
|
+ return Util::utf16BufToUtf8String(passwdBuffer, passwdBufferLen);
|
|
}
|
|
|
|
Rectangle Panel::GetPrimaryViewport() {
|
|
--- panel.h.orig 2014-08-12 18:08:28.000000000 +0200
|
|
+++ panel.h 2014-08-12 18:09:20.000000000 +0200
|
|
@@ -20,6 +20,7 @@
|
|
#include <X11/Xmu/WinUtil.h>
|
|
#include <sys/wait.h>
|
|
#include <stdlib.h>
|
|
+#include <stdint.h>
|
|
#include <signal.h>
|
|
#include <iostream>
|
|
#include <string>
|
|
@@ -86,20 +87,26 @@
|
|
void ResetName(void);
|
|
void ResetPasswd(void);
|
|
void SetName(const std::string &name);
|
|
- const std::string& GetName(void) const;
|
|
- const std::string& GetPasswd(void) const;
|
|
+ const std::string GetName(void) const;
|
|
+ const std::string GetPasswd(void) const;
|
|
void SwitchSession();
|
|
private:
|
|
Panel();
|
|
void Cursor(int visible);
|
|
unsigned long GetColor(const char *colorname);
|
|
void OnExpose(void);
|
|
- void EraseLastChar(string &formerString);
|
|
+ int FieldEraseLastChar(const uint16_t **buf, int *len);
|
|
+ int FieldClear(const uint16_t **buf, int *len);
|
|
bool OnKeyPress(XEvent& event);
|
|
void ShowText();
|
|
void ShowSession();
|
|
|
|
- void SlimDrawString8(XftDraw *d, XftColor *color, XftFont *font,
|
|
+ static bool isUtf16CharAllowed(uint16_t c);
|
|
+ void SlimDrawString16(XftDraw *d, XftColor *color, XftFont *font,
|
|
+ int x, int y, const uint16_t *str, int strLen,
|
|
+ XftColor* shadowColor, int xOffset, int yOffset);
|
|
+
|
|
+ void SlimDrawStringUtf8(XftDraw *d, XftColor *color, XftFont *font,
|
|
int x, int y, const std::string &str,
|
|
XftColor *shadowColor,
|
|
int xOffset, int yOffset);
|
|
@@ -136,12 +143,16 @@
|
|
XftColor entershadowcolor;
|
|
ActionType action;
|
|
FieldType field;
|
|
+ XIM displayIm;
|
|
+ XIC displayIc;
|
|
//Pixmap background;
|
|
|
|
/* Username/Password */
|
|
- std::string NameBuffer;
|
|
- std::string PasswdBuffer;
|
|
- std::string HiddenPasswdBuffer;
|
|
+ uint16_t nameBuffer[INPUT_MAXLENGTH_NAME + 1];
|
|
+ int nameBufferLen;
|
|
+ uint16_t passwdBuffer[INPUT_MAXLENGTH_PASSWD + 1];
|
|
+ int passwdBufferLen;
|
|
+ uint16_t hiddenPasswdBuffer[INPUT_MAXLENGTH_PASSWD + 1];
|
|
|
|
/* screen stuff */
|
|
Rectangle viewport;
|
|
--- slimlock.cpp.orig 2014-08-12 18:08:28.000000000 +0200
|
|
+++ slimlock.cpp 2014-08-12 18:09:24.000000000 +0200
|
|
@@ -48,19 +48,19 @@
|
|
void *RaiseWindow(void *data);
|
|
|
|
// I really didn't wanna put these globals here, but it's the only way...
|
|
-Display* dpy;
|
|
-int scr;
|
|
-Window win;
|
|
-Cfg* cfg;
|
|
-Panel* loginPanel;
|
|
-string themeName = "";
|
|
-
|
|
-pam_handle_t *pam_handle;
|
|
-struct pam_conv conv = {ConvCallback, NULL};
|
|
-
|
|
-CARD16 dpms_standby, dpms_suspend, dpms_off, dpms_level;
|
|
-BOOL dpms_state, using_dpms;
|
|
-int term;
|
|
+static Display* dpy;
|
|
+static int scr;
|
|
+static Window win;
|
|
+static Cfg* cfg;
|
|
+static Panel* loginPanel;
|
|
+static string themeName = "";
|
|
+
|
|
+static pam_handle_t *pam_handle;
|
|
+static struct pam_conv conv = {ConvCallback, NULL};
|
|
+
|
|
+static CARD16 dpms_standby, dpms_suspend, dpms_off, dpms_level;
|
|
+static BOOL dpms_state, using_dpms;
|
|
+static int term;
|
|
|
|
static void
|
|
die(const char *errstr, ...) {
|
|
@@ -73,6 +73,10 @@
|
|
}
|
|
|
|
int main(int argc, char **argv) {
|
|
+
|
|
+ // We need to set the locale to get the input encoded in UTF-8
|
|
+ setlocale (LC_ALL, "");
|
|
+
|
|
if((argc == 2) && !strcmp("-v", argv[1]))
|
|
die(APPNAME"-"VERSION", © 2010-2012 Joel Burget\n");
|
|
else if(argc != 1)
|
|
--- switchuser.h.orig 2014-08-12 18:08:28.000000000 +0200
|
|
+++ switchuser.h 2014-08-12 18:09:20.000000000 +0200
|
|
@@ -32,8 +32,6 @@
|
|
void Login(const char* cmd, const char* mcookie);
|
|
|
|
private:
|
|
- SwitchUser();
|
|
- void SetEnvironment();
|
|
void SetUserId();
|
|
void Execute(const char* cmd);
|
|
void SetClientAuth(const char* mcookie);
|
|
--- util.cpp.orig 2014-08-12 18:08:28.000000000 +0200
|
|
+++ util.cpp 2014-08-12 18:09:20.000000000 +0200
|
|
@@ -67,3 +67,162 @@
|
|
|
|
return pid + tm + (ts.tv_sec ^ ts.tv_nsec);
|
|
}
|
|
+
|
|
+/* Given a UTF-8 encoded string pointed to by utf8 of length length in
|
|
+bytes, returns the corresponding UTF-16 encoded string in the
|
|
+buffer pointed to by utf16. The maximum number of UTF-16 encoding
|
|
+units (i.e., Unit16s) allowed in the buffer is specified in
|
|
+utf16_max_length. The return value is the number of UTF-16
|
|
+encoding units placed in the output buffer pointed to by utf16.
|
|
+
|
|
+In case of an error, -1 is returned, leaving some unusable partial
|
|
+results in the output buffer.
|
|
+
|
|
+The caller must estimate the size of utf16 buffer by itself before
|
|
+calling this function. Insufficient output buffer is considered as
|
|
+an error, and once an error occured, this function doesn't give any
|
|
+clue how large the result will be.
|
|
+
|
|
+The error cases include following:
|
|
+
|
|
+- Invalid byte sequences were in the input UTF-8 bytes. The caller
|
|
+ has no way to know what point in the input buffer was the
|
|
+ errornous byte.
|
|
+
|
|
+- The input contained a character (a valid UTF-8 byte sequence)
|
|
+ whose scalar value exceeded the range that UTF-16 can represent
|
|
+ (i.e., characters whose Unicode scalar value above 0x110000).
|
|
+
|
|
+- The output buffer has no enough space to hold entire utf16 data.
|
|
+
|
|
+Please note:
|
|
+
|
|
+- '\0'-termination is not assumed both on the input UTF-8 string
|
|
+ and on the output UTF-16 string; any legal zero byte in the input
|
|
+ UTF-8 string will be converted to a 16-bit zero in output. As a
|
|
+ side effect, the last UTF-16 encoding unit stored in the output
|
|
+ buffer will have a non-zero value if the input UTF-8 was not
|
|
+ '\0'-terminated.
|
|
+
|
|
+- UTF-8 aliases are *not* considered as an error. They are
|
|
+ converted to UTF-16. For example, 0xC0 0xA0, 0xE0 0x80 0xA0,
|
|
+ and 0xF0 0x80 0x80 0xA0 are all mapped to a single UTF-16
|
|
+ encoding unit 0x0020.
|
|
+
|
|
+- Three byte UTF-8 sequences whose value corresponds to a surrogate
|
|
+ code or other reserved scalar value are not considered as an
|
|
+ error either. They may cause an invalid UTF-16 data (e.g., those
|
|
+ containing unpaired surrogates).
|
|
+
|
|
+*/
|
|
+int Util::utf8ToUtf16(const char *buf, const int utf8_length, uint16_t *utf16, const int utf16_max_length) {
|
|
+
|
|
+ /* p moves over the output buffer. max_ptr points to the next to the last slot of the buffer. */
|
|
+ uint16_t *p = utf16;
|
|
+ const uint16_t *max_ptr = utf16 + utf16_max_length;
|
|
+ const unsigned char *utf8 = (const unsigned char *)buf;
|
|
+
|
|
+ /* end_of_input points to the last byte of input as opposed to the next to the last byte. */
|
|
+ unsigned char const *const end_of_input = utf8 + utf8_length - 1;
|
|
+
|
|
+ while (utf8 <= end_of_input) {
|
|
+ const unsigned char c = *utf8;
|
|
+ if (p >= max_ptr) {
|
|
+ /* No more output space. */
|
|
+ return -1;
|
|
+ }
|
|
+ if (c < 0x80) {
|
|
+ /* One byte ASCII. */
|
|
+ *p++ = c;
|
|
+ utf8 += 1;
|
|
+ } else if (c < 0xC0) {
|
|
+ /* Follower byte without preceeding leader bytes. */
|
|
+ return -1;
|
|
+ } else if (c < 0xE0) {
|
|
+ /* Two byte sequence. We need one follower byte. */
|
|
+ if (end_of_input - utf8 < 1 || (((utf8[1] ^ 0x80)) & 0xC0)) {
|
|
+ return -1;
|
|
+ }
|
|
+ *p++ = (uint16_t)(0xCF80 + (c << 6) + utf8[1]);
|
|
+ utf8 += 2;
|
|
+ } else if (c < 0xF0) {
|
|
+ /* Three byte sequence. We need two follower byte. */
|
|
+ if (end_of_input - utf8 < 2 || (((utf8[1] ^ 0x80) | (utf8[2] ^ 0x80)) & 0xC0)) {
|
|
+ return -1;
|
|
+ }
|
|
+ *p++ = (uint16_t)(0xDF80 + (c << 12) + (utf8[1] << 6) + utf8[2]);
|
|
+ utf8 += 3;
|
|
+ } else if (c < 0xF8) {
|
|
+ int plane;
|
|
+ /* Four byte sequence. We need three follower bytes. */
|
|
+ if (end_of_input - utf8 < 3 || (((utf8[1] ^ 0x80) | (utf8[2] ^0x80) | (utf8[3] ^ 0x80)) & 0xC0)) {
|
|
+ return -1;
|
|
+ }
|
|
+ plane = (-0xC8 + (c << 2) + (utf8[1] >> 4));
|
|
+ if (plane == 0) {
|
|
+ /* This four byte sequence is an alias that
|
|
+ corresponds to a Unicode scalar value in BMP.
|
|
+ It fits in an UTF-16 encoding unit. */
|
|
+ *p++ = (uint16_t)(0xDF80 + (utf8[1] << 12) + (utf8[2] << 6) + utf8[3]);
|
|
+ } else if (plane <= 16) {
|
|
+ /* This is a legal four byte sequence that corresponds to a surrogate pair. */
|
|
+ if (p + 1 >= max_ptr) {
|
|
+ /* No enough space on the output buffer for the pair. */
|
|
+ return -1;
|
|
+ }
|
|
+ *p++ = (uint16_t)(0xE5B8 + (c << 8) + (utf8[1] << 2) + (utf8[2] >> 4));
|
|
+ *p++ = (uint16_t)(0xDB80 + ((utf8[2] & 0x0F) << 6) + utf8[3]);
|
|
+ } else {
|
|
+ /* This four byte sequence is out of UTF-16 code space. */
|
|
+ return -1;
|
|
+ }
|
|
+ utf8 += 4;
|
|
+ } else {
|
|
+ /* Longer sequence or unused byte. */
|
|
+ return -1;
|
|
+ }
|
|
+ }
|
|
+ return p - utf16;
|
|
+}
|
|
+
|
|
+/* Compare an ASCII string with an UTF-16 string */
|
|
+bool Util::utf16EqualToAscii(const char *ascii, uint16_t *utf16, int utf16Len) {
|
|
+
|
|
+ while(*ascii != 0 && utf16Len > 0) {
|
|
+ if(*utf16++ != (uint16_t)*ascii++) {
|
|
+ return false;
|
|
+ }
|
|
+ utf16Len--;
|
|
+ }
|
|
+ return *ascii == 0 && utf16Len == 0;
|
|
+}
|
|
+
|
|
+std::string Util::utf16BufToUtf8String(const uint16_t *utf16Buf, int utf16Len) {
|
|
+
|
|
+ std::string outStr;
|
|
+ outStr.reserve(utf16Len * 2);
|
|
+
|
|
+ while(*utf16Buf != 0 && utf16Len > 0) {
|
|
+
|
|
+ const uint16_t c16 = *utf16Buf++;
|
|
+ if (c16 <= 0x007F) {
|
|
+ outStr.push_back((char)c16);
|
|
+ }
|
|
+ else if (c16 <= 0x07FF) {
|
|
+ unsigned char c = 0xC0 | ((unsigned char)(c16 >> 6));
|
|
+ outStr.push_back(c);
|
|
+ c = 0x80 | ((unsigned char)(c16 & 0x003F));
|
|
+ outStr.push_back(c);
|
|
+ }
|
|
+ else {
|
|
+ unsigned char c = 0xE0 | ((unsigned char)(c16 >> 12));
|
|
+ outStr.push_back(c);
|
|
+ c = 0x80 | ((unsigned char)((c16 >> 6) & 0x003F));
|
|
+ outStr.push_back(c);
|
|
+ c = 0x80 | ((unsigned char)(c16 & 0x003F));
|
|
+ outStr.push_back(c);
|
|
+ }
|
|
+ utf16Len--;
|
|
+ }
|
|
+ return outStr;
|
|
+}
|
|
--- util.h.orig 2014-08-12 18:08:28.000000000 +0200
|
|
+++ util.h 2014-08-12 18:09:20.000000000 +0200
|
|
@@ -10,6 +10,7 @@
|
|
#define _UTIL_H__
|
|
|
|
#include <string>
|
|
+#include <stdint.h>
|
|
|
|
namespace Util {
|
|
bool add_mcookie(const std::string &mcookie, const char *display,
|
|
@@ -19,6 +20,10 @@
|
|
long random(void);
|
|
|
|
long makeseed(void);
|
|
+ int utf8ToUtf16(const char *utf8, const int utf8_length,
|
|
+ uint16_t *utf16, const int utf16_max_length);
|
|
+ bool utf16EqualToAscii(const char *ascii, uint16_t *utf16, int utf16Len);
|
|
+ std::string utf16BufToUtf8String(const uint16_t *utf16Buf, int utf16Len);
|
|
}
|
|
|
|
#endif /* _UTIL_H__ */
|