/* treewm - an X11 window manager.
* Copyright (c) 2001-2002 Thomas Jäger <TheHunter2000 at web dot de>
* This code is released under the terms of the GNU GPL.
* See the included file LICENSE for details.
*/
#include "textdialog.h"
#include "sceme.h"
#include "uehandler.h"
#include <X11/keysym.h>
void TextDialog::AddHistory() {
if (!length)
return;
hist[histpos] = strdup(line);
++histpos;
histpos %= HISTSIZE;
histref = histpos;
if (hist[histpos])
free(hist[histpos]);
hist[histpos] = 0;
}
void TextDialog::ChangeHist(int a) {
if (!hist[(histref + a) % HISTSIZE])
return;
histref = (histref + a) % HISTSIZE;
strcpy(line,hist[histref]);
length = strlen(line);
cur = length;
ReDraw();
}
char *TextDialog::hist[HISTSIZE];
int TextDialog::histpos;
char *TextDialog::Key(XKeyEvent &ev) {
char buf[2];
KeySym ks = XLookupKeysym(&ev, 0);
if (ev.state & Mod1Mask) {
switch (ks) {
case XK_space:
return strdup(line);
case XK_Return:
return strdup(line);
default:
return 0;
}
}
switch (ks) {
case XK_Return:
if (length == 0)
return strdup(line);
AddHistory();
UEH->ExecCommand(0,0,line,true);
cur = 0;
length = 0;
line[0] = '\0';
ReDraw();
return 0;
case XK_Escape:
return strdup("");
case XK_Home:
cur = 0;
ReDraw();
return 0;
case XK_End:
cur = length;
ReDraw();
return 0;
case XK_Left:
if (cur) {
--cur;
ReDraw();
}
return 0;
case XK_Right:
if (cur != length) {
++cur;
ReDraw();
}
return 0;
case XK_BackSpace:
if (!cur)
return 0;
--cur;
case XK_Delete:
if (cur == length)
return 0;
for (int i=cur;i!=length;i++)
line[i]=line[i+1];
line[--length] = '\0';
ReDraw();
return 0;
case XK_Up:
case XK_Page_Up:
ChangeHist(HISTSIZE - 1);
return 0;
case XK_Down:
case XK_Page_Down:
ChangeHist(1);
return 0;
case XK_Tab:
Complete();
return 0;
}
// XmbLookupString ??
if (1 != XLookupString(&ev,buf,1,0,&cstatus)) {
#ifdef DEBUG
err("%i",cstatus.chars_matched);
#endif
return 0;
}
if (length == 0) {
buf[1] = '\0';
if (UEH->ExecCommand(0,0,buf,false))
return 0;
}
if (length == MAXLENGTH-1)
return 0;
for (int i=length;i>=cur;i--)
line[i+1]=line[i];
line[cur++] = buf[0];
++length;
ReDraw();
return 0;
}
TextDialog::TextDialog(Sceme *SC) {
Sc = SC;
histref = histpos;
XSetWindowAttributes pattr;
cstatus.compose_ptr = 0;
cstatus.chars_matched = 0;
XFontSetExtents *e = XExtentsOfFontSet(Sc->fonts[FO_DIALOG]);
height = e->max_logical_extent.height*4/5 + e->max_logical_extent.height/5 + 2*DIALOGSPACE;
int sw = DisplayWidth(dpy,screen);
int sh = DisplayHeight(dpy,screen);
int space = sw/64;
pattr.override_redirect = True;
pattr.background_pixel = Sc->colors[C_DBG].pixel;
pattr.border_pixel = Sc->colors[C_DBD].pixel;
pattr.event_mask = ChildMask|ButtonMask|ExposureMask|EnterWindowMask|KeyPressMask;
window = XCreateWindow(dpy, root, space, sh-height-space, sw-2*space, height, 1,
DefaultDepth(dpy, screen), CopyFromParent, DefaultVisual(dpy, screen),
CWOverrideRedirect|CWBackPixel|CWBorderPixel|CWEventMask, &pattr);
XMapWindow(dpy,window);
XGrabKeyboard(dpy,window,false,GrabModeAsync,GrabModeAsync,CurrentTime);
cur = 0;
length = 0;
line[0] = '\0';
}
void TextDialog::ReDraw() {
XClearWindow(dpy,window);
XFontSetExtents *e = XExtentsOfFontSet(Sc->fonts[FO_DIALOG]);
XmbDrawString(dpy, window, Sc->fonts[FO_DIALOG], Sc->dialogstring_gc, DIALOGSPACE,
DIALOGSPACE + e->max_logical_extent.height*4/5, line, length);
int curpos = DIALOGSPACE + XmbTextEscapement(Sc->fonts[FO_DIALOG],line,cur);
XDrawLine(dpy,window,Sc->invert_gc,curpos,DIALOGSPACE,curpos,height - DIALOGSPACE);
}
void TextDialog::SetCursor(int x) {
x -= DIALOGSPACE;
if (x < 0) {
cur = 0;
ReDraw();
return;
}
if (x > XmbTextEscapement(Sc->fonts[FO_DIALOG],line,length)) {
cur = length;
ReDraw();
return;
}
int i1=0,i2=length;
while (i2 != i1+1) {
int i = (i1 + i2) / 2;
if (x > XmbTextEscapement(Sc->fonts[FO_DIALOG],line,i))
i1 = i; else
i2 = i;
}
if (XmbTextEscapement(Sc->fonts[FO_DIALOG],line,i1) +
XmbTextEscapement(Sc->fonts[FO_DIALOG],line,i2) <= 2*x)
cur = i2; else
cur = i1;
ReDraw();
}
void TextDialog::Paste() {
char *buffer,*tmp;
int rest;
int nbytes;
if ((buffer = XFetchBytes(dpy, &nbytes)) != NULL) {
tmp = strdup(line+cur);
rest = length - cur;
strncpy(line+cur,buffer,MAXLENGTH - cur - 1);
line[MAXLENGTH-1] = '\0';
length = strlen(line);
cur = length;
if (length + rest > MAXLENGTH-1)
cur = MAXLENGTH - 1 - rest;
strcpy(line+cur,tmp);
length = strlen(line);
free(tmp);
}
XFree(buffer);
ReDraw();
}
void TextDialog::SetLine(char *n) {
strncpy(line, n, MAXLENGTH - 1);
line[MAXLENGTH-1] = '\0';
length = strlen(line);
cur = length;
ReDraw();
}
void TextDialog::Complete() {
// !!!
}
TextDialog::~TextDialog() {
AddHistory();
XUngrabKeyboard(dpy,CurrentTime);
XUnmapWindow(dpy,window);
XDestroyWindow(dpy,window);
}
syntax highlighted by Code2HTML, v. 0.9.1