00001
00002
00003
00004
00005
00006
00007
00008
00009 #include "mit-copyright.h"
00010
00011
00012
00013
00014
00015
00016
00017 #ifndef X_DISPLAY_MISSING
00018
00019 #include <X11/Xlib.h>
00020 #include <X11/Xutil.h>
00021 #include "new_string.h"
00022 #include "X_gram.h"
00023 #include "main.h"
00024 #include "xselect.h"
00025 #include "xmark.h"
00026 #include "error.h"
00027 #include "xrevstack.h"
00028
00029
00030
00031
00032
00033 extern char *xmarkGetText();
00034
00035 extern long ttl;
00036
00037 static char *selected_text = NULL;
00038 static Window selecting_in = 0;
00039
00040 char *
00041 getSelectedText()
00042 {
00043 return (selected_text);
00044 }
00045
00046
00047
00048
00049
00050
00051 Bool
00052 isShiftButton1(dpy, event, arg)
00053 Display *dpy;
00054 XEvent *event;
00055 char *arg;
00056 {
00057 return (event->xbutton.state & (ShiftMask | Button1Mask));
00058 }
00059
00060
00061 Bool
00062 isShiftButton3(dpy, event, arg)
00063 Display *dpy;
00064 XEvent *event;
00065 char *arg;
00066 {
00067 return (event->xbutton.state & (ShiftMask | Button3Mask));
00068 }
00069
00070 void
00071 getLastEvent(dpy, state, event)
00072 Display *dpy;
00073 unsigned int state;
00074 XEvent *event;
00075 {
00076 XEvent xev;
00077
00078 if (state & Button1Mask) {
00079 while (XCheckIfEvent(dpy, &xev, isShiftButton1, NULL))
00080 *event = xev;
00081 }
00082 else if (state & Button3Mask) {
00083 while (XCheckIfEvent(dpy, &xev, isShiftButton3, NULL))
00084 *event = xev;
00085 }
00086 }
00087
00088 void
00089 xunmark(dpy, w, gram, desc_context)
00090 Display *dpy;
00091 Window w;
00092 x_gram *gram;
00093 XContext desc_context;
00094 {
00095 if (gram == NULL)
00096 if (XFindContext(dpy, w, desc_context, (caddr_t *) & gram))
00097 return;
00098
00099 xmarkClear();
00100 xmarkRedraw(dpy, w, gram, XMARK_REDRAW_OLD);
00101 }
00102
00103
00104
00105 #define PRESSOP_NONE 0
00106 #define PRESSOP_KILL 1
00107 #define PRESSOP_SEL 2
00108 #define PRESSOP_EXT 3
00109 #define PRESSOP_NUKE 4
00110 #define PRESSOP_STOP 5
00111
00112 static int current_pressop = PRESSOP_NONE;
00113
00114 void
00115 xdestroygram(dpy, w, desc_context, gram)
00116 Display *dpy;
00117 Window w;
00118 XContext desc_context;
00119 x_gram *gram;
00120 {
00121 struct timeval now;
00122
00123 gettimeofday(&now, NULL);
00124 if ((gram->can_die.tv_sec == 0) ||
00125 (gram->can_die.tv_sec > now.tv_sec) ||
00126 ((gram->can_die.tv_sec == now.tv_sec) &&
00127 (gram->can_die.tv_usec > now.tv_usec)))
00128 return;
00129
00130 if (w == selecting_in) {
00131 selecting_in = 0;
00132 xmarkClear();
00133 }
00134 current_pressop = PRESSOP_NONE;
00135 XDeleteContext(dpy, w, desc_context);
00136 XDestroyWindow(dpy, w);
00137 delete_gram(gram);
00138 free(gram->text);
00139 free(gram->blocks);
00140 free(gram);
00141
00142 if (bottom_gram == NULL && unlinked == NULL) {
00143
00144 }
00145 }
00146
00147 void
00148 xcut(dpy, event, desc_context)
00149 Display *dpy;
00150 XEvent *event;
00151 XContext desc_context;
00152 {
00153 x_gram *gram;
00154 Window w = event->xany.window;
00155 int changedbound;
00156
00157
00158
00159
00160
00161 if (XFindContext(dpy, w, desc_context, (caddr_t *) & gram))
00162 return;
00163
00164
00165
00166
00167 switch (event->type) {
00168 case ClientMessage:
00169 if ((event->xclient.message_type == XA_WM_PROTOCOLS) &&
00170 (event->xclient.format == 32) &&
00171 (event->xclient.data.l[0] == XA_WM_DELETE_WINDOW))
00172 xdestroygram(dpy, w, desc_context, gram);
00173 break;
00174
00175 case MapNotify:
00176
00177
00178
00179
00180
00181
00182 if (gram->can_die.tv_sec == 0) {
00183 gettimeofday(&(gram->can_die), NULL);
00184 gram->can_die.tv_sec += (int) (ttl / 1000);
00185 gram->can_die.tv_usec += (ttl % 1000) * 1000;
00186 }
00187 break;
00188
00189 case UnmapNotify:
00190 unlink_gram(gram);
00191 break;
00192
00193 case LeaveNotify:
00194 if (current_pressop == PRESSOP_KILL ||
00195 current_pressop == PRESSOP_NUKE)
00196 current_pressop = PRESSOP_STOP;
00197 break;
00198
00199 case MotionNotify:
00200 if (current_pressop == PRESSOP_SEL) {
00201
00202 changedbound = xmarkExtendFromFirst(gram, event->xmotion.x,
00203 event->xmotion.y);
00204 xmarkRedraw(dpy, w, gram, changedbound);
00205 }
00206 else if (current_pressop == PRESSOP_EXT) {
00207
00208 changedbound = xmarkExtendFromNearest(gram, event->xmotion.x,
00209 event->xmotion.y);
00210 xmarkRedraw(dpy, w, gram, changedbound);
00211 }
00212 break;
00213
00214 case ButtonPress:
00215 if (current_pressop != PRESSOP_NONE) {
00216 current_pressop = PRESSOP_STOP;
00217 }
00218 else if ((event->xbutton.state) & ShiftMask) {
00219 if (event->xbutton.button == Button1) {
00220 if (selecting_in)
00221 xunmark(dpy, selecting_in, NULL, desc_context);
00222 if (selected_text)
00223 free(selected_text);
00224 selected_text = NULL;
00225 if (!xselGetOwnership(dpy, w, event->xbutton.time)) {
00226 XBell(dpy, 0);
00227 ERROR("Unable to get ownership of PRIMARY selection.\n");
00228 selecting_in = 0;
00229 current_pressop = PRESSOP_STOP;
00230 }
00231 else {
00232 selecting_in = w;
00233 xmarkStart(gram, event->xbutton.x, event->xbutton.y);
00234 current_pressop = PRESSOP_SEL;
00235 }
00236 }
00237 else if ((event->xbutton.button == Button3) &&
00238 (w == selecting_in)) {
00239 if (selected_text)
00240 free(selected_text);
00241 selected_text = NULL;
00242 changedbound = xmarkExtendFromNearest(gram, event->xbutton.x,
00243 event->xbutton.y);
00244 xmarkRedraw(dpy, w, gram, changedbound);
00245 selected_text = xmarkGetText();
00246
00247
00248
00249
00250 current_pressop = PRESSOP_EXT;
00251 }
00252 }
00253 else if ((event->xbutton.state) & ControlMask) {
00254 current_pressop = PRESSOP_NUKE;
00255 }
00256 else {
00257 current_pressop = PRESSOP_KILL;
00258 }
00259 break;
00260
00261 case ButtonRelease:
00262 if (current_pressop == PRESSOP_KILL) {
00263 xdestroygram(dpy, w, desc_context, gram);
00264 }
00265 else if (current_pressop == PRESSOP_SEL ||
00266 current_pressop == PRESSOP_EXT) {
00267 if (selected_text)
00268 free(selected_text);
00269 selected_text = xmarkGetText();
00270 }
00271 else if (current_pressop == PRESSOP_NUKE) {
00272 XWindowAttributes wa;
00273 int gx, gy;
00274 Window temp;
00275 x_gram *next;
00276
00277 for (gram = bottom_gram; gram; gram = next) {
00278 XGetWindowAttributes(dpy, gram->w, &wa);
00279 XTranslateCoordinates(dpy, gram->w, wa.root, 0, 0, &gx, &gy,
00280 &temp);
00281
00282 next = gram->above;
00283
00284 if ((wa.map_state == IsViewable) &&
00285 (gx <= event->xbutton.x_root) &&
00286 (event->xbutton.x_root < gx + wa.width) &&
00287 (gy <= event->xbutton.y_root) &&
00288 (event->xbutton.y_root < gy + wa.height)) {
00289 xdestroygram(dpy, gram->w, desc_context, gram);
00290 }
00291 }
00292 for (gram = unlinked; gram; gram = next) {
00293 XGetWindowAttributes(dpy, gram->w, &wa);
00294 XTranslateCoordinates(dpy, gram->w, wa.root, 0, 0, &gx, &gy,
00295 &temp);
00296
00297 next = gram->above;
00298
00299 if ((wa.map_state == IsViewable) &&
00300 (gx <= event->xbutton.x_root) &&
00301 (event->xbutton.x_root < gx + wa.width) &&
00302 (gy <= event->xbutton.y_root) &&
00303 (event->xbutton.y_root < gy + wa.height)) {
00304 xdestroygram(dpy, gram->w, desc_context, gram);
00305 }
00306 }
00307 }
00308 current_pressop = PRESSOP_NONE;
00309 break;
00310
00311 case SelectionRequest:
00312 xselProcessSelection(dpy, w, event);
00313 break;
00314
00315 case SelectionClear:
00316 xselOwnershipLost(event->xselectionclear.time);
00317 if (w == selecting_in) {
00318 selecting_in = 0;
00319 xunmark(dpy, w, gram, desc_context);
00320 if (selected_text)
00321 free(selected_text);
00322 selected_text = NULL;
00323 }
00324 break;
00325
00326 default:
00327 break;
00328 }
00329
00330 XFlush(dpy);
00331 }
00332
00333 #endif