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