Code update for Window Maker version 0.50.0
[wmaker-crm.git] / WINGs / wtextfield.c
blob2821e2e36c2b1b559b5469d072bdc0336ba109dc
5 #include "WINGsP.h"
7 #include <X11/keysym.h>
8 #include <X11/Xatom.h>
10 #include <ctype.h>
12 #define CURSOR_BLINK_ON_DELAY 600
13 #define CURSOR_BLINK_OFF_DELAY 300
16 char *WMTextDidChangeNotification = "WMTextDidChangeNotification";
17 char *WMTextDidBeginEditingNotification = "WMTextDidBeginEditingNotification";
18 char *WMTextDidEndEditingNotification = "WMTextDidEndEditingNotification";
21 typedef struct W_TextField {
22 W_Class widgetClass;
23 W_View *view;
25 struct W_TextField *nextField; /* next textfield in the chain */
26 struct W_TextField *prevField;
28 char *text;
29 int textLen; /* size of text */
30 int bufferSize; /* memory allocated for text */
32 int viewPosition; /* position of text being shown */
34 int cursorPosition; /* position of the insertion cursor */
36 short usableWidth;
37 short offsetWidth; /* offset of text from border */
39 WMRange selection;
41 #if 0
42 WMHandlerID timerID; /* for cursor blinking */
43 #endif
44 struct {
45 WMAlignment alignment:2;
47 unsigned int bordered:1;
49 unsigned int enabled:1;
51 unsigned int focused:1;
53 unsigned int cursorOn:1;
55 unsigned int secure:1; /* password entry style */
57 /**/
58 unsigned int notIllegalMovement:1;
59 } flags;
60 } TextField;
63 #define MIN_TEXT_BUFFER 2
64 #define TEXT_BUFFER_INCR 8
67 #define WM_EMACSKEYMASK ControlMask
69 #define WM_EMACSKEY_LEFT XK_b
70 #define WM_EMACSKEY_RIGHT XK_f
71 #define WM_EMACSKEY_HOME XK_a
72 #define WM_EMACSKEY_END XK_e
73 #define WM_EMACSKEY_BS XK_h
74 #define WM_EMACSKEY_DEL XK_d
78 #define DEFAULT_WIDTH 60
79 #define DEFAULT_HEIGHT 20
80 #define DEFAULT_BORDERED True
81 #define DEFAULT_ALIGNMENT WALeft
85 static void destroyTextField(TextField *tPtr);
86 static void paintTextField(TextField *tPtr);
88 static void handleEvents(XEvent *event, void *data);
89 static void handleTextFieldActionEvents(XEvent *event, void *data);
90 static void resizeTextField();
92 struct W_ViewProcedureTable _TextFieldViewProcedures = {
93 NULL,
94 resizeTextField,
95 NULL
99 #define TEXT_WIDTH(tPtr, start) (WMWidthOfString((tPtr)->view->screen->normalFont, \
100 &((tPtr)->text[(start)]), (tPtr)->textLen - (start) + 1))
102 #define TEXT_WIDTH2(tPtr, start, end) (WMWidthOfString((tPtr)->view->screen->normalFont, \
103 &((tPtr)->text[(start)]), (end) - (start) + 1))
106 static void
107 memmv(char *dest, char *src, int size)
109 int i;
111 if (dest > src) {
112 for (i=size-1; i>=0; i--) {
113 dest[i] = src[i];
115 } else if (dest < src) {
116 for (i=0; i<size; i++) {
117 dest[i] = src[i];
123 static int
124 incrToFit(TextField *tPtr)
126 int vp = tPtr->viewPosition;
128 while (TEXT_WIDTH(tPtr, tPtr->viewPosition) > tPtr->usableWidth) {
129 tPtr->viewPosition++;
131 return vp!=tPtr->viewPosition;
134 static int
135 incrToFit2(TextField *tPtr)
137 int vp = tPtr->viewPosition;
138 while (TEXT_WIDTH2(tPtr, tPtr->viewPosition, tPtr->cursorPosition)
139 >= tPtr->usableWidth)
140 tPtr->viewPosition++;
143 return vp!=tPtr->viewPosition;
147 static void
148 decrToFit(TextField *tPtr)
150 while (TEXT_WIDTH(tPtr, tPtr->viewPosition-1) < tPtr->usableWidth
151 && tPtr->viewPosition>0)
152 tPtr->viewPosition--;
155 #undef TEXT_WIDTH
156 #undef TEXT_WIDTH2
159 WMTextField*
160 WMCreateTextField(WMWidget *parent)
162 TextField *tPtr;
165 tPtr = wmalloc(sizeof(TextField));
166 memset(tPtr, 0, sizeof(TextField));
168 tPtr->widgetClass = WC_TextField;
170 tPtr->view = W_CreateView(W_VIEW(parent));
171 if (!tPtr->view) {
172 free(tPtr);
173 return NULL;
175 tPtr->view->self = tPtr;
177 tPtr->view->attribFlags |= CWCursor;
178 tPtr->view->attribs.cursor = tPtr->view->screen->textCursor;
180 W_SetViewBackgroundColor(tPtr->view, tPtr->view->screen->white);
182 tPtr->text = wmalloc(MIN_TEXT_BUFFER);
183 tPtr->text[0] = 0;
184 tPtr->textLen = 0;
185 tPtr->bufferSize = MIN_TEXT_BUFFER;
187 tPtr->flags.enabled = 1;
189 WMCreateEventHandler(tPtr->view, ExposureMask|StructureNotifyMask
190 |FocusChangeMask, handleEvents, tPtr);
192 W_ResizeView(tPtr->view, DEFAULT_WIDTH, DEFAULT_HEIGHT);
193 WMSetTextFieldBordered(tPtr, DEFAULT_BORDERED);
194 tPtr->flags.alignment = DEFAULT_ALIGNMENT;
195 tPtr->offsetWidth = (tPtr->view->size.height
196 - WMFontHeight(tPtr->view->screen->normalFont))/2;
198 WMCreateEventHandler(tPtr->view, EnterWindowMask|LeaveWindowMask
199 |ButtonPressMask|KeyPressMask|Button1MotionMask,
200 handleTextFieldActionEvents, tPtr);
202 tPtr->flags.cursorOn = 1;
204 return tPtr;
208 void
209 WMInsertTextFieldText(WMTextField *tPtr, char *text, int position)
211 int len;
213 CHECK_CLASS(tPtr, WC_TextField);
215 if (!text)
216 return;
218 len = strlen(text);
220 /* check if buffer will hold the text */
221 if (len + tPtr->textLen >= tPtr->bufferSize) {
222 tPtr->bufferSize = tPtr->textLen + len + TEXT_BUFFER_INCR;
223 tPtr->text = realloc(tPtr->text, tPtr->bufferSize);
226 if (position < 0 || position >= tPtr->textLen) {
227 /* append the text at the end */
228 strcat(tPtr->text, text);
230 incrToFit(tPtr);
232 tPtr->textLen += len;
233 tPtr->cursorPosition += len;
234 } else {
235 /* insert text at position */
236 memmv(&(tPtr->text[position+len]), &(tPtr->text[position]),
237 tPtr->textLen-position+1);
239 memcpy(&(tPtr->text[position]), text, len);
241 tPtr->textLen += len;
242 if (position >= tPtr->cursorPosition) {
243 tPtr->cursorPosition += len;
244 incrToFit2(tPtr);
245 } else {
246 incrToFit(tPtr);
250 paintTextField(tPtr);
254 void
255 WMDeleteTextFieldRange(WMTextField *tPtr, WMRange range)
257 CHECK_CLASS(tPtr, WC_TextField);
259 if (range.position >= tPtr->textLen)
260 return;
262 if (range.count < 1) {
263 if (range.position < 0)
264 range.position = 0;
265 tPtr->text[range.position] = 0;
266 tPtr->textLen = range.position;
268 tPtr->cursorPosition = 0;
269 tPtr->viewPosition = 0;
270 } else {
271 if (range.position + range.count > tPtr->textLen)
272 range.count = tPtr->textLen - range.position;
273 memmv(&(tPtr->text[range.position]), &(tPtr->text[range.position+range.count]),
274 tPtr->textLen - (range.position+range.count) + 1);
275 tPtr->textLen -= range.count;
277 if (tPtr->cursorPosition > range.position)
278 tPtr->cursorPosition -= range.count;
280 decrToFit(tPtr);
283 paintTextField(tPtr);
288 char*
289 WMGetTextFieldText(WMTextField *tPtr)
291 CHECK_CLASS(tPtr, WC_TextField);
293 return wstrdup(tPtr->text);
297 void
298 WMSetTextFieldText(WMTextField *tPtr, char *text)
300 if (text==NULL) {
301 tPtr->text[0] = 0;
302 tPtr->textLen = 0;
303 } else {
304 tPtr->textLen = strlen(text);
306 if (tPtr->textLen >= tPtr->bufferSize) {
307 tPtr->bufferSize = tPtr->textLen + TEXT_BUFFER_INCR;
308 tPtr->text = realloc(tPtr->text, tPtr->bufferSize);
310 strcpy(tPtr->text, text);
313 if (tPtr->textLen < tPtr->cursorPosition)
314 tPtr->cursorPosition = tPtr->textLen;
316 tPtr->cursorPosition = 0;
317 tPtr->viewPosition = 0;
319 if (tPtr->view->flags.realized)
320 paintTextField(tPtr);
324 void
325 WMSetTextFieldAlignment(WMTextField *tPtr, WMAlignment alignment)
327 tPtr->flags.alignment = alignment;
328 if (alignment!=WALeft) {
329 wwarning("only left alignment is supported in textfields");
330 return;
333 if (tPtr->view->flags.realized) {
334 paintTextField(tPtr);
339 void
340 WMSetTextFieldBordered(WMTextField *tPtr, Bool bordered)
342 tPtr->flags.bordered = bordered;
344 if (tPtr->view->flags.realized) {
345 paintTextField(tPtr);
351 void
352 WMSetTextFieldSecure(WMTextField *tPtr, Bool flag)
354 tPtr->flags.secure = flag;
356 if (tPtr->view->flags.realized) {
357 paintTextField(tPtr);
362 void
363 WMSetTextFieldEnabled(WMTextField *tPtr, Bool flag)
365 tPtr->flags.enabled = flag;
367 if (tPtr->view->flags.realized) {
368 paintTextField(tPtr);
373 static void
374 resizeTextField(WMTextField *tPtr, unsigned int width, unsigned int height)
376 W_ResizeView(tPtr->view, width, height);
378 tPtr->offsetWidth = (tPtr->view->size.height
379 - WMFontHeight(tPtr->view->screen->normalFont))/2;
381 tPtr->usableWidth = tPtr->view->size.width - 2*tPtr->offsetWidth;
385 static void
386 paintCursor(TextField *tPtr)
388 int cx;
389 WMScreen *screen = tPtr->view->screen;
390 int textWidth;
392 cx = WMWidthOfString(screen->normalFont,
393 &(tPtr->text[tPtr->viewPosition]),
394 tPtr->cursorPosition-tPtr->viewPosition);
396 switch (tPtr->flags.alignment) {
397 case WARight:
398 textWidth = WMWidthOfString(screen->normalFont, tPtr->text,
399 tPtr->textLen);
400 if (textWidth < tPtr->usableWidth)
401 cx += tPtr->offsetWidth + tPtr->usableWidth - textWidth;
402 else
403 cx += tPtr->offsetWidth;
404 break;
405 case WALeft:
406 cx += tPtr->offsetWidth;
407 break;
408 case WACenter:
409 textWidth = WMWidthOfString(screen->normalFont, tPtr->text,
410 tPtr->textLen);
411 if (textWidth < tPtr->usableWidth)
412 cx += tPtr->offsetWidth + (tPtr->usableWidth-textWidth)/2;
413 else
414 cx += tPtr->offsetWidth;
415 break;
418 XDrawRectangle(screen->display, tPtr->view->window, screen->xorGC,
419 cx, tPtr->offsetWidth, 1,
420 tPtr->view->size.height - 2*tPtr->offsetWidth - 1);
422 XDrawLine(screen->display, tPtr->view->window, screen->xorGC,
423 cx, tPtr->offsetWidth, cx,
424 tPtr->view->size.height - tPtr->offsetWidth - 1);
429 static void
430 drawRelief(WMView *view)
432 WMScreen *scr = view->screen;
433 Display *dpy = scr->display;
434 GC wgc;
435 GC lgc;
436 GC dgc;
437 int width = view->size.width;
438 int height = view->size.height;
440 wgc = W_GC(scr->white);
441 dgc = W_GC(scr->darkGray);
442 lgc = W_GC(scr->gray);
444 /* top left */
445 XDrawLine(dpy, view->window, dgc, 0, 0, width-1, 0);
446 XDrawLine(dpy, view->window, dgc, 0, 1, width-2, 1);
448 XDrawLine(dpy, view->window, dgc, 0, 0, 0, height-2);
449 XDrawLine(dpy, view->window, dgc, 1, 0, 1, height-3);
451 /* bottom right */
452 XDrawLine(dpy, view->window, wgc, 0, height-1, width-1, height-1);
453 XDrawLine(dpy, view->window, lgc, 1, height-2, width-2, height-2);
455 XDrawLine(dpy, view->window, wgc, width-1, 0, width-1, height-1);
456 XDrawLine(dpy, view->window, lgc, width-2, 1, width-2, height-3);
460 static void
461 paintTextField(TextField *tPtr)
463 W_Screen *screen = tPtr->view->screen;
464 W_View *view = tPtr->view;
465 int tx, ty, tw, th;
466 int bd;
467 int totalWidth;
470 if (!view->flags.realized || !view->flags.mapped)
471 return;
473 if (!tPtr->flags.bordered) {
474 bd = 0;
475 } else {
476 bd = 2;
479 totalWidth = tPtr->view->size.width - 2*bd;
481 if (tPtr->textLen > 0) {
482 tw = WMWidthOfString(screen->normalFont,
483 &(tPtr->text[tPtr->viewPosition]),
484 tPtr->textLen - tPtr->viewPosition);
486 th = WMFontHeight(screen->normalFont);
488 ty = tPtr->offsetWidth;
489 switch (tPtr->flags.alignment) {
490 case WALeft:
491 tx = tPtr->offsetWidth;
492 if (tw < tPtr->usableWidth)
493 XClearArea(screen->display, view->window, bd+tw, bd,
494 totalWidth-tw, view->size.height-2*bd,
495 False);
496 break;
498 case WACenter:
499 tx = tPtr->offsetWidth + (tPtr->usableWidth - tw) / 2;
500 if (tw < tPtr->usableWidth)
501 XClearArea(screen->display, view->window, bd, bd,
502 totalWidth, view->size.height-2*bd, False);
503 break;
505 default:
506 case WARight:
507 tx = tPtr->offsetWidth + tPtr->usableWidth - tw;
508 if (tw < tPtr->usableWidth)
509 XClearArea(screen->display, view->window, bd, bd,
510 totalWidth-tw, view->size.height-2*bd, False);
511 break;
514 if (!tPtr->flags.secure) {
515 if (!tPtr->flags.enabled)
516 WMSetColorInGC(screen->darkGray, screen->textFieldGC);
518 WMDrawImageString(screen, view->window, screen->textFieldGC,
519 screen->normalFont, tx, ty,
520 &(tPtr->text[tPtr->viewPosition]),
521 tPtr->textLen - tPtr->viewPosition);
523 if (!tPtr->flags.enabled)
524 WMSetColorInGC(screen->black, screen->textFieldGC);
526 } else {
527 XClearArea(screen->display, view->window, bd, bd, totalWidth,
528 view->size.height - 2*bd, False);
531 /* draw cursor */
532 if (tPtr->flags.focused && tPtr->flags.enabled && tPtr->flags.cursorOn) {
533 paintCursor(tPtr);
536 /* draw relief */
537 if (tPtr->flags.bordered) {
538 drawRelief(view);
543 #if 0
544 static void
545 blinkCursor(void *data)
547 TextField *tPtr = (TextField*)data;
549 if (tPtr->flags.cursorOn) {
550 tPtr->timerID = WMAddTimerHandler(CURSOR_BLINK_OFF_DELAY, blinkCursor,
551 data);
552 } else {
553 tPtr->timerID = WMAddTimerHandler(CURSOR_BLINK_ON_DELAY, blinkCursor,
554 data);
556 paintCursor(tPtr);
557 tPtr->flags.cursorOn = !tPtr->flags.cursorOn;
559 #endif
561 static void
562 handleEvents(XEvent *event, void *data)
564 TextField *tPtr = (TextField*)data;
566 CHECK_CLASS(data, WC_TextField);
569 switch (event->type) {
570 case FocusIn:
571 if (W_FocusedViewOfToplevel(W_TopLevelOfView(tPtr->view))!=tPtr->view)
572 return;
573 tPtr->flags.focused = 1;
574 #if 0
575 if (!tPtr->timerID) {
576 tPtr->timerID = WMAddTimerHandler(CURSOR_BLINK_ON_DELAY,
577 blinkCursor, tPtr);
579 #endif
580 paintTextField(tPtr);
582 WMPostNotificationName(WMTextDidBeginEditingNotification, tPtr, NULL);
584 tPtr->flags.notIllegalMovement = 0;
585 break;
587 case FocusOut:
588 tPtr->flags.focused = 0;
589 #if 0
590 if (tPtr->timerID)
591 WMDeleteTimerHandler(tPtr->timerID);
592 tPtr->timerID = NULL;
593 #endif
595 paintTextField(tPtr);
596 if (!tPtr->flags.notIllegalMovement) {
597 WMPostNotificationName(WMTextDidEndEditingNotification, tPtr,
598 (void*)WMIllegalTextMovement);
600 break;
602 case Expose:
603 if (event->xexpose.count!=0)
604 break;
605 paintTextField(tPtr);
606 break;
608 case DestroyNotify:
609 destroyTextField(tPtr);
610 break;
615 static void
616 handleTextFieldKeyPress(TextField *tPtr, XEvent *event)
618 char buffer[64];
619 KeySym ksym;
620 int count, refresh = 0;
621 int control_pressed = 0;
622 int changed;
623 WMScreen *scr = tPtr->view->screen;
625 changed = 0;
627 if (((XKeyEvent *) event)->state & WM_EMACSKEYMASK) {
628 control_pressed = 1;
631 count = XLookupString(&event->xkey, buffer, 63, &ksym, NULL);
632 buffer[count] = '\0';
634 switch (ksym) {
635 case XK_Tab:
636 if (event->xkey.state & ShiftMask) {
637 if (tPtr->view->prevFocusChain) {
638 W_SetFocusOfTopLevel(W_TopLevelOfView(tPtr->view),
639 tPtr->view->prevFocusChain);
640 tPtr->flags.notIllegalMovement = 1;
642 WMPostNotificationName(WMTextDidEndEditingNotification, tPtr,
643 (void*)WMBacktabTextMovement);
644 } else {
645 if (tPtr->view->nextFocusChain) {
646 W_SetFocusOfTopLevel(W_TopLevelOfView(tPtr->view),
647 tPtr->view->nextFocusChain);
648 tPtr->flags.notIllegalMovement = 1;
650 WMPostNotificationName(WMTextDidEndEditingNotification,
651 tPtr, (void*)WMTabTextMovement);
653 break;
655 case XK_Return:
656 WMPostNotificationName(WMTextDidEndEditingNotification, tPtr,
657 (void*)WMReturnTextMovement);
658 break;
660 case WM_EMACSKEY_LEFT:
661 if (!control_pressed) {
662 goto normal_key;
664 case XK_KP_Left:
665 case XK_Left:
666 if (tPtr->cursorPosition > 0) {
667 paintCursor(tPtr);
668 tPtr->cursorPosition--;
669 if (tPtr->cursorPosition < tPtr->viewPosition) {
670 tPtr->viewPosition = tPtr->cursorPosition;
671 refresh = 1;
672 } else {
673 paintCursor(tPtr);
676 break;
678 case WM_EMACSKEY_RIGHT:
679 if (!control_pressed) {
680 goto normal_key;
682 case XK_KP_Right:
683 case XK_Right:
684 if (tPtr->cursorPosition < tPtr->textLen) {
685 paintCursor(tPtr);
686 tPtr->cursorPosition++;
687 while (WMWidthOfString(scr->normalFont,
688 &(tPtr->text[tPtr->viewPosition]),
689 tPtr->cursorPosition-tPtr->viewPosition)
690 > tPtr->usableWidth) {
691 tPtr->viewPosition++;
692 refresh = 1;
694 if (!refresh)
695 paintCursor(tPtr);
697 break;
699 case WM_EMACSKEY_HOME:
700 if (!control_pressed) {
701 goto normal_key;
703 case XK_KP_Home:
704 case XK_Home:
705 if (tPtr->cursorPosition > 0) {
706 paintCursor(tPtr);
707 tPtr->cursorPosition = 0;
708 if (tPtr->viewPosition > 0) {
709 tPtr->viewPosition = 0;
710 refresh = 1;
711 } else {
712 paintCursor(tPtr);
715 break;
717 case WM_EMACSKEY_END:
718 if (!control_pressed) {
719 goto normal_key;
721 case XK_KP_End:
722 case XK_End:
723 if (tPtr->cursorPosition < tPtr->textLen) {
724 paintCursor(tPtr);
725 tPtr->cursorPosition = tPtr->textLen;
726 tPtr->viewPosition = 0;
727 while (WMWidthOfString(scr->normalFont,
728 &(tPtr->text[tPtr->viewPosition]),
729 tPtr->textLen-tPtr->viewPosition)
730 >= tPtr->usableWidth) {
731 tPtr->viewPosition++;
732 refresh = 1;
734 if (!refresh)
735 paintCursor(tPtr);
737 break;
739 case WM_EMACSKEY_BS:
740 if (!control_pressed) {
741 goto normal_key;
743 case XK_BackSpace:
744 if (tPtr->cursorPosition > 0) {
745 WMRange range;
746 changed = 1;
747 range.position = tPtr->cursorPosition-1;
748 range.count = 1;
749 WMDeleteTextFieldRange(tPtr, range);
751 break;
753 case WM_EMACSKEY_DEL:
754 if (!control_pressed) {
755 goto normal_key;
757 case XK_KP_Delete:
758 case XK_Delete:
759 if (tPtr->cursorPosition < tPtr->textLen) {
760 WMRange range;
761 changed = 1;
762 range.position = tPtr->cursorPosition;
763 range.count = 1;
764 WMDeleteTextFieldRange(tPtr, range);
766 break;
768 normal_key:
769 default:
770 if (count > 0 && !iscntrl(buffer[0])) {
771 changed = 1;
772 WMInsertTextFieldText(tPtr, buffer, tPtr->cursorPosition);
775 if (refresh) {
776 paintTextField(tPtr);
779 if (changed) {
780 WMPostNotificationName(WMTextDidChangeNotification, tPtr, NULL);
785 static int
786 pointToCursorPosition(TextField *tPtr, int x)
788 WMFont *font = tPtr->view->screen->normalFont;
789 int a, b, mid;
790 int tw;
792 if (tPtr->flags.bordered)
793 x -= 2;
795 a = tPtr->viewPosition;
796 b = tPtr->viewPosition + tPtr->textLen;
797 if (WMWidthOfString(font, &(tPtr->text[tPtr->viewPosition]),
798 tPtr->textLen-tPtr->viewPosition) < x)
799 return tPtr->textLen;
801 while (a < b && b-a>1) {
802 mid = (a+b)/2;
803 tw = WMWidthOfString(font, &(tPtr->text[tPtr->viewPosition]),
804 mid - tPtr->viewPosition);
805 if (tw > x)
806 b = mid;
807 else if (tw < x)
808 a = mid;
809 else
810 return mid;
812 return (a+b)/2;
816 static void
817 handleTextFieldActionEvents(XEvent *event, void *data)
819 TextField *tPtr = (TextField*)data;
821 CHECK_CLASS(data, WC_TextField);
823 switch (event->type) {
824 case KeyPress:
825 if (tPtr->flags.enabled)
826 handleTextFieldKeyPress(tPtr, event);
827 break;
829 case MotionNotify:
830 if (tPtr->flags.enabled && (event->xmotion.state & Button1Mask)) {
831 tPtr->cursorPosition = pointToCursorPosition(tPtr,
832 event->xmotion.x);
833 paintTextField(tPtr);
835 break;
837 case ButtonPress:
838 if (tPtr->flags.enabled && !tPtr->flags.focused) {
839 WMSetFocusToWidget(tPtr);
840 tPtr->cursorPosition = pointToCursorPosition(tPtr,
841 event->xbutton.x);
842 paintTextField(tPtr);
843 } else if (tPtr->flags.focused) {
844 tPtr->cursorPosition = pointToCursorPosition(tPtr,
845 event->xbutton.x);
846 paintTextField(tPtr);
848 if (event->xbutton.button == Button2 && tPtr->flags.enabled) {
849 char *text;
851 text = W_GetTextSelection(tPtr->view->screen, XA_PRIMARY);
852 if (!text) {
853 text = W_GetTextSelection(tPtr->view->screen, XA_CUT_BUFFER0);
855 if (text) {
856 WMInsertTextFieldText(tPtr, text, tPtr->cursorPosition);
857 XFree(text);
858 WMPostNotificationName(WMTextDidChangeNotification, tPtr,
859 NULL);
862 break;
864 case ButtonRelease:
866 break;
871 static void
872 destroyTextField(TextField *tPtr)
874 #if 0
875 if (tPtr->timerID)
876 WMDeleteTimerHandler(tPtr->timerID);
877 #endif
879 if (tPtr->text)
880 free(tPtr->text);
882 free(tPtr);