1 /* g_motif.cpp
2 *
3 * Copyright (c) 1994-1996, Marko Macek
4 * Copyright (c) 2010, Zdenek Kabelac
5 *
6 * You may distribute under the terms of either the GNU General Public
7 * License or the Artistic License, as specified in the README file.
8 *
9 * Only demo code
10 */
11
12 #include "c_config.h"
13 #include "console.h"
14 #include "gui.h"
15 #include "s_string.h"
16
17 #include <X11/Xatom.h>
18 #include <X11/Xlib.h>
19 #include <X11/Xutil.h>
20 #include <X11/keysym.h>
21
22 #ifdef HPUX
23 #include </usr/include/X11R5/X11/HPkeysym.h>
24 #endif
25
26 #include <Xm/Xm.h>
27
28 #include <Xm/BulletinB.h>
29 #include <Xm/CascadeB.h>
30 #include <Xm/DrawingA.h>
31 #include <Xm/Form.h>
32 #include <Xm/Label.h>
33 #include <Xm/MainW.h>
34 #include <Xm/MainW.h>
35 #include <Xm/PanedW.h>
36 #include <Xm/PushB.h>
37 #include <Xm/RowColumn.h>
38 #include <Xm/ScrollBar.h>
39 #include <Xm/ScrolledW.h>
40 #include <Xm/Separator.h>
41 #include <Xm/Text.h>
42
43 #include <fcntl.h>
44 #include <stdarg.h>
45 #include <stdio.h>
46 #include <stdlib.h>
47 #include <sys/wait.h>
48
49 #define DEBUG(x)
50 //printf x
51
52 #define MAX_PIPES 4
53 //#define PIPE_BUFLEN 4096
54
55 typedef struct {
56 int used;
57 int id;
58 int fd;
59 int pid;
60 int stopped;
61 EModel *notify;
62 XtInputId input;
63 } GPipe;
64
65 static GPipe Pipes[MAX_PIPES] = {
66 { 0 }, { 0 }, { 0 }, { 0 }
67 };
68
69 #define sfFocus 1
70
71 static long MouseAutoDelay = 40;
72 static long MouseAutoRepeat = 200;
73 static long MouseMultiClick = 300;
74
75 static Atom WM_DELETE_WINDOW;
76 static Atom XA_CLIPBOARD;
77
78 class GViewPeer {
79 public:
80 Widget ScrollWin;
81 Widget TextWin;
82 Widget SbHorz, SbVert;
83 GC gc[256];
84 XGCValues gcv;
85 // TAttr GCattr;
86 int Visibility;
87
88 GView *View;
89 // int wX, wY;
90 int wW, wH, wState, wRefresh;
91 int cX, cY, cVisible, cStart, cEnd;
92 int sbVstart, sbVamount, sbVtotal;
93 int sbHstart, sbHamount, sbHtotal;
94 int VertPos, HorzPos;
95 char *ScreenBuffer;
96
97 GViewPeer(GView *view, int XSize, int YSize);
98 ~GViewPeer();
99
100 int AllocBuffer();
101 void DrawCursor(int Show);
102 void UpdateWindow(int xx, int yy, int ww, int hh);
103
104 int ConPutBox(int X, int Y, int W, int H, PCell Cell);
105 int ConGetBox(int X, int Y, int W, int H, PCell Cell);
106 int ConPutLine(int X, int Y, int W, int H, PCell Cell);
107 int ConSetBox(int X, int Y, int W, int H, TCell Cell);
108 int ConScroll(int Way, int X, int Y, int W, int H, TAttr Fill, int Count);
109
110 int ConSetSize(int X, int Y);
111 int ConQuerySize(int *X, int *Y);
112
113 int ConSetCursorPos(int X, int Y);
114 int ConQueryCursorPos(int *X, int *Y);
115 int ConShowCursor();
116 int ConHideCursor();
117 int ConCursorVisible();
118 int ConSetCursorSize(int Start, int End);
119
120 int QuerySbVPos();
121 int SetSbVPos(int Start, int Amount, int Total);
122 int SetSbHPos(int Start, int Amount, int Total);
123 int ExpandHeight(int DeltaY);
124
125 int UpdateCursor();
126 int PMShowCursor();
127 int PMHideCursor();
128 int PMSetCursorPos();
129 };
130
131 class GFramePeer {
132 public:
133 GFrame *Frame;
134 Widget ShellWin, MainWin, PanedWin, MenuBar;
135
136 GFramePeer(GFrame *frame, int Width, int Height);
137 ~GFramePeer();
138
139 int ConSetTitle(const char *Title, const char *STitle);
140 int ConGetTitle(char *Title, size_t MaxLen, char *STitle, size_t SMaxLen);
141
142 int ConSetSize(int X, int Y);
143 int ConQuerySize(int *X, int *Y);
144 void MapFrame();
145 };
146
147 int ShowVScroll = 1;
148 int ShowHScroll = 0;
149 int ShowMenuBar = 1;
150 int ShowToolBar = 0;
151
152 GFrame *frames = 0;
153 GUI *gui = 0;
154
155 unsigned long HaveGUIDialogs = 0;
156
157 static GView *MouseCapture = 0;
158 static GView *FocusCapture = 0;
159
160 static int cxChar = 8;
161 static int cyChar = 13;
162
163 static XtAppContext AppContext;
164 static Widget TopLevel;
165 static Display *display;
166 static Window root;
167 static int screen;
168 static Colormap colormap;
169 static XColor Colors[16];
170 static XFontStruct *fontStruct;
171
172 TEvent EventBuf = { evNone };
173
174 TEvent NextEvent = { evNone };
175
176 XButtonEvent LastRelease;
177 Widget LPopupMenu = 0;
178
179 static int LastMouseX = -1, LastMouseY = -1;
180
SetColor(int i)181 static void SetColor(int i) {
182 int j, k, z;
183 j = i & 7;
184 k = 65535 - 20480;
185 z = (i > 7) ? (20480) : 0;
186 Colors[i].blue = k * (j & 1) + z;
187 Colors[i].green = k * ((j & 2)?1:0) + z;
188 Colors[i].red = k * ((j & 4)?1:0) + z;
189 Colors[i].flags = DoRed | DoGreen | DoBlue;
190 }
191
InitXColors()192 static int InitXColors() {
193 int i, j;
194 long d = 0, d1;
195 XColor clr;
196 long pix;
197 int num;
198 long d_red, d_green, d_blue;
199 unsigned long u_red, u_green, u_blue;
200
201 for (i = 0; i < 16; i++) {
202 SetColor(i);
203 if (XAllocColor(display, colormap, &Colors[i]) == 0) {
204 SetColor(i);
205 pix = -1;
206 num = DisplayCells(display, DefaultScreen(display));
207 for (j = 0; j < num; j++) {
208 clr.pixel = j;
209 XQueryColor(display, colormap, &clr);
210
211 d_red = clr.red - Colors[i].red;
212 d_green = clr.green - Colors[i].green;
213 d_blue = clr.blue - Colors[i].blue;
214
215 //fprintf(stderr, "%d:%d dr:%d, dg:%d, db:%d\n", i, j, d_red, d_green, d_blue);
216
217 u_red = d_red / 10 * d_red;
218 u_green = d_green / 10 * d_green;
219 u_blue = d_blue / 10 * d_blue;
220
221 //fprintf(stderr, "%d:%d dr:%u, dg:%u, db:%u\n", i, j, u_red, u_green, u_blue);
222
223 d1 = u_red + u_blue + u_green;
224
225 if (d1 < 0)
226 d1 = -d1;
227 if (pix == -1 || d1 < d) {
228 pix = j;
229 d = d1;
230 }
231 }
232 if (pix == -1) {
233 fprintf(stderr, "Color search failed for #%04X%04X%04X\n",
234 Colors[i].red,
235 Colors[i].green,
236 Colors[i].blue);
237 }
238 clr.pixel = pix;
239 XQueryColor(display, colormap, &clr);
240 Colors[i] = clr;
241 if (XAllocColor(display, colormap, &Colors[i]) == 0) {
242 fprintf(stderr, "Color alloc failed for #%04X%04X%04X\n",
243 Colors[i].red,
244 Colors[i].green,
245 Colors[i].blue);
246 }
247 }
248 }
249 return 0;
250 }
251
252 // *INDENT-OFF*
253 static const struct {
254 long keysym;
255 long keycode;
256 } key_table[] = {
257 { XK_Escape, kbEsc },
258 { XK_Tab, kbTab },
259 { XK_Return, kbEnter },
260 { XK_Pause, kbPause },
261 { XK_BackSpace, kbBackSp },
262 { XK_Home, kbHome },
263 { XK_Up, kbUp },
264 { XK_Prior, kbPgUp },
265 { XK_Left, kbLeft },
266 { XK_Right, kbRight },
267 { XK_End, kbEnd },
268 { XK_Down, kbDown },
269 { XK_Next, kbPgDn },
270 { XK_Select, kbEnd },
271 { XK_KP_Enter, kbEnter | kfGray },
272 { XK_Insert, kbIns | kfGray },
273 { XK_Delete, kbDel | kfGray },
274 { XK_KP_Add, '+' | kfGray },
275 { XK_KP_Subtract, '-' | kfGray },
276 { XK_KP_Multiply, '*' | kfGray },
277 { XK_KP_Divide, '/' | kfGray },
278 { XK_Num_Lock, kbNumLock },
279 { XK_Caps_Lock, kbCapsLock },
280 { XK_Print, kbPrtScr },
281 { XK_Shift_L, kbShift },
282 { XK_Shift_R, kbShift | kfGray },
283 { XK_Control_L, kbCtrl },
284 { XK_Control_R, kbCtrl | kfGray },
285 { XK_Alt_L, kbAlt },
286 { XK_Alt_R, kbAlt | kfGray },
287 { XK_Meta_L, kbAlt },
288 { XK_Meta_R, kbAlt | kfGray },
289 { XK_F1, kbF1 },
290 { XK_F2, kbF2 },
291 { XK_F3, kbF3 },
292 { XK_F4, kbF4 },
293 { XK_F5, kbF5 },
294 { XK_F6, kbF6 },
295 { XK_F7, kbF7 },
296 { XK_F8, kbF8 },
297 { XK_F9, kbF9 },
298 { XK_F10, kbF10 },
299 { XK_F11, kbF11 },
300 { XK_F12, kbF12 },
301 { XK_KP_0, '0' | kfGray },
302 { XK_KP_1, '1' | kfGray },
303 { XK_KP_2, '2' | kfGray },
304 { XK_KP_3, '3' | kfGray },
305 { XK_KP_4, '4' | kfGray },
306 { XK_KP_5, '5' | kfGray },
307 { XK_KP_6, '6' | kfGray },
308 { XK_KP_7, '7' | kfGray },
309 { XK_KP_8, '8' | kfGray },
310 { XK_KP_9, '9' | kfGray },
311 { XK_KP_Decimal, '.' | kfGray },
312 { 0x1000FF6F, kbDel | kfShift | kfGray },
313 { 0x1000FF70, kbIns | kfCtrl | kfGray },
314 { 0x1000FF71, kbIns | kfShift | kfGray },
315 { 0x1000FF72, kbIns | kfGray },
316 { 0x1000FF73, kbDel | kfGray },
317 { 0x1000FF74, kbTab | kfShift },
318 { 0x1000FF75, kbTab | kfShift },
319 { 0, 0 }
320 };
321 // *INDENT-ON*
322
ConvertKeyToEvent(KeySym key,KeySym key1,char * keyname,int etype,int state,TEvent * Event)323 static void ConvertKeyToEvent(KeySym key, KeySym key1, char *keyname, int etype, int state, TEvent *Event) {
324 unsigned int myState = 0;
325 int k;
326
327
328 DEBUG(("key: \n"));
329 Event->What = evNone;
330
331 switch (etype) {
332 case KeyPress: Event->What = evKeyDown; break;
333 case KeyRelease: Event->What = evKeyUp; break;
334 }
335
336 if (state & ShiftMask) myState |= kfShift;
337 if (state & ControlMask) myState |= kfCtrl;
338 if (state & Mod1Mask) myState |= kfAlt;
339 if (state & Mod2Mask) myState |= kfAlt;
340 if (state & Mod3Mask) myState |= kfAlt;
341 if (state & Mod4Mask) myState |= kfAlt;
342
343 DEBUG(("key: %d ; %d ; %d\n", key, key1, state));
344 if (key < 256) {
345 if (myState == kfShift) myState = 0;
346 if (myState & kfCtrl) {
347 if (((key >= 'A') && (key < 'A' + 32)) ||
348 ((key >= 'a') && (key < 'a' + 32)))
349 key &= 0x1F;
350 }
351 if (myState & kfAlt) {
352 if (((key >= 'A') && (key <= 'Z')) ||
353 ((key >= 'a') && (key <= 'z')))
354 key &= ~0x20;
355 }
356 Event->Key.Code = key | myState;
357 return;
358 } else {
359 for (size_t i = 0; i < FTE_ARRAY_SIZE(key_table); ++i) {
360 if (key1 == key_table[i].keysym) {
361 k = key_table[i].keycode;
362 if (k < 256)
363 if (myState == kfShift) myState = 0;
364 Event->Key.Code = k | myState;
365 return;
366 }
367 }
368 }
369 DEBUG(("Unknown key: %ld %s %d %d\n", key, keyname, etype, state));
370 Event->What = evNone;
371 }
372
373
374 static TEvent LastMouseEvent = { evNone };
375
376 #define TM_DIFF(x,y) ((long)(((long)(x) < (long)(y)) ? ((long)(y) - (long)(x)) : ((long)(x) - (long)(y))))
377
ConvertClickToEvent(int type,int xx,int yy,int button,int state,TEvent * Event,Time time)378 static void ConvertClickToEvent(int type, int xx, int yy, int button, int state, TEvent *Event, Time time) {
379 unsigned int myState = 0;
380 static unsigned long LastClickTime = 0;
381 static unsigned long LastClickCount = 0;
382 static unsigned long LastClick = 0;
383 unsigned long CurTime = time;
384
385 if (type == MotionNotify) Event->What = evMouseMove;
386 else if (type == ButtonPress) Event->What = evMouseDown;
387 else Event->What = evMouseUp;
388 Event->Mouse.X = xx / cxChar;
389 Event->Mouse.Y = yy / cyChar;
390 if (Event->What == evMouseMove)
391 if (LastMouseX == Event->Mouse.X &&
392 LastMouseY == Event->Mouse.Y)
393 {
394 Event->What = evNone;
395 return;
396 }
397 LastMouseX = Event->Mouse.X;
398 LastMouseY = Event->Mouse.Y;
399 Event->Mouse.Buttons = 0;
400 if (type == MotionNotify) {
401 if (state & Button1Mask) Event->Mouse.Buttons |= 1;
402 if (state & Button2Mask) Event->Mouse.Buttons |= 4;
403 if (state & Button3Mask) Event->Mouse.Buttons |= 2;
404 } else {
405 switch (button) {
406 case Button1: Event->Mouse.Buttons |= 1; break;
407 case Button2: Event->Mouse.Buttons |= 4; break;
408 case Button3: Event->Mouse.Buttons |= 2; break;
409 }
410 }
411 Event->Mouse.Count = 1;
412 if (state & ShiftMask) myState |= kfShift;
413 if (state & ControlMask) myState |= kfCtrl;
414 if (state & Mod1Mask) myState |= kfAlt;
415 if (state & Mod2Mask) myState |= kfAlt;
416 if (state & Mod3Mask) myState |= kfAlt;
417 if (state & Mod4Mask) myState |= kfAlt;
418 Event->Mouse.KeyMask = myState;
419
420 if (Event->What == evMouseDown) {
421 if (LastClickCount) {
422 if (LastClick == Event->Mouse.Buttons) {
423 if (TM_DIFF(CurTime, LastClickTime) <= MouseMultiClick) {
424 Event->Mouse.Count = ++LastClickCount;
425 } else {
426 LastClickCount = 0;
427 }
428 } else {
429 LastClick = 0;
430 LastClickCount = 0;
431 LastClickTime = 0;
432 }
433 }
434
435 LastClick = Event->Mouse.Buttons;
436 if (LastClickCount == 0)
437 LastClickCount = 1;
438 LastClickTime = CurTime;
439 }
440 /* if (Event->What == evMouseMove) {
441 LastClick = 0;
442 LastClickCount = 0;
443 LastClickTime = 0;
444 }
445 */
446 DEBUG(("Mouse: %d %d %d\n", Event->What, Event->Mouse.X, Event->Mouse.Y));
447 LastMouseEvent = *Event;
448 }
449
ProcessXEvents(XEvent * event,TEvent * Event,GViewPeer * Peer)450 static void ProcessXEvents(XEvent *event, TEvent *Event, GViewPeer *Peer) {
451 XAnyEvent *anyEvent = (XAnyEvent *) event;
452 XExposeEvent *exposeEvent = (XExposeEvent *) event;
453 XButtonEvent *buttonEvent = (XButtonEvent *) event;
454 XKeyEvent *keyEvent = (XKeyEvent *) event;
455 XKeyEvent keyEvent1;
456 XConfigureEvent *configureEvent = (XConfigureEvent *) event;
457 XGraphicsExposeEvent *gexposeEvent = (XGraphicsExposeEvent *) event;
458 XMotionEvent *motionEvent = (XMotionEvent *) event;
459 KeySym key, key1;
460 int state;
461 char keyName[32];
462 char keyName1[32];
463 static int hasConfig = 0;
464
465 Event->What = evNone;
466 Event->Msg.View = Peer->View;
467
468 switch (event->type) {
469 case ButtonRelease:
470 case ButtonPress:
471 LastRelease = *buttonEvent;
472 ConvertClickToEvent(event->type, buttonEvent->x, buttonEvent->y, buttonEvent->button, buttonEvent->state, Event, motionEvent->time);
473 break;
474 case KeyPress:
475 case KeyRelease:
476 state = keyEvent->state;
477
478 keyEvent1 = *keyEvent;
479 keyEvent1.state &= ~(ShiftMask | ControlMask | Mod1Mask | Mod2Mask | Mod3Mask | Mod4Mask);
480
481 XLookupString(keyEvent, keyName, sizeof(keyName), &key, 0);
482 XLookupString(&keyEvent1, keyName1, sizeof(keyName1), &key1, 0);
483 //key1 = XLookupKeysym(keyEvent, 0);
484 ConvertKeyToEvent(key, key1, keyName, event->type, state, Event);
485 break;
486 case MotionNotify:
487 ConvertClickToEvent(event->type, motionEvent->x, motionEvent->y, 0, motionEvent->state, Event, motionEvent->time);
488 break;
489 }
490 }
491
CloseWindow(Widget w,void * framev,XEvent * event,Boolean * cont)492 static void CloseWindow(Widget w, void *framev, XEvent *event, Boolean *cont)
493 {
494 GFramePeer *frame = (GFramePeer*)framev;
495 if (event->type != ClientMessage ||
496 ((XClientMessageEvent *)event)->data.l[0] != WM_DELETE_WINDOW)
497 return;
498
499 NextEvent.What = evCommand;
500 NextEvent.Msg.Command = cmClose;
501 *cont = False;
502 }
503
MainCallback(Widget w,void * itemv,XtPointer callData)504 static void MainCallback (Widget w, void* itemv, XtPointer callData)
505 {
506 mItem *item = (mItem*) itemv;
507 DEBUG(("Main: %d\n", item->Cmd));
508 NextEvent.What = evCommand;
509 NextEvent.Msg.Command = item->Cmd;
510 }
511
PopupCallback(Widget w,void * itemv,XtPointer callData)512 static void PopupCallback (Widget w, void* itemv, XtPointer callData)
513 {
514 mItem *item = (mItem*) itemv;
515 DEBUG(("Popup: %d\n", item->Cmd));
516 NextEvent.What = evCommand;
517 NextEvent.Msg.Command = item->Cmd;
518 }
519
MenuPopdownCb(Widget w,void * itemv,XtPointer callData)520 static void MenuPopdownCb (Widget w, void* itemv, XtPointer callData)
521 {
522 mItem *item = (mItem*) itemv;
523 DEBUG(("Popdown: %d\n", item->Cmd));
524 if (LPopupMenu != 0) {
525 XtDestroyWidget(LPopupMenu);
526 LPopupMenu = 0;
527 }
528 }
529
InputWindow(Widget w,void * PeerV,XEvent * event,Boolean * cont)530 static void InputWindow(Widget w, void *PeerV, XEvent *event, Boolean *cont)
531 {
532 GViewPeer *Peer = (GViewPeer*)PeerV;
533
534 DEBUG(("Input\n"));
535 if (!Peer->View->IsActive())
536 Peer->View->Parent->SelectView(Peer->View);
537 NextEvent.Msg.View = Peer->View;
538 ProcessXEvents(event, &NextEvent, Peer);
539 *cont = False;
540 }
541
VisibilityCb(Widget w,void * peerv,XEvent * event,Boolean * cont)542 static void VisibilityCb(Widget w, void* peerv, XEvent *event, Boolean *cont)
543 {
544 GViewPeer *peer = (GViewPeer*)peerv;
545
546 if (event->type != VisibilityNotify)
547 return;
548
549 peer->Visibility = event->xvisibility.state;
550 DEBUG(("Visibility %d\n", peer->Visibility));
551
552 /*
553 * When we do an XCopyArea(), and the window is partially obscured, we want
554 * to receive an event to tell us whether it worked or not.
555 */
556 /*XSetGraphicsExposures(display, gui.text_gc,
557 gui.visibility != VisibilityUnobscured);*/
558 *cont = True;
559 }
560
ConfigureWindow(Widget w,void * PeerV,XEvent * event,Boolean * cont)561 static void ConfigureWindow(Widget w, void *PeerV, XEvent *event, Boolean *cont)
562 {
563 GViewPeer *Peer = (GViewPeer*)PeerV;
564 XConfigureEvent *confEvent = (XConfigureEvent*)event;
565 int X, Y;
566
567 DEBUG(("Configure\n"));
568 X = confEvent->width / cxChar;
569 Y = confEvent->height / cyChar;
570 DEBUG(("!! Resize %d, %d\n", X, Y));
571 if (X > 0 && Y > 0) {
572 Peer->ConSetSize(X, Y);
573 NextEvent.What = evCommand;
574 NextEvent.Msg.Command = cmResize;
575 }
576 DEBUG(("!! resize done\n"));
577 *cont = True;
578 }
579
ExposeWindow(Widget w,void * PeerV,void * CallV)580 static void ExposeWindow(Widget w, void* PeerV, void* CallV)
581 {
582 GViewPeer *Peer = (GViewPeer*)PeerV;
583 XmDrawingAreaCallbackStruct *Call = (XmDrawingAreaCallbackStruct*)CallV;
584 XExposeEvent *exposeEvent = (XExposeEvent *) Call->event;
585
586 DEBUG(("Expose\n"));
587 // if (!XtIsManaged(w)) return
588 Peer->UpdateWindow(exposeEvent->x,
589 exposeEvent->y,
590 exposeEvent->width,
591 exposeEvent->height);
592 DEBUG(("! Expose done\n"));
593 }
594
595
VertValueChanged(Widget w,void * PeerV,void * CallV)596 static void VertValueChanged(Widget w, void* PeerV, void* CallV)
597 {
598 GViewPeer *Peer = (GViewPeer*)PeerV;
599 XmScrollBarCallbackStruct *Call = (XmScrollBarCallbackStruct*)CallV;
600
601 if (!Peer->View->IsActive())
602 Peer->View->Parent->SelectView(Peer->View);
603 if (Peer->VertPos != Call->value) {
604 NextEvent.What = evCommand;
605 NextEvent.Msg.View = Peer->View;
606 NextEvent.Msg.Command = cmVScrollMove;
607 NextEvent.Msg.Param1 = Call->value;
608 DEBUG(("Vert: %d\n", Call->value));
609 Peer->VertPos = Call->value;
610 }
611 }
612
613 //void HorzValueChanged(Widget w, GViewPeer *Peer, XmScrollBarCallbackStruct *Call)
HorzValueChanged(Widget w,void * PeerV,void * CallV)614 void HorzValueChanged(Widget w, void* PeerV, void* CallV)
615 {
616 GViewPeer *Peer = (GViewPeer*)PeerV;
617 XmScrollBarCallbackStruct *Call = (XmScrollBarCallbackStruct*) CallV;
618
619 if (!Peer->View->IsActive())
620 Peer->View->Parent->SelectView(Peer->View);
621 if (Call->value != Peer->HorzPos) {
622 NextEvent.What = evCommand;
623 NextEvent.Msg.View = Peer->View;
624 NextEvent.Msg.Command = cmHScrollMove;
625 NextEvent.Msg.Param1 = Call->value;
626 DEBUG(("Horz: %d\n", Call->value));
627 Peer->HorzPos = Call->value;
628 }
629 }
630
631 ///////////////////////////////////////////////////////////////////////////
632
GViewPeer(GView * view,int XSize,int YSize)633 GViewPeer::GViewPeer(GView *view, int XSize, int YSize) :
634 Visibility(VisibilityFullyObscured),
635 View(view),
636 //wX(0),
637 //wY(0),
638 //wW(XSize),
639 //wH(YSize),
640 wW(80),
641 wH(40),
642 wState(0),
643 wRefresh(0),
644 cX(-1),
645 cY(-1),
646 cVisible(1),
647 cStart(0), // %
648 cEnd(100),
649 sbVstart(0),
650 sbVamount(0),
651 sbVtotal(0),
652 sbHstart(0),
653 sbHamount(0),
654 sbHtotal(0),
655 VertPos(-1),
656 HorzPos(-1),
657 ScreenBuffer(0)
658 {
659 for (int jj = 0; jj < 256; jj++)
660 gc[jj] = 0;
661
662 AllocBuffer();
663
664 ScrollWin = XtVaCreateWidget("ScrollWin",
665 xmScrolledWindowWidgetClass, frames->Peer->PanedWin,
666 XmNmarginHeight, 0,
667 XmNmarginWidth, 0,
668 XmNspacing, 0,
669 NULL);
670
671 TextWin = XtVaCreateManagedWidget ("TextWin",
672 xmDrawingAreaWidgetClass, ScrollWin,
673 XmNmarginHeight, 0,
674 XmNmarginWidth, 0,
675 XmNhighlightThickness, 0,
676 XmNshadowThickness, 0,
677 XmNwidthInc, cxChar,
678 XmNheightInc, cyChar,
679 XmNwidth, cxChar * 80,
680 XmNheight, cyChar * 30,
681 NULL);
682
683 // XSetWindowColormap(display, XtWindow(TextWin), colormap);
684
685 XtVaSetValues (ScrollWin,
686 XmNworkWindow, TextWin,
687 NULL);
688
689 SbVert = XtVaCreateManagedWidget("VScrollBar",
690 xmScrollBarWidgetClass, ScrollWin,
691 XmNmarginHeight, 0,
692 XmNmarginWidth, 0,
693 XmNwidth, 20,
694 NULL);
695
696 SbHorz = XtVaCreateManagedWidget("HScrollBar",
697 xmScrollBarWidgetClass, ScrollWin,
698 XmNmarginHeight, 0,
699 XmNmarginWidth, 0,
700 XmNorientation, XmHORIZONTAL,
701 NULL);
702
703 XtVaSetValues(ScrollWin,
704 XmNhorizontalScrollBar, SbHorz,
705 XmNverticalScrollBar, SbVert,
706 NULL);
707
708 XtManageChild(ScrollWin);
709
710 gcv.foreground = Colors[0].pixel;
711 gcv.background = Colors[0].pixel;
712 gcv.font = fontStruct->fid;
713 gc[0] = XtGetGC(TextWin,
714 GCForeground | GCBackground | GCFont, &gcv);
715 // GCattr = 0x07;
716
717
718 /* XtAddCallback(TextWin, XmNinputCallback, InputWindow, this);*/
719
720 XtAddEventHandler(TextWin,
721 KeyPressMask | KeyReleaseMask |
722 ButtonPressMask | ButtonReleaseMask | ButtonMotionMask,
723 False, InputWindow, this);
724 XtAddEventHandler(TextWin,
725 VisibilityChangeMask,
726 False, VisibilityCb,
727 this);
728 XtAddEventHandler(TextWin,
729 StructureNotifyMask,
730 False, ConfigureWindow, this);
731 //XtAddCallback(TextWin, XmNresizeCallback, ResizeWindow, this);
732 XtAddCallback(TextWin, XmNexposeCallback, ExposeWindow, this);
733
734 XtAddCallback(SbHorz, XmNvalueChangedCallback, HorzValueChanged, this);
735 XtAddCallback(SbHorz, XmNdragCallback, HorzValueChanged, this);
736 XtAddCallback(SbHorz, XmNincrementCallback, HorzValueChanged, this);
737 XtAddCallback(SbHorz, XmNdecrementCallback, HorzValueChanged, this);
738 XtAddCallback(SbHorz, XmNpageIncrementCallback, HorzValueChanged, this);
739 XtAddCallback(SbHorz, XmNpageDecrementCallback, HorzValueChanged, this);
740 XtAddCallback(SbHorz, XmNtoTopCallback, HorzValueChanged, this);
741 XtAddCallback(SbHorz, XmNtoBottomCallback, HorzValueChanged, this);
742
743 XtAddCallback(SbVert, XmNvalueChangedCallback, VertValueChanged, this);
744 XtAddCallback(SbVert, XmNdragCallback, VertValueChanged, this);
745 XtAddCallback(SbVert, XmNincrementCallback, VertValueChanged, this);
746 XtAddCallback(SbVert, XmNdecrementCallback, VertValueChanged, this);
747 XtAddCallback(SbVert, XmNpageIncrementCallback, VertValueChanged, this);
748 XtAddCallback(SbVert, XmNpageDecrementCallback, VertValueChanged, this);
749 XtAddCallback(SbVert, XmNtoTopCallback, VertValueChanged, this);
750 XtAddCallback(SbVert, XmNtoBottomCallback, VertValueChanged, this);
751 }
752
~GViewPeer()753 GViewPeer::~GViewPeer() {
754 // Widget destroyed recursively
755 // from master shell widget
756 free(ScreenBuffer);
757 ScreenBuffer = 0;
758 }
759
AllocBuffer()760 int GViewPeer::AllocBuffer() {
761 int i;
762 char *p;
763 /* FIXME */
764 if (!(ScreenBuffer = (char *)malloc(wW * wH * sizeof(TCell))))
765 return 0;
766 for (i = 0, p = ScreenBuffer; i < wW * wH; i++) {
767 *p++ = 32;
768 *p++ = 0x07;
769 }
770
771 return 1;
772 }
773
774 #define InRange(x,a,y) (((x) <= (a)) && ((a) < (y)))
775 #define CursorXYPos(x,y) (ScreenBuffer + ((x) + ((y) * wW)) * 2)
776
DrawCursor(int Show)777 void GViewPeer::DrawCursor(int Show) {
778 if (!(View && View->Parent))
779 return;
780
781 if (!(wState & sfFocus))
782 Show = 0;
783
784 if (Visibility == VisibilityFullyObscured)
785 return;
786
787 if (cX >= wW || cY >= wW ||
788 cX + 1 > wW || cY + 1 > wH)
789 {
790 //fprintf(stderr, "%d %d %d %d %d %d\n", ScreenCols, ScreenRows, X, Y, W, H);
791 return;
792 }
793
794 DEBUG(("DrawCursor %d %d\n", cX, cY));
795 // if (!XtIsManaged(TextWin)) return ;
796
797 if (cVisible && cX >= 0 && cY >= 0) {
798 char *p = CursorXYPos(cX, cY), attr;
799 attr = p[1];
800 /*if (Show) attr = ((((attr << 4) & 0xF0)) | (attr >> 4)) ^ 0x77;*/
801 if (Show) attr = (attr ^ 0x77);
802
803 if (gc[attr] == 0) {
804 gcv.foreground = Colors[attr & 0xF].pixel;
805 gcv.background = Colors[(attr >> 4) & 0xF].pixel;
806 gcv.font = fontStruct->fid;
807 gc[attr] = XtGetGC(TextWin,
808 GCForeground | GCBackground | GCFont, &gcv);
809 }
810 XDrawImageString(display, XtWindow(TextWin), gc[attr],
811 cX * cxChar,
812 fontStruct->max_bounds.ascent + cY * cyChar,
813 (const char*)p, 1);
814 }
815 }
816
ConPutBox(int X,int Y,int W,int H,PCell Cell)817 int GViewPeer::ConPutBox(int X, int Y, int W, int H, PCell Cell) {
818 int i;
819 char temp[256], attr;
820 char *p, *ps, *c, *ops;
821 int len, x, l, ox, olen, skip;
822
823 if (!(View && View->Parent && gc))
824 return 1;
825
826 if (Visibility == VisibilityFullyObscured)
827 return 0;
828
829 if (X >= wW || Y >= wH ||
830 X + W > wW || Y + H > wH)
831 {
832 //fprintf(stderr, "%d %d %d %d %d %d\n", ScreenCols, ScreenRows, X, Y, W, H);
833 return 0;
834 }
835
836 DEBUG(("PutBox %d | %d %d %d %d | %d %d\n", wRefresh, X, Y, W, H, wW, wH));
837 for (i = 0; i < H; i++) {
838 len = W;
839 p = CursorXYPos(X, Y + i);
840 ps = (char *) Cell;
841 x = X;
842 while (len > 0) {
843 if (!wRefresh) {
844 c = CursorXYPos(x, Y + i);
845 skip = 0;
846 ops = ps;
847 ox = x;
848 olen = len;
849 while ((len > 0) && (*(unsigned short *) c == *(unsigned short *)ps)) x++, len--, ps+=2, c+=2, skip++;
850 if (len <= 0) break;
851 if (skip <= 4) {
852 ps = ops;
853 x = ox;
854 len = olen;
855 }
856 }
857 p = ps;
858 l = 1;
859 temp[0] = *ps++; attr = *ps++;
860 while ((l < len) && ((unsigned char) (ps[1]) == attr)) {
861 temp[l++] = *ps++;
862 ps++;
863 }
864
865 if (gc[attr] == 0) {
866 gcv.foreground = Colors[attr & 0xF].pixel;
867 gcv.background = Colors[(attr >> 4) & 0xF].pixel;
868 gcv.font = fontStruct->fid;
869 gc[attr] = XtGetGC(TextWin,
870 GCForeground | GCBackground | GCFont, &gcv);
871 }
872
873 XDrawImageString(display,
874 XtWindow(TextWin), gc[attr],
875 x * cxChar,
876 fontStruct->max_bounds.ascent + (Y + i) * cyChar,
877 temp, l);
878 x += l;
879 len -= l;
880 }
881 p = CursorXYPos(X, Y + i);
882 memmove(p, Cell, W * sizeof(TCell));
883 if (i + Y == cY)
884 DrawCursor(1);
885 Cell += W;
886 }
887 DEBUG(("done putbox\n"));
888
889 return 1;
890 }
891
UpdateWindow(int xx,int yy,int ww,int hh)892 void GViewPeer::UpdateWindow(int xx, int yy, int ww, int hh) {
893 PCell p;
894 int i;
895
896 ww /= cxChar; ww += 2;
897 hh /= cyChar; hh += 2;
898 xx /= cxChar;
899 yy /= cyChar;
900 if (xx + ww > wW) ww = wW - xx;
901 if (yy + hh > wH) hh = wH - yy;
902 wRefresh = 1;
903 p = (PCell) CursorXYPos(xx, yy);
904
905 for (i = 0; i < hh; i++) {
906 ConPutBox(xx, yy + i, ww, 1, p);
907 p += wW;
908 }
909
910 XFlush(display);
911 wRefresh = 0;
912 }
913
ConGetBox(int X,int Y,int W,int H,PCell Cell)914 int GViewPeer::ConGetBox(int X, int Y, int W, int H, PCell Cell) {
915 for (int i = 0; i < H; i++) {
916 memcpy(Cell, CursorXYPos(X, Y + i), 2 * W);
917 Cell += W;
918 }
919
920 return 1;
921 }
922
ConPutLine(int X,int Y,int W,int H,PCell Cell)923 int GViewPeer::ConPutLine(int X, int Y, int W, int H, PCell Cell) {
924 for (int i = 0; i < H; i++)
925 if (!ConPutBox(X, Y + i, W, 1, Cell))
926 return 0;
927
928 return 1;
929 }
930
ConSetBox(int X,int Y,int W,int H,TCell Cell)931 int GViewPeer::ConSetBox(int X, int Y, int W, int H, TCell Cell) {
932 TDrawBuffer B;
933
934 for (int i = 0; i < W; i++)
935 B[i] = Cell;
936 ConPutLine(X, Y, W, H, B);
937
938 return 1;
939 }
940
ConScroll(int Way,int X,int Y,int W,int H,TAttr Fill,int Count)941 int GViewPeer::ConScroll(int Way, int X, int Y, int W, int H, TAttr Fill, int Count) {
942 TCell Cell;
943 int l;
944
945 MoveCh(&Cell, ' ', Fill, 1);
946 DrawCursor(0);
947 if (Way == csUp) {
948 XCopyArea(display, XtWindow(TextWin), XtWindow(TextWin), gc[0],
949 X * cxChar,
950 (Y + Count) * cyChar,
951 W * cxChar,
952 (H - Count) * cyChar,
953 X * cxChar,
954 Y * cyChar
955 );
956 for (l = 0; l < H - Count; l++)
957 memcpy(CursorXYPos(X, Y + l), CursorXYPos(X, Y + l + Count), 2 * W);
958
959 if (!ConSetBox(X, Y + H - Count, W, Count, Cell))
960 return 0;
961 } else if (Way == csDown) {
962 XCopyArea(display, XtWindow(TextWin), XtWindow(TextWin), gc[0],
963 X * cxChar,
964 Y * cyChar,
965 W * cxChar,
966 (H - Count) * cyChar,
967 X * cxChar,
968 (Y + Count)* cyChar
969 );
970 for (l = H - 1; l >= Count; l--)
971 memcpy(CursorXYPos(X, Y + l), CursorXYPos(X, Y + l - Count), 2 * W);
972
973 if (!ConSetBox(X, Y, W, Count, Cell))
974 return 0;
975 }
976 DrawCursor(1);
977
978 return 0;
979 }
980
ConSetSize(int X,int Y)981 int GViewPeer::ConSetSize(int X, int Y) {
982 char *NewBuffer;
983 char *p;
984 int i;
985 int MX, MY;
986
987 p = NewBuffer = (char *) malloc(X * Y * sizeof(TCell));
988 if (NewBuffer == NULL)
989 return 0;
990 for (int i = 0; i < X * Y; i++) {
991 *p++ = ' ';
992 *p++ = 0x07;
993 }
994 if (ScreenBuffer) {
995 MX = wW; if (X < MX) MX = X;
996 MY = wH; if (Y < MY) MY = Y;
997 if (X < MX) MX = X;
998 p = NewBuffer;
999 for (i = 0; i < MY; i++) {
1000 memcpy(p, CursorXYPos(0, i), MX * sizeof(TCell));
1001 p += X * 2;
1002 }
1003 free(ScreenBuffer);
1004 }
1005 ScreenBuffer = NewBuffer;
1006 wW = X;
1007 wH = Y;
1008 wRefresh = 1;
1009 View->Resize(wW, wH);
1010 ConPutBox(0, 0, wW, wH, (PCell) ScreenBuffer);
1011 wRefresh = 0;
1012 // if (Refresh == 0)
1013 // XResizeWindow(display, win, ScreenCols * cxChar, ScreenRows * cyChar);
1014
1015 return 1;
1016 }
1017
ConQuerySize(int * X,int * Y)1018 int GViewPeer::ConQuerySize(int *X, int *Y) {
1019 //printf("3CONQUERYSIZE %d %d\n", wW, wH);
1020 if (X) *X = wW;
1021 if (Y) *Y = wH;
1022
1023 return 1;
1024 }
1025
ConSetCursorPos(int X,int Y)1026 int GViewPeer::ConSetCursorPos(int X, int Y) {
1027 if (X < 0) X = 0;
1028 else if (X >= wW) X = wW - 1;
1029
1030 if (Y < 0) Y = 0;
1031 else if (Y >= wH) Y = wH - 1;
1032 DrawCursor(0);
1033 cX = X;
1034 cY = Y;
1035 DrawCursor(1);
1036
1037 return 1;
1038 }
1039
ConQueryCursorPos(int * X,int * Y)1040 int GViewPeer::ConQueryCursorPos(int *X, int *Y) {
1041 if (X) *X = cX;
1042 if (Y) *Y = cY;
1043
1044 return 1;
1045 }
1046
ConShowCursor()1047 int GViewPeer::ConShowCursor() {
1048 cVisible = 1;
1049 // DrawCursor(1);
1050
1051 return 1;
1052 }
1053
ConHideCursor()1054 int GViewPeer::ConHideCursor() {
1055 cVisible = 0;
1056 // DrawCursor(0);
1057
1058 return 1;
1059 }
1060
ConCursorVisible()1061 int GViewPeer::ConCursorVisible() {
1062 return cVisible;
1063 }
1064
ConSetCursorSize(int Start,int End)1065 int GViewPeer::ConSetCursorSize(int Start, int End) {
1066 cStart = Start;
1067 cEnd = End;
1068
1069 if (wState & sfFocus)
1070 return 1; //PMSetCursorSize(Start, End);
1071
1072 return 1;
1073 }
1074
ExpandHeight(int DeltaY)1075 int GViewPeer::ExpandHeight(int DeltaY) {
1076 return 0;
1077 }
1078
QuerySbVPos()1079 int GViewPeer::QuerySbVPos() {
1080 return sbVstart;
1081 }
1082
SetSbVPos(int Start,int Amount,int Total)1083 int GViewPeer::SetSbVPos(int Start, int Amount, int Total) {
1084 if (sbVstart != Start || sbVamount != Amount || sbVtotal != Total) {
1085 sbVstart = Start;
1086 sbVamount = Amount;
1087 sbVtotal = Total;
1088
1089 if (!View->Parent)
1090 return 0;
1091
1092 if (Amount < 1 || Start + Amount > Total) {
1093 XtVaSetValues(SbVert,
1094 XmNmaximum, 1,
1095 XmNminimum, 0,
1096 XmNpageIncrement, 1,
1097 XmNsliderSize, 1,
1098 XmNvalue, 0,
1099 NULL);
1100 } else {
1101 XtVaSetValues(SbVert,
1102 XmNmaximum, Total,
1103 XmNminimum, 0,
1104 XmNpageIncrement, ((Amount > 1) ? Amount : 1),
1105 XmNsliderSize, Amount,
1106 XmNvalue, Start,
1107 NULL);
1108 }
1109 }
1110
1111 return 1;
1112 }
1113
SetSbHPos(int Start,int Amount,int Total)1114 int GViewPeer::SetSbHPos(int Start, int Amount, int Total) {
1115 if (sbHstart != Start || sbHamount != Amount || sbHtotal != Total) {
1116 sbHstart = Start;
1117 sbHamount = Amount;
1118 sbHtotal = Total;
1119
1120 if (!View->Parent)
1121 return 0;
1122
1123 if (Amount < 1 || Start + Amount > Total)
1124 XtVaSetValues(SbHorz,
1125 XmNmaximum, 1,
1126 XmNminimum, 0,
1127 XmNpageIncrement, 1,
1128 XmNsliderSize, 1,
1129 XmNvalue, 0,
1130 NULL);
1131 else
1132 XtVaSetValues(SbHorz,
1133 XmNmaximum, Total,
1134 XmNminimum, 0,
1135 XmNpageIncrement, ((Amount > 1) ? Amount : 1),
1136 XmNsliderSize, Amount,
1137 XmNvalue, Start,
1138 NULL);
1139 }
1140
1141 return 1;
1142 }
1143
UpdateCursor()1144 int GViewPeer::UpdateCursor() {
1145 ConSetCursorPos(cX, cY);
1146 ConSetCursorSize(cStart, cEnd);
1147 if (cVisible)
1148 ConShowCursor();
1149 else
1150 ConHideCursor();
1151
1152 return 1;
1153 }
1154
PMShowCursor()1155 int GViewPeer::PMShowCursor() {
1156 // if (wState & sfFocus)
1157 // WinShowCursor(hwndView, TRUE);
1158 return 1;
1159 }
1160
PMHideCursor()1161 int GViewPeer::PMHideCursor() {
1162 // if (wState & sfFocus)
1163 // WinShowCursor(hwndView, FALSE);
1164 return 1;
1165 }
1166
PMSetCursorPos()1167 int GViewPeer::PMSetCursorPos() {
1168 // if (wState & sfFocus) {
1169 // WinDestroyCursor(hwndView);
1170 // WinCreateCursor(hwndView,
1171 // cxChar * cX, cyChar * (wH - cY - 1), cxChar, 2,
1172 // CURSOR_TYPE,
1173 // NULL);
1174 // WinShowCursor(hwndView, TRUE);
1175 // }
1176 return 1;
1177 }
1178
1179 ///////////////////////////////////////////////////////////////////////////
1180
GView(GFrame * parent,int XSize,int YSize)1181 GView::GView(GFrame *parent, int XSize, int YSize) :
1182 Parent(parent),
1183 Next(0),
1184 Prev(0),
1185 Peer(new GViewPeer(this, XSize, YSize))
1186 {
1187 if (Parent)
1188 Parent->AddView(this);
1189 }
1190
~GView()1191 GView::~GView() {
1192 if (Parent)
1193 Parent->RemoveView(this);
1194 delete Peer;
1195 }
1196
ConClear()1197 int GView::ConClear() {
1198 int W, H;
1199 TDrawBuffer B;
1200
1201 ConQuerySize(&W, &H);
1202 MoveChar(B, 0, W, ' ', 0x07, 1);
1203 ConSetBox(0, 0, W, H, B[0]);
1204
1205 return 1;
1206 }
1207
ConPutBox(int X,int Y,int W,int H,PCell Cell)1208 int GView::ConPutBox(int X, int Y, int W, int H, PCell Cell) {
1209 return Peer->ConPutBox(X, Y, W, H, Cell);
1210 }
1211
ConGetBox(int X,int Y,int W,int H,PCell Cell)1212 int GView::ConGetBox(int X, int Y, int W, int H, PCell Cell) {
1213 return Peer->ConGetBox(X, Y, W, H, Cell);
1214 }
1215
ConPutLine(int X,int Y,int W,int H,PCell Cell)1216 int GView::ConPutLine(int X, int Y, int W, int H, PCell Cell) {
1217 return Peer->ConPutLine(X, Y, W, H, Cell);
1218 }
1219
ConSetBox(int X,int Y,int W,int H,TCell Cell)1220 int GView::ConSetBox(int X, int Y, int W, int H, TCell Cell) {
1221 return Peer->ConSetBox(X, Y, W, H, Cell);
1222 }
1223
ConScroll(int Way,int X,int Y,int W,int H,TAttr Fill,int Count)1224 int GView::ConScroll(int Way, int X, int Y, int W, int H, TAttr Fill, int Count) {
1225 return Peer->ConScroll(Way, X, Y, W, H, Fill, Count);
1226 }
1227
ConSetSize(int X,int Y)1228 int GView::ConSetSize(int X, int Y) {
1229 printf("ConSetSize %d %d\n", X, Y);
1230 if (Peer->ConSetSize(X, Y)) {
1231 // Resize(X, Y);
1232 return 1;
1233 }
1234
1235 return 0;
1236 }
1237
ConQuerySize(int * X,int * Y)1238 int GView::ConQuerySize(int *X, int *Y) {
1239 return Peer->ConQuerySize(X, Y);
1240 }
1241
ConSetCursorPos(int X,int Y)1242 int GView::ConSetCursorPos(int X, int Y) {
1243 return Peer->ConSetCursorPos(X, Y);
1244 }
1245
ConQueryCursorPos(int * X,int * Y)1246 int GView::ConQueryCursorPos(int *X, int *Y) {
1247 return Peer->ConQueryCursorPos(X, Y);
1248 }
1249
ConShowCursor()1250 int GView::ConShowCursor() {
1251 return Peer->ConShowCursor();
1252 }
1253
ConHideCursor()1254 int GView::ConHideCursor() {
1255 return Peer->ConHideCursor();
1256 }
1257
ConCursorVisible()1258 int GView::ConCursorVisible() {
1259 return Peer->ConCursorVisible();
1260 }
1261
ConSetCursorSize(int Start,int End)1262 int GView::ConSetCursorSize(int Start, int End) {
1263 return Peer->ConSetCursorSize(Start, End);
1264 }
1265
QuerySbVPos()1266 int GView::QuerySbVPos() {
1267 return Peer->QuerySbVPos();
1268 }
1269
SetSbVPos(int Start,int Amount,int Total)1270 int GView::SetSbVPos(int Start, int Amount, int Total) {
1271 return Peer->SetSbVPos(Start, Amount, Total);
1272 }
1273
SetSbHPos(int Start,int Amount,int Total)1274 int GView::SetSbHPos(int Start, int Amount, int Total) {
1275 return Peer->SetSbHPos(Start, Amount, Total);
1276 }
1277
ExpandHeight(int DeltaY)1278 int GView::ExpandHeight(int DeltaY) {
1279 return Peer->ExpandHeight(DeltaY);
1280 }
1281
Update()1282 void GView::Update() {
1283 }
1284
Repaint()1285 void GView::Repaint() {
1286 }
1287
HandleEvent(TEvent & Event)1288 void GView::HandleEvent(TEvent &Event) {
1289 }
1290
Resize(int width,int height)1291 void GView::Resize(int width, int height) {
1292 Repaint();
1293 }
1294
EndExec(int NewResult)1295 void GView::EndExec(int NewResult) {
1296 Result = NewResult;
1297 }
1298
Execute()1299 int GView::Execute() {
1300 int SaveRc = Result;
1301 int NewResult;
1302
1303 Result = -2;
1304 while (Result == -2 && frames != 0)
1305 gui->ProcessEvent();
1306 NewResult = Result;
1307 Result = SaveRc;
1308 return NewResult;
1309 }
1310
IsActive()1311 int GView::IsActive() {
1312 return (Parent->Active == this);
1313 }
1314
Activate(int gotfocus)1315 void GView::Activate(int gotfocus) {
1316 if (gotfocus) {
1317 Peer->wState |= sfFocus;
1318 Peer->UpdateCursor();
1319 } else
1320 Peer->wState &= ~sfFocus;
1321
1322 Repaint();
1323 }
1324
CaptureMouse(int grab)1325 int GView::CaptureMouse(int grab) {
1326 if (MouseCapture == 0) {
1327 if (!grab)
1328 return 0;
1329 MouseCapture = this;
1330 } else {
1331 if (grab || MouseCapture != this)
1332 return 0;
1333 MouseCapture = 0;
1334 }
1335
1336 return 1;
1337 }
1338
1339 ///////////////////////////////////////////////////////////////////////////
1340
GFramePeer(GFrame * frame,int Width,int Height)1341 GFramePeer::GFramePeer(GFrame *frame, int Width, int Height) :
1342 MenuBar(0)
1343 {
1344 ShellWin = XtCreatePopupShell("fte", topLevelShellWidgetClass,
1345 TopLevel, NULL, 0);
1346
1347 XtVaSetValues(ShellWin,
1348 XmNwidthInc, cxChar,
1349 XmNheightInc, cyChar,
1350 NULL);
1351
1352 MainWin = XtCreateManagedWidget("Widget", xmMainWindowWidgetClass,
1353 ShellWin, NULL, 0);
1354
1355 PanedWin = XtVaCreateManagedWidget("pane",
1356 xmPanedWindowWidgetClass, MainWin,
1357 XmNmarginHeight, 0,
1358 XmNmarginWidth, 0,
1359 NULL);
1360
1361 XtVaSetValues (MainWin,
1362 XmNworkWindow, PanedWin,
1363 NULL);
1364
1365 if (Width != -1 && Height != -1)
1366 ConSetSize(Width, Height);
1367 }
1368
~GFramePeer()1369 GFramePeer::~GFramePeer() {
1370 // Kill master window - deletes recursively all related widgets
1371 XtDestroyWidget(MenuBar);
1372 XtDestroyWidget(ShellWin);
1373 }
1374
ConSetSize(int X,int Y)1375 int GFramePeer::ConSetSize(int X, int Y) {
1376 printf("SetSIZE %d x %d\n", X, Y);
1377 //return ::ConSetSize(X, Y);
1378 return 0;
1379 }
1380
ConQuerySize(int * X,int * Y)1381 int GFramePeer::ConQuerySize(int *X, int *Y) {
1382 //::ConQuerySize(&fW, &fH);
1383 //if (X) *X = fW;
1384 //if (Y) *Y = fH;
1385 if (X) *X = 80;
1386 if (Y) *Y = 25;
1387
1388 printf("ConQuerySize %d x %d\n", *X, *Y);
1389 return 1;
1390 }
1391
1392
ConSetTitle(const char * Title,const char * STitle)1393 int GFramePeer::ConSetTitle(const char *Title, const char *STitle) {
1394 XSetStandardProperties(display, XtWindow(ShellWin), Title, STitle, 0, NULL, 0, NULL);
1395 return 1;
1396 }
1397
ConGetTitle(char * Title,size_t MaxLen,char * STitle,size_t SMaxLen)1398 int GFramePeer::ConGetTitle(char *Title, size_t MaxLen, char *STitle, size_t SMaxLen) {
1399 *Title = 0;
1400 *STitle = 0;
1401 return 1;
1402 }
1403
MapFrame()1404 void GFramePeer::MapFrame() {
1405 //Parent->UpdateMenu();
1406 XtPopup(ShellWin, XtGrabNone);
1407 XSetWMProtocols(display, XtWindow(ShellWin), &WM_DELETE_WINDOW, 1);
1408 XtInsertEventHandler(ShellWin, NoEventMask, True, CloseWindow, NULL, XtListHead);
1409 }
1410
1411 ///////////////////////////////////////////////////////////////////////////
1412
GFrame(int XSize,int YSize)1413 GFrame::GFrame(int XSize, int YSize) {
1414 Menu = 0;
1415 if (!frames) {
1416 frames = Prev = Next = this;
1417 } else {
1418 Next = frames->Next;
1419 Prev = frames;
1420 frames->Next->Prev = this;
1421 frames->Next = this;
1422 frames = this;
1423 }
1424 Top = Active = 0;
1425 Peer = new GFramePeer(this, XSize, YSize);
1426 }
1427
~GFrame()1428 GFrame::~GFrame() {
1429 delete Peer;
1430 free(Menu);
1431
1432 if (Next == this) {
1433 frames = 0;
1434 // DEBUG(("No more frames\x7\x7\n"));
1435 } else {
1436 Next->Prev = Prev;
1437 Prev->Next = Next;
1438 frames = Next;
1439 }
1440 }
1441
ConSetTitle(const char * Title,const char * STitle)1442 int GFrame::ConSetTitle(const char *Title, const char *STitle) {
1443 return Peer->ConSetTitle(Title, STitle);
1444 }
1445
ConGetTitle(char * Title,size_t MaxLen,char * STitle,size_t SMaxLen)1446 int GFrame::ConGetTitle(char *Title, size_t MaxLen, char *STitle, size_t SMaxLen) {
1447 return Peer->ConGetTitle(Title, MaxLen, STitle, SMaxLen);
1448 }
1449
ConSetSize(int X,int Y)1450 int GFrame::ConSetSize(int X, int Y) {
1451 return Peer->ConSetSize(X, Y);
1452 }
1453
ConQuerySize(int * X,int * Y)1454 int GFrame::ConQuerySize(int *X, int *Y) {
1455 return Peer->ConQuerySize(X, Y);
1456 }
1457
ConSplitView(GView * view,GView * newview)1458 int GFrame::ConSplitView(GView *view, GView *newview) {
1459 int dmy;
1460
1461 newview->Parent = this;
1462 // newview->Peer->wX = 0;
1463 ConQuerySize(&newview->Peer->wW, &dmy);
1464 // newview->Peer->wY = view->Peer->wY + view->Peer->wH / 2;
1465 // newview->Peer->wH = view->Peer->wH - view->Peer->wH / 2;
1466 // view->Peer->wH /= 2;
1467 InsertView(view, newview);
1468 view->ConSetSize(view->Peer->wW, view->Peer->wH);
1469 newview->ConSetSize(newview->Peer->wW, newview->Peer->wH);
1470 return 1;
1471 }
1472
ConCloseView(GView * view)1473 int GFrame::ConCloseView(GView *view) {
1474 return 0;
1475 }
1476
ConResizeView(GView * view,int DeltaY)1477 int GFrame::ConResizeView(GView *view, int DeltaY) {
1478 return 0;
1479 }
1480
AddView(GView * view)1481 int GFrame::AddView(GView *view) {
1482 if (Top != 0)
1483 return ConSplitView(Top, view);
1484
1485 // int W, H;
1486
1487 view->Parent = this;
1488 view->Prev = view->Next = 0;
1489
1490 // view->Peer->wX = 0;
1491 // view->Peer->wY = 0;
1492 // ConQuerySize(&W, &H);
1493 // view->ConSetSize(W, H);
1494 InsertView(Top, view);
1495 return 1;
1496 }
1497
Update()1498 void GFrame::Update() {
1499 UpdateMenu();
1500 for (GView *v = Active; v; v = v->Next) {
1501 v->Update();
1502 if (v->Next == Active)
1503 break;
1504 }
1505 }
1506
UpdateMenu()1507 void GFrame::UpdateMenu() {
1508 }
1509
Repaint()1510 void GFrame::Repaint() {
1511 for (GView* v = Active; v; v = v->Next) {
1512 v->Repaint();
1513 if (v->Next == Active)
1514 break;
1515 }
1516 }
1517
InsertView(GView * Prev,GView * view)1518 void GFrame::InsertView(GView *Prev, GView *view) {
1519 if (!view) return ;
1520 if (Prev) {
1521 view->Prev = Prev;
1522 view->Next = Prev->Next;
1523 Prev->Next = view;
1524 view->Next->Prev = view;
1525 } else {
1526 view->Prev = view->Next = view;
1527 Top = view;
1528 }
1529 if (Active == 0) {
1530 Active = view;
1531 Active->Activate(1);
1532 }
1533 }
1534
RemoveView(GView * view)1535 void GFrame::RemoveView(GView *view) {
1536 if (!view) return ;
1537
1538 if (Active == view)
1539 Active->Activate(0);
1540 if (view->Next == view) {
1541 Top = Active = 0;
1542 delete this;
1543 } else {
1544 view->Next->Prev = view->Prev;
1545 view->Prev->Next = view->Next;
1546
1547 // if (Top == view) {
1548 // Top = view->Next;
1549 // Top->Peer->wY -= view->Peer->wH;
1550 // Top->ConSetSize(Top->Peer->wW, Top->Peer->wH + view->Peer->wH);
1551 // } else {
1552 // view->Prev->ConSetSize(view->Prev->Peer->wW,
1553 // view->Prev->Peer->wH + view->Peer->wH);
1554 // }
1555
1556 if (Active == view) {
1557 Active = view->Prev;
1558 Active->Activate(1);
1559 }
1560 }
1561 }
1562
SelectNext(int back)1563 void GFrame::SelectNext(int back) {
1564 GView *c = Active;
1565
1566 if (c == 0 && Top == 0)
1567 return;
1568
1569 if (c == 0)
1570 c = Active = Top;
1571 else
1572 if (back) {
1573 Active = Active->Prev;
1574 } else {
1575 Active = Active->Next;
1576 }
1577
1578 if (c != Active) {
1579 c->Activate(0);
1580 Active->Activate(1);
1581 }
1582
1583 if (Active)
1584 XtSetKeyboardFocus(Peer->PanedWin, Active->Peer->TextWin);
1585 }
1586
SelectView(GView * view)1587 int GFrame::SelectView(GView *view) {
1588 if (Top == 0)
1589 return 0;
1590
1591 if (FocusCapture != 0 || MouseCapture != 0)
1592 return 0;
1593
1594 if (Active)
1595 Active->Activate(0);
1596
1597 Active = view;
1598
1599 if (Active)
1600 Active->Activate(1);
1601
1602 if (Active)
1603 XtSetKeyboardFocus(Peer->PanedWin, Active->Peer->TextWin);
1604
1605 return 1;
1606 }
1607
Resize(int width,int height)1608 void GFrame::Resize(int width, int height) {
1609 if (!Top)
1610 return;
1611
1612 if (width < 8 || height < 2)
1613 return;
1614
1615 if (Top == Top->Next)
1616 Top->ConSetSize(width, height);
1617 }
1618
CreateMotifMenu(Widget parent,int menu,int main,XtCallbackProc MenuProc)1619 static Widget CreateMotifMenu(Widget parent, int menu, int main, XtCallbackProc MenuProc) {
1620 Widget hmenu;
1621 Widget item;
1622
1623 if (main == 1)
1624 hmenu = XmCreateMenuBar(parent, "menu", NULL, 0);
1625 else if (main == 2) {
1626 hmenu = XmCreatePopupMenu(parent, "submenu",
1627 NULL, 0);
1628 // XtCreateManagedWidget ( "Title", xmLabelWidgetClass, hmenu,
1629 // NULL, 0 );
1630
1631 // XtCreateManagedWidget ( "separator", xmSeparatorWidgetClass,
1632 // hmenu, NULL, 0 );
1633 } else
1634 hmenu = XmCreatePulldownMenu(parent, "submenu",
1635 NULL, 0);
1636
1637 for (int i = 0; i < Menus[menu].Count; ++i) {
1638 if (Menus[menu].Items[i].Name) {
1639 char s[256];
1640 char *mn = 0;
1641
1642 strcpy(s, Menus[menu].Items[i].Name);
1643 char* p = strchr(s, '&');
1644 if (p) {
1645 mn = p;
1646 // for strcpy src & dest may not overlap!
1647 for (; p[0]; ++p)
1648 p[0] = p[1];
1649 }
1650 p = strchr(s, '\t');
1651 if (p) {
1652 *p = 0;
1653 p++;
1654 }
1655 if (Menus[menu].Items[i].SubMenu != -1) {
1656 item = XtVaCreateManagedWidget(s,
1657 xmCascadeButtonWidgetClass,
1658 hmenu,
1659 XmNsubMenuId,
1660 CreateMotifMenu(hmenu,
1661 Menus[menu].Items[i].SubMenu,
1662 0, MenuProc),
1663 NULL);
1664 } else {
1665 item = XtVaCreateManagedWidget(s,
1666 xmPushButtonWidgetClass,
1667 hmenu,
1668 NULL);
1669 XtAddCallback(item, XmNactivateCallback,
1670 MenuProc, &(Menus[menu].Items[i]));
1671 }
1672
1673 if (p)
1674 XtVaSetValues(item,
1675 XmNacceleratorText,
1676 XmStringCreate(p, XmSTRING_DEFAULT_CHARSET),
1677 NULL);
1678 if (mn)
1679 XtVaSetValues(item,
1680 XmNmnemonic,
1681 KeySym(*mn),
1682 NULL);
1683 } else {
1684 item = XtVaCreateManagedWidget("separator",
1685 xmSeparatorWidgetClass,
1686 hmenu,
1687 NULL);
1688 //XmCreateSeparator(parent, "xx", 0, 0);
1689 }
1690 // item.id = Menus[menu].Items[i].Cmd & 0xFFFF; // ?
1691 }
1692 return hmenu;
1693 }
1694
CreateMotifMainMenu(Widget parent,char * Name)1695 static Widget CreateMotifMainMenu(Widget parent, char *Name) {
1696 int id = GetMenuId(Name);
1697
1698 return CreateMotifMenu(parent, id, 1, MainCallback);
1699 }
1700
SetMenu(const char * Name)1701 int GFrame::SetMenu(const char *Name) {
1702 free(Menu);
1703 Menu = strdup(Name);
1704
1705 if (Peer->MenuBar)
1706 XtDestroyWidget(Peer->MenuBar);
1707
1708 Peer->MenuBar = CreateMotifMainMenu(Peer->MainWin, Menu);
1709 XtManageChild (Peer->MenuBar);
1710 XtVaSetValues (Peer->MainWin,
1711 XmNmenuBar, Peer->MenuBar,
1712 NULL);
1713 return 1;
1714 }
1715
ExecMainMenu(char Sub)1716 int GFrame::ExecMainMenu(char Sub) {
1717 return 1;
1718 }
1719
PopupMenu(const char * Name)1720 int GFrame::PopupMenu(const char *Name) {
1721 int id = GetMenuId(Name);
1722
1723 if (LPopupMenu)
1724 XtDestroyWidget(LPopupMenu);
1725
1726 LPopupMenu = CreateMotifMenu(Peer->MainWin, id, 2, PopupCallback);
1727 XtAddCallback(XtParent(LPopupMenu), XmNpopdownCallback, MenuPopdownCb, 0);
1728 XmMenuPosition(LPopupMenu, &LastRelease);
1729 XtManageChild(LPopupMenu);
1730 return 1;
1731 }
1732
Show()1733 void GFrame::Show() {
1734 Update();
1735 Peer->MapFrame();
1736 }
1737
Activate()1738 void GFrame::Activate() {
1739 frames = this;
1740 Update();
1741 //Peer->ShowFrame();
1742 }
1743
1744 // GUI
1745
multiFrame()1746 int GUI::multiFrame() {
1747 return 1;
1748 }
1749
GUI(int & argc,char ** argv,int XSize,int YSize)1750 GUI::GUI(int &argc, char **argv, int XSize, int YSize) :
1751 fArgc(argc),
1752 fArgv(argv)
1753 {
1754 char *fs = getenv("VIOFONT");
1755 if (fs == 0 && WindowFont[0] != 0)
1756 fs = WindowFont;
1757
1758 TopLevel = XtVaAppInitialize(&AppContext, "TopLevel", NULL, 0,
1759 &argc, argv, NULL,
1760 XmNmappedWhenManaged, FALSE,
1761 NULL);
1762 if (!TopLevel)
1763 return;
1764
1765 if (!(display = XtDisplay(TopLevel)))
1766 return;
1767 //XSynchronize(display, True);
1768
1769 root = DefaultRootWindow(display);
1770 screen = DefaultScreen(display);
1771 colormap = DefaultColormap(display, screen);
1772
1773 InitXColors();
1774
1775 fontStruct = NULL;
1776 if (fs)
1777 fontStruct = XLoadQueryFont(display, fs);
1778 else {
1779 #ifdef HPUX
1780 fontStruct = XLoadQueryFont(display, "8x13");
1781 #endif
1782 #ifdef AIX
1783 fontStruct = XLoadQueryFont(display, "8x13");
1784 #endif
1785 #ifdef LINUX
1786 fontStruct = XLoadQueryFont(display, "8x13");
1787 #endif
1788 #ifdef IRIX
1789 fontStruct = XLoadQueryFont(display, "8x13");
1790 #endif
1791 }
1792 if (fontStruct == NULL)
1793 fontStruct = XLoadQueryFont(display, "fixed");
1794 if (fontStruct == NULL)
1795 return;
1796 cxChar = fontStruct->max_bounds.width;
1797 cyChar = fontStruct->max_bounds.ascent + fontStruct->max_bounds.descent;
1798 XtRealizeWidget(TopLevel);
1799
1800 WM_DELETE_WINDOW = XInternAtom(display, "WM_DELETE_WINDOW", False);
1801 XA_CLIPBOARD = XInternAtom(display, "CLIPBOARD", False);
1802
1803 gui = this;
1804 }
1805
~GUI()1806 GUI::~GUI() {
1807 //core: XtCloseDisplay(display);
1808 //core: XtDestroyApplicationContext(AppContext);
1809 gui = 0;
1810 }
1811
ConGrabEvents(TEventMask EventMask)1812 int GUI::ConGrabEvents(TEventMask EventMask) {
1813 return 1;
1814 }
1815
DispatchEvent(GFrame * frame,GView * view,TEvent & Event)1816 void GUI::DispatchEvent(GFrame *frame, GView *view, TEvent &Event) {
1817 if (Event.What != evNone) {
1818 if (view)
1819 view->HandleEvent(Event);
1820 }
1821 }
1822
ConSuspend()1823 int GUI::ConSuspend() { return 0; }
1824
ConContinue()1825 int GUI::ConContinue() { return 0; }
1826
ConGetEvent(TEventMask EventMask,TEvent * Event,int WaitTime,int Delete,GView ** view)1827 int GUI::ConGetEvent(TEventMask EventMask, TEvent *Event, int WaitTime, int Delete, GView **view) {
1828 //return ::ConGetEvent(EventMask, Event, WaitTime, Delete, view);
1829 assert(1 == 0);
1830 return 1;
1831 }
1832
ConPutEvent(const TEvent & Event)1833 int GUI::ConPutEvent(const TEvent& Event) {
1834 EventBuf = Event;
1835 return 1;
1836 }
1837
ConFlush()1838 int GUI::ConFlush() {
1839 return 1;
1840 }
1841
ProcessEvent()1842 void GUI::ProcessEvent() {
1843 static int need_update = 1;
1844
1845 if (need_update && XtAppPending(AppContext) == 0 ) {
1846 frames->Update();
1847 need_update = 0;
1848 }
1849 XtAppProcessEvent(AppContext, XtIMAll);
1850 if (NextEvent.What != evNone) {
1851 DispatchEvent(frames, NextEvent.Msg.View, NextEvent);
1852 NextEvent.What = evNone;
1853 need_update = 1;
1854 }
1855 }
1856
Run()1857 int GUI::Run() {
1858 if (Start(fArgc, fArgv)) {
1859 doLoop = 1;
1860 frames->Show();
1861
1862 //if (frames && frames->Peer)
1863 // frames->Peer->MapFrame();
1864
1865 //XtAppMainLoop(AppContext);
1866 while (doLoop)
1867 ProcessEvent();
1868
1869 Stop();
1870 return 1;
1871 }
1872
1873 return 0;
1874 }
1875
ShowEntryScreen()1876 int GUI::ShowEntryScreen() {
1877 return 1;
1878 }
1879
RunProgram(int mode,char * Command)1880 int GUI::RunProgram(int mode, char *Command) {
1881 char Cmd[1024];
1882
1883 strlcpy(Cmd, XShellCommand, sizeof(Cmd));
1884
1885 if (*Command == 0) // empty string = shell
1886 strlcat(Cmd, " -ls &", sizeof(Cmd));
1887 else {
1888 strlcat(Cmd, " -e ", sizeof(Cmd));
1889 strlcat(Cmd, Command, sizeof(Cmd));
1890 if (mode == RUN_ASYNC)
1891 strlcat(Cmd, " &", sizeof(Cmd));
1892 }
1893
1894 return (system(Cmd) == 0);
1895 }
1896
1897 //void PipeCallback(GPipe *pipe, int *source, XtInputId *input)
PipeCallback(void * pipev,int * source,XtInputId * input)1898 void PipeCallback(void *pipev, int *source, XtInputId *input)
1899 {
1900 GPipe *pipe = (GPipe*)pipev;
1901 if (pipe && pipe->notify && *source == pipe->fd) {
1902 NextEvent.What = evNotify;
1903 NextEvent.Msg.View = frames->Active;
1904 NextEvent.Msg.Model = pipe->notify;
1905 NextEvent.Msg.Command = cmPipeRead;
1906 NextEvent.Msg.Param1 = pipe->id;
1907 pipe->stopped = 0;
1908 }
1909 //fprintf(stderr, "Pipe %d\n", *source);
1910 }
1911
OpenPipe(const char * Command,EModel * notify)1912 int GUI::OpenPipe(const char *Command, EModel *notify) {
1913 for (int i = 0; i < MAX_PIPES; i++) {
1914 if (Pipes[i].used == 0) {
1915 int pfd[2];
1916
1917 Pipes[i].id = i;
1918 Pipes[i].notify = notify;
1919 Pipes[i].stopped = 1;
1920
1921 if (pipe((int *)pfd) == -1)
1922 return 0;
1923
1924 switch (Pipes[i].pid = fork()) {
1925 case -1: /* fail */
1926 return -1;
1927 case 0: /* child */
1928 close(pfd[0]);
1929 close(0);
1930 dup2(pfd[1], 1);
1931 dup2(pfd[1], 2);
1932 exit(system(Command));
1933 default:
1934 close(pfd[1]);
1935 fcntl(pfd[0], F_SETFL, O_NONBLOCK);
1936 Pipes[i].fd = pfd[0];
1937 }
1938 Pipes[i].input = /* FIXME: */
1939 XtAppAddInput(AppContext, Pipes[i].fd, (void*)XtInputReadMask, PipeCallback, &Pipes[i]);
1940 Pipes[i].used = 1;
1941 //fprintf(stderr, "Pipe Open: %d\n", i);
1942 return i;
1943 }
1944 }
1945
1946 return -1;
1947 }
1948
SetPipeView(int id,EModel * notify)1949 int GUI::SetPipeView(int id, EModel *notify) {
1950 if (id < 0 || id > MAX_PIPES)
1951 return 0;
1952 if (Pipes[id].used == 0)
1953 return 0;
1954
1955 //fprintf(stderr, "Pipe View: %d %08X\n", id, notify);
1956 Pipes[id].notify = notify;
1957 if (notify != Pipes[id].notify) {
1958 if (notify) {
1959 Pipes[id].input = /* FIXME */
1960 XtAppAddInput(AppContext, Pipes[id].fd, (void*)XtInputReadMask, PipeCallback, &Pipes[id]);
1961 } else {
1962 if (Pipes[id].input != 0) {
1963 XtRemoveInput(Pipes[id].input);
1964 Pipes[id].input = 0;
1965 }
1966 }
1967 }
1968
1969 return 1;
1970 }
1971
ReadPipe(int id,void * buffer,size_t len)1972 ssize_t GUI::ReadPipe(int id, void *buffer, size_t len) {
1973 ssize_t rc;
1974
1975 if (id < 0 || id > MAX_PIPES || Pipes[id].used == 0)
1976 return -1;
1977
1978 //fprintf(stderr, "Pipe Read: Get %d %d\n", id, len);
1979
1980 rc = read(Pipes[id].fd, buffer, len);
1981 //fprintf(stderr, "Pipe Read: Got %d %d\n", id, len);
1982 if (rc == 0) {
1983 if (Pipes[id].input != 0) {
1984 XtRemoveInput(Pipes[id].input);
1985 Pipes[id].input = 0;
1986 }
1987 close(Pipes[id].fd);
1988 return -1;
1989 }
1990 if (rc == -1)
1991 Pipes[id].stopped = 1;
1992
1993 return rc;
1994 }
1995
ClosePipe(int id)1996 int GUI::ClosePipe(int id) {
1997 int status;
1998
1999 if (id < 0 || id > MAX_PIPES || Pipes[id].used == 0)
2000 return 0;
2001
2002 waitpid(Pipes[id].pid, &status, 0);
2003 //fprintf(stderr, "Pipe Close: %d\n", id);
2004 Pipes[id].used = 0;
2005
2006 return (WEXITSTATUS(status) == 0);
2007 }
2008
GetXSelection(int * len,char ** data,int clipboard)2009 int GetXSelection(int *len, char **data, int clipboard) {
2010 // XXX use clipboard?
2011 if (!(*data = XFetchBytes(display, len)))
2012 return 0;
2013
2014 return 1;
2015 }
2016
SetXSelection(int len,char * data,int clipboard)2017 int SetXSelection(int len, char *data, int clipboard) {
2018 Atom clip;
2019
2020 XStoreBytes(display, data, len);
2021 switch (clipboard) {
2022 case 0:
2023 clip = XA_CLIPBOARD;
2024 break;
2025 case 1:
2026 clip = XA_PRIMARY;
2027 break;
2028 case 2:
2029 clip = XA_SECONDARY;
2030 break;
2031 default:
2032 // not supported
2033 return 0;
2034 }
2035 XSetSelectionOwner(display, clip, None, CurrentTime);
2036
2037 return 1;
2038 }
2039
2040 /*
2041 static void SetColor(int i) {
2042 int j, k, z;
2043 j = i & 7;
2044 k = 65535 - 20480;
2045 z = (i > 7) ? (20480) : 0;
2046 Colors[i].blue = k * (j & 1) + z;
2047 Colors[i].green = k * ((j & 2)?1:0) + z;
2048 Colors[i].red = k * ((j & 4)?1:0) + z;
2049 Colors[i].flags = DoRed | DoGreen | DoBlue;
2050 }
2051
2052 static int InitXColors() {
2053 int i;
2054
2055 for (i = 0; i < 16; i++) {
2056 SetColor(i);
2057 if (XAllocColor(display, colormap, &Colors[i]) == 0) {
2058 colormap = XCreateColormap(display, win, DefaultVisual(display, screen), AllocNone);
2059 for (i = 0; i < 16; i++) {
2060 SetColor(i);
2061 XAllocColor(display, colormap, &Colors[i]);
2062 }
2063 XSetWindowColormap(display, win, colormap);
2064 return 0;
2065 }
2066 }
2067 return 0;
2068 }
2069 static int InitXGCs() {
2070 int i;
2071 XGCValues gcv;
2072
2073 for (i = 0; i < 256; i++) {
2074 gcv.foreground = Colors[i % 16].pixel;
2075 gcv.background = Colors[(i / 16)].pixel;
2076 gcv.font = fontStruct->fid;
2077 GCs[i] = XCreateGC(display, win, GCForeground | GCBackground | GCFont, &gcv);
2078 }
2079 return 0;
2080 }
2081 */
2082
DieError(int rc,const char * msg,...)2083 void DieError(int rc, const char *msg, ...) {
2084 va_list ap;
2085
2086 va_start(ap, msg);
2087 vfprintf(stderr, msg, ap);
2088 va_end(ap);
2089 exit(rc);
2090 }
2091
ConGetDrawChar(unsigned int index)2092 char ConGetDrawChar(unsigned int index) {
2093 static const char tab[] = "\x0D\x0C\x0E\x0B\x12\x19____+>\x1F\x01\x12\x01\x01 \x02";
2094
2095 assert(index < sizeof(tab) - 1);
2096
2097 return tab[index];
2098 }
2099