1
2 /*
3 edx/emx (EDitor for X) (C) 2002, Terry Loveall
4 released into the public domain.
5 Based upon the original work ee.c of Yijun Ding, copyright 1991 which is
6 in the public domain.
7 This program comes with no warranties or binaries. Use at your own risk.
8 */
9
10 #include <stdio.h>
11 #include <string.h>
12 #include <sys/stat.h>
13 #include <stdlib.h>
14 #include <ctype.h>
15 #include <signal.h>
16 #include <pwd.h>
17 #include <X11/Xlib.h>
18 #include <X11/Xatom.h>
19 #include <X11/Xutil.h>
20 #include <X11/Xos.h>
21 #define XK_MISCELLANY
22 #include <X11/keysymdef.h>
23 #include <sys/time.h>
24
25 #ifdef MINIMAL
26 #define DEFAULT_HEIGHT 25
27 #else
28 #define DEFAULT_HEIGHT 32
29 #endif
30
31 #define DEFAULT_WIDTH 80
32
33 /* turns on display of keypressed event values in upper right corner */
34 /* #define DEBUG */
35
36 /*
37 #define FONTNAME "-b&h-lucidatypewriter-medium-r-normal-sans-12-*-*-*-m-70-iso8859-1"
38 #define FONTNAME "-b&h-lucidatypewriter-bold-r-normal-sans-12-*-*-*-m-70-iso8859-1"
39 #define FONTNAME "9x15bold"
40 */
41 #ifdef TLL
42 #define FONTNAME "-b&h-lucidatypewriter-bold-r-normal-sans-12-*-*-*-m-70-iso8859-1"
43 #else
44 #define FONTNAME "8x13"
45 #endif
46
47 #define X11
48
49 /* #define cprintf(s,v) { char str[350]; sprintf(str,s,v); cputs(str); } */
50
51 #/************************************************************/
52
53 /* use MS style COORD to track cursor pos */
54 typedef struct {
55 int X; /* x coordinate */
56 int Y; /* y coordinate */
57 } COORD; /* x-y structure */
58
59 COORD outxy; /* cursor coordinates for screen positioning */
60
61 #/************************************************************/
62
63 /* X related globals */
64 Display *dpy;
65 Window win;
66 GC gc;
67 XFontStruct *font;
68 /*
69 int Ascent, Descent;
70 */ /* font max y excursions */
71 XEvent event;
72 XKeyEvent *keve;
73 Time eve_time;
74 char *selection_text; /* selected text for X clipboard */
75 char *comment;
76 int selection_length;
77 int expose;
78 int vtot, vcur, pos, ftheight; /* global variables for scrollbar */
79
80 int Width, Height;
81 int fwidth, fheight, ycur = 0; /* font character width, height */
82
83 /* Foreground, Background normal and highlight colores */
84 XColor FgXColor, BgXColor, CrXColor,
85 HiFgXColor, HiBgXColor;
86
87 int HiLo; /* hightlight status, 0=off */
88 Atom DeleteWindow; /* Atom of delete window message */
89
90 /* char *FgColor="Black", *BgColor="Linen", *HiFgColor="Black", *HiBgColor="Grey75"; */
91 #ifdef DARK
92 char *FgColor="Yellow",
93 *BgColor="Black",
94 *CrColor="White",
95 #else
96 char *FgColor="Black",
97 *BgColor="White",
98 *CrColor="Red",
99 #endif
100 *HiFgColor="Black",
101 *HiBgColor="Grey84";
102 char *FontName=NULL;
103 char *DisplayName=NULL;
104 char *AppName;
105 char *RcFile = NULL;
106
107 char *Geometry=NULL;
108 /* maximum viewable 6x8 chars on a 2000x1600 screen */
109 #define MAXVLINE 450
110 char eolbuf[MAXVLINE]; /* holds spaces for clreol(), 450 is 2000x1600 */
111
112 /* func prototypes */
113
114 void gotoxy(int horz,int vert);
115 void cursor_draw(unsigned long color);
116 void draw_cursor();
117 void undraw_cursor();
118 void drawstring(char *str, int len);
119 void cputs(char *prntstr);
120 int putch(char chr);
121 void clreol();
122 void highvideo();
123 void lowvideo();
124 void clrscr();
125 void bell();
126 void show_vbar();
127 void update();
128 void scroll_text();
129 void sig_handler(int);
130 void font_height(void);
131 int paste_primary(int win, int property, int Delete);
132 int request_selection(int time);
133 char *mrealloc(char *s, int len);
134 void set_selection();
135 void send_selection(XSelectionRequestEvent * rq);
136 void init(int argc,char *argv[]);
137 void handle_key(char *astr, int skey, int state);
138 void moveto();
139 void do_paste();
140 void do_select(int delete);
141 void iconify();
142 void set_title(char *str);
143
144 /* for monolithic whole include engine here */
145
146 #include "version.h"
147 #include "messages.def"
148 #include "edit.h"
149
150 #ifdef EMACS
151 #include "x11_bind_em.c"
152 #endif
153 #ifdef WORDSTAR
154 #include "x11_bind_ws.c"
155 #endif
156
157 /******************** Start of cursor I/O ********************/
158
159 /* Goto the specified location. */
160
gotoxy(int horz,int vert)161 void gotoxy(int horz,int vert)
162 {
163 outxy.X = horz;
164 outxy.Y = vert;
165 }
166
cursor_draw(unsigned long color)167 void cursor_draw(unsigned long color)
168 {
169 XSetForeground(dpy, gc, color);
170 #ifdef VERTCURS
171 XDrawRectangle(dpy, win, gc,
172 (outxy.X * fwidth) + 2, (outxy.Y * fheight) + 2,
173 0, fheight - 0);
174 #else
175 #ifdef BOXCURS
176 XDrawRectangle(dpy, win, gc,
177 (outxy.X * fwidth) + 1, (outxy.Y * fheight) + 2,
178 fwidth, fheight);
179 #else
180 XFillRectangle(dpy, win, gc,
181 (outxy.X * fwidth) + 2, ((outxy.Y+1)* fheight) + 2,
182 fwidth-1, 2);
183 #endif
184 #endif
185 XSetForeground(dpy, gc, HiLo ? HiFgXColor.pixel : FgXColor.pixel);
186 }
187
draw_cursor()188 void draw_cursor()
189 {
190 /*
191 cursor_draw( HiLo ? HiFgXColor.pixel : FgXColor.pixel);
192 */
193 cursor_draw( CrXColor.pixel);
194 }
195
undraw_cursor()196 void undraw_cursor()
197 {
198 cursor_draw( HiLo ? HiBgXColor.pixel : BgXColor.pixel);
199 }
200
drawstring(char * str,int len)201 void drawstring(char *str, int len)
202 {
203 if (outxy.X+len>screen_width+1) len = screen_width+1-outxy.X;
204 XDrawImageString(dpy, win, gc, (outxy.X * fwidth) + 2,
205 (outxy.Y+1) * fheight, str, len > 0 ? len : 0);
206 }
207
putch(char chr)208 int putch(char chr)
209 {
210 static char str[]="\0\0";
211
212 if(chr >= ' '){
213 str[0] = chr;
214 drawstring(str, 1);
215 outxy.X += 1;
216 }
217
218 if(!(chr) || ((chr & 0xff) == LF)){
219 clreol();
220 outxy.X = 0;
221 outxy.Y += 1;
222 }
223 return 0;
224 }
225
cputs(char * prntstr)226 void cputs(char *prntstr)
227 {
228 int strl = strlen(prntstr);
229
230 drawstring(prntstr, strl);
231 outxy.X += strl;
232 }
233
234 /* Erase from cursor to end of line. */
235
clreol()236 void clreol()
237 {
238 int tmpx = outxy.X;
239 int eollen = abs(screen_width+1 - tmpx);
240 outxy.X = outxy.X <= screen_width ? outxy.X : screen_width+1;
241 drawstring(eolbuf, eollen);
242 outxy.X = tmpx;
243 }
244
245 /* display string if visible, bump X */
246
highvideo()247 void highvideo()
248 {
249 XSetBackground(dpy,gc,HiBgXColor.pixel);
250 XSetForeground(dpy,gc,HiFgXColor.pixel);
251 HiLo = -1;
252 }
253
lowvideo()254 void lowvideo()
255 {
256 XSetBackground(dpy,gc,BgXColor.pixel);
257 XSetForeground(dpy,gc,FgXColor.pixel);
258 HiLo = 0;
259 }
260
clrscr()261 void clrscr()
262 {
263 XClearWindow(dpy,win);
264 }
265
bell()266 void bell()
267 {
268 XBell(dpy,100);
269 }
270
show_vbar()271 void show_vbar()
272 {
273 int j;
274
275 /* display buffer screen height in pixels */
276 vtot = (screen_height-2)*fheight - font->descent;
277
278 /* font true height as a constant */
279 ftheight = fheight+font->descent+1;
280
281 /* thumb height is display buffer percentage of total lines */
282 vcur = (vtot*(screen_height-1))/((ytot)?ytot:1);
283
284 /* min thumb size is 1 char */
285 if (vcur<fheight) vcur = fheight;
286
287 /* max thumb size is 2/3 vtot */
288 j = 2*vtot/3;
289 if (vcur>j) vcur = j;
290
291 /* current line number to vertical thumb pos */
292 pos = (ytru * (vtot-(vcur-fheight)))/((ytot)? ytot:1);
293
294 /* draw scrollbar through */
295 XSetForeground(dpy,gc,HiBgXColor.pixel);
296 #ifdef THREED // provide background for line scroll triangles
297 XFillRectangle(dpy, win, gc, Width-10, 0, 10, Height);
298 #else /* indicate line scroll rectangles */
299 XFillRectangle(dpy, win, gc, Width-10, ftheight, 10, Height+2-2*(ftheight));
300 #endif /* THREED */
301
302 /* draw thumb */
303 XSetForeground(dpy,gc,~HiBgXColor.pixel);
304 XDrawRectangle(dpy, win, gc, Width-9, ftheight+pos, 8, vcur);
305
306 #ifdef THREED
307 {
308 XPoint opoints[] ={{Width-10,ftheight-1},{10,0},
309 {-5,-9},{-5,9},
310 {0,Height+2-(2*(ftheight))},{5,9},
311 {5,-9},{-10,0}
312 };
313 XSegment lpoints[] ={{Width-1, ftheight+pos, Width-9, ftheight+pos},
314 {Width-9, ftheight+pos, Width-9, ftheight+pos+vcur},
315 {Width-9, ftheight-2, Width-6, ftheight-9},
316 {Width-9, Height+2-ftheight, Width-6, Height+3-ftheight+6}
317 };
318
319 /* outline trough and end triangles */
320 XDrawLines(dpy, win, gc, opoints, 8, CoordModePrevious);
321
322 /* draw in light color for 3D shading */
323 XSetForeground(dpy, gc, -1);
324 XDrawSegments(dpy, win, gc, lpoints, 4);
325 }
326 #endif /* THREED */
327 lowvideo();
328 }
329
scroll_text()330 void scroll_text()
331 {
332 int m, rep;
333
334 if (ycur<0) { y=0 ; scroll_down(); ycur = 0; }
335 if (ycur>ytot) ycur = ytot;
336
337 m = (ycur * vtot) / (ytot? ytot : 1);
338 rep = abs(ytru-ycur)/screen_height;
339
340 if(m<0) scroll_down(); /* if cursor at top of screen */
341 else if(m>vtot+ftheight) scroll_up(); /* if cursor at bottom of screen */
342 else if(m<pos) {
343 for (m=0; m<rep; m++)
344 cursor_pageup(); /* if cursor above thumb */
345 }
346 else if(m>pos+vcur) {
347 for (m=0; m<rep; m++)
348 cursor_pagedown(); /* if cursor below thumb */
349 }
350
351 goto_y(ycur); /* cursor on thumb so track it */
352
353 scr_update(); /* does show_vbar */
354 }
355
356
update()357 void update()
358 {
359 flag[SHW] = 1;
360 show_top();
361 scr_update();
362 show_vbar();
363 if (executive == DIALOG) {
364 undraw_cursor();
365 show_gets(comment, diabuf, dblen, dialogCB);
366 gotoxy(diastart+col,yl1);
367 draw_cursor();
368 }
369 }
370
sig_handler(int nothing)371 void sig_handler(int nothing)
372 {
373 update();
374 XFlush(dpy);
375 }
376
377 /*
378 void font_height(void)
379 {
380 int foo,bar,baz;
381 XCharStruct extents;
382
383 XTextExtents(font,"OOO|jW6789",10,&foo,&bar,&baz,&extents);
384 Ascent=extents.ascent;
385 Descent=extents.descent;
386 }
387 */
388
389
paste_primary(int win,int property,int Delete)390 int paste_primary(int win, int property, int Delete)
391 {
392 Atom actual_type;
393 int actual_format, i;
394 long nitem, bytes_after, nread;
395 unsigned char *data;
396 char indent = flag[IND]; /* stash autoindent state */
397
398 if (property == None) /* don't paste anything */
399 return(0);
400
401 flag[IND] = 0; /* off autoindent */
402 nread = 0;
403 /* X-selection paste loop */
404 do {
405 if (XGetWindowProperty /* get remaining selection max 1024 chars */
406 (dpy, win, property, nread / 4, 1024, Delete,
407 AnyPropertyType, &actual_type, &actual_format, &nitem,
408 &bytes_after, (unsigned char **) &data)
409 != Success)
410 return(0);
411 update_scr = 0; /* dont update scr...yet */
412 /* paste last batch one char at a time */
413 for(i = 0; i < nitem; handle_key(NULL, data[i++],0));
414 nread += nitem;
415 XFree(data);
416 } while (bytes_after > 0);
417 update_scr = 1; /* _now_ update display */
418 flag[SHW] = 1;
419 scr_update();
420 flag[IND] = indent; /* restore autoindent state */
421 return(nread);
422 }
423
request_selection(int time)424 int request_selection(int time)
425 {
426 Window w;
427 Atom property;
428
429 if ((w = XGetSelectionOwner(dpy, XA_PRIMARY)) == None) {
430 int tmp = paste_primary(DefaultRootWindow(dpy), XA_CUT_BUFFER0,
431 False);
432 return(tmp);
433 }
434 property = XInternAtom(dpy, "VT_SELECTION", False);
435 XConvertSelection(dpy, XA_PRIMARY, XA_STRING, property, win,
436 time);
437 return(0);
438 }
439
mrealloc(char * s,int len)440 char *mrealloc(char *s, int len)
441 {
442 char *ttt;
443 if(!s) ttt = (char *) malloc(len);
444 else ttt = (char *) realloc(s, len);
445 return ttt;
446 }
447
set_selection()448 void set_selection()
449 {
450 int i;
451
452 if(!flag[BLK] || mk == cur_pos) return;
453
454 if(cur_pos < mk)
455 { bstart = cur_pos; bend = mk; }
456 else
457 { bstart = mk; bend = cur_pos; }
458
459 selection_length = bend - bstart;
460 if ((selection_text = (char *) mrealloc(selection_text, selection_length)) == NULL) {
461 printf(SELECT_REALLOC"\n");
462 se_exit:
463 bell();
464 return;
465 }
466 for (i = 0; i < selection_length; i++) {
467 selection_text[i] = bstart[i] == EOL ? '\n' : bstart[i];
468 }
469 XSetSelectionOwner(dpy, XA_PRIMARY, win, (Time) eve_time);
470 if (XGetSelectionOwner(dpy, XA_PRIMARY) != win) {
471 printf(CANT_SELECT"\n");
472 goto se_exit;
473 }
474 XChangeProperty(dpy, DefaultRootWindow(dpy), XA_CUT_BUFFER0,
475 XA_STRING, 8, PropModeReplace, selection_text,
476 selection_length);
477 }
478
send_selection(XSelectionRequestEvent * rq)479 void send_selection(XSelectionRequestEvent * rq)
480 {
481 XSelectionEvent notify;
482
483 notify.type = SelectionNotify;
484 notify.display = rq->display;
485 notify.requestor = rq->requestor;
486 notify.selection = rq->selection;
487 notify.target = rq->target;
488 notify.time = rq->time;
489 XChangeProperty(dpy, rq->requestor, rq->property, XA_STRING, 8,
490 PropModeReplace, selection_text, selection_length);
491 notify.property = rq->property;
492 XSendEvent(dpy, rq->requestor, False, 0, (XEvent *) & notify);
493 }
494
parse_arg(char * arg1,char * arg2)495 void parse_arg(char *arg1, char *arg2)
496 {
497 if(*arg1=='-') {
498 if (!strcasecmp(arg1, "-f"))
499 strcpy(ewin.name, arg2);
500 else
501 if (!strcasecmp(arg1, "-t"))
502 tabsize = atoi(arg2);
503 else
504 if (!strcasecmp(arg1, "-j"))
505 ewin.jump = atoi(arg2);
506 else
507 if (!strcasecmp(arg1, "-w")) {
508 screen_width = atoi(arg2);
509 if (screen_width<20) screen_width = 20;
510 if (screen_width>180) screen_width = 180;
511 }
512 else
513 if (!strcasecmp(arg1, "-h")) {
514 screen_height = atoi(arg2);
515 if (screen_height<5) screen_height = 5;
516 if (screen_height>80) screen_height = 80;
517 }
518 else
519 if (!strcasecmp(arg1, "-fn"))
520 FontName = strdup(arg2);
521 else
522 if (!strcasecmp(arg1, "-rc"))
523 RcFile = strdup(arg2);
524 else
525 if (!strcasecmp(arg1, "-fg"))
526 FgColor = strdup(arg2);
527 else
528 if (!strcasecmp(arg1, "-bg"))
529 BgColor = strdup(arg2);
530 else
531 if (!strcasecmp(arg1, "-hifg"))
532 HiFgColor = strdup(arg2);
533 else
534 if (!strcasecmp(arg1, "-hibg"))
535 HiBgColor = strdup(arg2);
536 else
537 if (!strcasecmp(arg1, "-cr"))
538 CrColor = strdup(arg2);
539 else
540 if (!strcasecmp(arg1, "-edit"))
541 flag[EDT] = atoi(arg2);
542 }
543 #ifndef MINIMAL
544 if(*arg1=='@') {
545 char *ptr;
546 int i;
547 i = tolower(arg1[1])-'a';
548 if (i>=0 && i<26) {
549 ptr = arg2;
550 while(isspace(*ptr)) ++ptr;
551 if (binding[i]) free(binding[i]);
552 binding[i] = strdup(ptr);
553 }
554 }
555 #endif /* MINIMAL */
556 }
557
558 #ifndef MINIMAL
parse_rc(FILE * f)559 void parse_rc(FILE *f)
560 {
561 char buf[512], *ptr;
562 int i, l;
563 while ((ptr=fgets(buf, 510, f))) {
564 while (isspace(*ptr)) ++ptr;
565 if (strlen(ptr)<2 || *ptr == '#') continue;
566 i = 0;
567 while(ptr[i] && !isspace(ptr[i])) ++i;
568 if (!ptr[i]) continue;
569 ptr[i++] = '\0';
570 if (ptr[i]) {
571 l = strlen(ptr+i)+i-1;
572 if (l>=i && ptr[l]=='\n') ptr[l] = '\0';
573 parse_arg(ptr, ptr+i);
574 }
575 }
576 }
577
read_rc()578 void read_rc()
579 {
580 FILE *fr = NULL;
581 char name[NLEN], *ptr;
582
583 if ((ptr=getenv("HOME"))) {
584 if (RcFile) {
585 if (ptr && *RcFile == '~' && RcFile[1] == '/')
586 sprintf(name, "%s/%s", ptr, RcFile+2);
587 else
588 strcpy(name, RcFile);
589 }
590 else
591 sprintf(name, "%s/.%s", ptr, DEFAULT_RC);
592 fr = fopen(name, "r");
593 }
594
595 if (!fr) {
596 sprintf(name, "%s/%s", SHAREDIR, DEFAULT_RC);
597 fr = fopen(name, "r");
598 }
599
600 if (fr) {
601 parse_rc(fr);
602 fclose(fr);
603 }
604 }
605 #endif /* MINIMAL */
606
init(int argc,char * argv[])607 void init(int argc,char *argv[])
608 {
609 int screen;
610 XWMHints *wmh;
611 XSizeHints *xsh;
612 XClassHint *classh;
613 XColor tmp;
614 int i, x, y;
615
616 /* Default settings */
617 *ewin.name = '\0';
618 amax = AMAX;
619 bmax = BMAX;
620 umax = UMAX;
621
622 /* engine screen width, height, font */
623 screen_height = DEFAULT_HEIGHT - 1;
624 screen_width = DEFAULT_WIDTH;
625
626 #ifndef MINIMAL
627 memset((void *)binding, 0, 26*sizeof(char *));
628
629 for (i=1; i<argc; i++) {
630 if (i<argc-1 && !strcasecmp(argv[i], "-rc"))
631 RcFile = strdup(argv[++i]);
632 }
633 read_rc();
634 #endif /* MINIMAL */
635
636 /* get command line options */
637 for (i=1; i<argc; i++) {
638 if ((i<argc-1) &&
639 (argv[i][0]=='-'
640 #ifndef MINIMAL
641 || argv[i][0]=='@'
642 #endif
643 )) {
644 parse_arg(argv[i], argv[i+1]);
645 ++i;
646 } else {
647 if (*ewin.name) break;
648 /* case of syntax 'filename:linenumber' */
649 {
650 char* p=strchr(argv[i],':');
651 if (p) {
652 *p++ = '\0';
653 ewin.jump = atoi(p);
654 }
655 }
656 strcpy(ewin.name, argv[i]);
657 }
658 }
659
660 /* alloc memory for the main buffer and block buffer */
661 edbuf = (char *) malloc((size_t)(amax+tabsize+1));
662 bb = (char *) malloc((size_t)(bmax+tabsize+1));
663 unbuf = (void *) malloc((size_t)(umax+tabsize+1));
664
665 if (!edbuf || !bb || !unbuf) {
666 fprintf(stderr,"Memory allocation failed, aborting !!\n");
667 exit(1);
668 }
669
670 /* open the display */
671 dpy=XOpenDisplay(DisplayName);
672 if(dpy==NULL) {
673 fprintf(stderr,"Can't open display: %s\n",DisplayName);
674 sys_exit(1);
675 }
676
677 /* setup to gracefully respond to exit requests from X */
678 screen=DefaultScreen(dpy);
679 DeleteWindow = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
680
681 /* establish window manager hints data structure */
682 xsh=XAllocSizeHints();
683 wmh=XAllocWMHints();
684 classh=XAllocClassHint();
685
686 x = 1; y=0;
687
688 /* setup font(s) */
689 if(FontName == NULL) { FontName = FONTNAME; }
690
691 font=XLoadQueryFont(dpy, FontName);
692 if(font==NULL) {
693 fprintf(stderr, FONTS_NOT_FOUND"\n");
694 sys_exit(1);
695 }
696
697 fheight = font->ascent + font->descent;
698 Height = fheight * screen_height + font->descent + 2;
699
700 /* engine screen width */
701 fwidth = XTextWidth(font,"8",1);
702
703 Width = (fwidth * screen_width)+13;
704 xsh->flags = PSize; xsh->width = Width; xsh->height = Height;
705
706 /* initialize clreol string to all blanks */
707 memset(eolbuf, ' ', sizeof(eolbuf));
708
709 /* create the only window */
710 win=XCreateSimpleWindow(dpy,RootWindow(dpy,screen), x, y,
711 Width, Height, 0,
712 BlackPixel(dpy,screen),WhitePixel(dpy,screen));
713
714 /* setup window hints */
715 wmh->initial_state=NormalState;
716 wmh->input=True;
717 wmh->window_group = win;
718 wmh->flags = StateHint | InputHint | WindowGroupHint;
719
720 /* setup window class resource names */
721 classh->res_name = (AppName==NULL)?EDIT:AppName;
722 classh->res_class = "Xedit";
723
724 /* name that window */
725 XmbSetWMProperties(dpy, win, EDIT, EDIT, argv, argc,
726 xsh, wmh, classh);
727 /* notify X on how to force emx to exit */
728 XSetWMProtocols(dpy, win, &DeleteWindow, 1);
729
730 /* specify accepted XEvent loop events */
731 XSelectInput(dpy, win,
732 KeyPressMask|\
733 FocusChangeMask|\
734 StructureNotifyMask|\
735 ButtonPressMask|\
736 ButtonReleaseMask|\
737 ExposureMask|\
738 PropertyChangeMask|\
739 Button1MotionMask|\
740 Button2MotionMask|\
741 Button3MotionMask|\
742 VisibilityChangeMask
743 );
744 keve = (XKeyEvent *)&event;
745
746 /* create the Graphic Context for drawing purposes */
747 gc=XCreateGC(dpy,win,0,NULL);
748
749 /* allocate required colors */
750 XAllocNamedColor(dpy,DefaultColormap(dpy,screen),FgColor,&FgXColor,&tmp);
751 XAllocNamedColor(dpy,DefaultColormap(dpy,screen),BgColor,&BgXColor,&tmp);
752 XAllocNamedColor(dpy,DefaultColormap(dpy,screen),CrColor,&CrXColor,&tmp);
753 XAllocNamedColor(dpy,DefaultColormap(dpy,screen),HiFgColor,&HiFgXColor,&tmp);
754 XAllocNamedColor(dpy,DefaultColormap(dpy,screen),HiBgColor,&HiBgXColor,&tmp);
755
756 /* apply colors to window */
757 XSetForeground(dpy,gc,FgXColor.pixel);
758 XSetWindowBackground(dpy,win,BgXColor.pixel);
759
760 /* set the font */
761 XSetFont(dpy,gc,font->fid);
762
763 /* map the window real */
764 XMapWindow(dpy, win);
765 }
766
handle_key(char * astr,int skey,int state)767 void handle_key(char *astr, int skey, int state)
768 {
769 char chstr[256];
770 int x=outxy.X, y=outxy.Y, n=0;
771
772 /* display keyboard shift/control/alt status */
773 highvideo();
774 gotoxy(0,yl1);
775 for(n=5;n;chstr[n--]=' ');
776 if(state & ShiftMask) chstr[n++] = 'S';
777 if(state & Mod1Mask) chstr[n++] = 'A';
778 if(skey & 0xff00) chstr[n++] = 'F';
779 if(state & ControlMask) chstr[n++] = '^';
780 chstr[n] = skey & 0xff;
781 chstr[5] = '\0';
782 cputs(chstr);
783 chstr[0] = '\0';
784
785 #ifdef DEBUG
786 /* display raw key event data */
787 sprintf(chstr,"k=%4x,s=%2x.",skey,state);
788 #endif /* DEBUG */
789 gotoxy(screen_width - 12,0);
790 clreol();
791 cputs(chstr);
792 gotoxy(x,y);
793 lowvideo();
794
795 if((skey >= 0xffe1) && (skey <= 0xffee)) return;
796 if(skey == NoSymbol) return;
797
798 switch(executive) {
799 case MAIN:
800 main_exec(skey);
801 break;
802 case DIALOG:
803 dialog(skey);
804 break;
805 case OPTIONS:
806 options(skey);
807 break;
808 }
809 }
810
moveto()811 void moveto()
812 {
813 move_to(((event.xbutton.x < 0 ? 0 : event.xbutton.x)/fwidth) + 1 + xlo,
814 ((event.xbutton.y-3)/fheight) - 1);
815 }
816
do_select(int delete)817 void do_select(int delete)
818 {
819 if(flag[BLK] && mk != cur_pos) {
820 set_selection();
821 block_copy(delete);
822 }
823 mark_off();
824 }
825
do_paste()826 void do_paste()
827 {
828 if(flag[BLK] && executive == MAIN) block_remove_update();
829 request_selection(event.xbutton.time);
830 }
831
iconify()832 void iconify()
833 {
834 XIconifyWindow(dpy, win, DefaultScreen(dpy));
835 }
836
set_title(char * str)837 void set_title(char *str)
838 {
839 char b[NLEN];
840
841 sprintf(b, EDIT" : %s", str);
842 XStoreName(dpy, win, b);
843 }
844
main(int argc,char * argv[])845 int main(int argc,char *argv[])
846 {
847 Atom WM_PROTOCOLS = 0;
848 struct sigaction sig;
849 int yp0 = 0, yp1 = 0, yf, yt;
850
851 init(argc,argv);
852
853 /* disconnect from the console */
854 /* JPD commented this out. Use instead emx/edx & from shell */
855 /*
856 switch (fork()) { case 0: case -1: break; default: exit(0); }
857 */
858
859 /* set path */
860 if (cfdpath == NULL) {
861 cfdpath = (char *) malloc(BUFSIZ);
862 getcwd(cfdpath, BUFSIZ);
863 if (strcmp(cfdpath, "/") != 0)
864 strcat(cfdpath, "/");
865 }
866
867 usleep(10000);
868 XFlush(dpy);
869 do_open();
870
871 /* end of edit engine init */
872
873 /* request/create WM_PROTOCOLS atom */
874 WM_PROTOCOLS = XInternAtom(dpy, "WM_PROTOCOLS", False);
875
876 /* set up the signal handler response */
877 sig.sa_handler=sig_handler;
878 sigemptyset(&sig.sa_mask);
879 sig.sa_flags=SA_RESTART;
880 sigaction(SIGALRM,&sig,NULL);
881
882 /* display the initial cursor */
883 clrscr();
884
885 #define DBLCLICK 300
886
887 /* main event loop, dispatch function calls in response to events */
888 for(;;) {
889 static Time button_release_time;
890 static int buttonpressed = 0;
891 XNextEvent(dpy,&event);
892
893 switch(event.type) {
894 case Expose:
895 while(XCheckTypedEvent(dpy,Expose,&event));
896 expose = 1;
897 update();
898 expose = 0;
899 break;
900 case MotionNotify:
901 if (buttonpressed==-1) {
902 if (executive == MAIN) {
903 ycur =
904 ((event.xbutton.y - ftheight)*ytot)/vtot;
905 scroll_text();
906 }
907 break;
908 }
909 #ifndef TWOBUTN
910 motion:
911 yf = (buttonpressed == Button3)? fheight : 0;
912 #endif
913 if(buttonpressed) {
914 #ifdef TWOBUTN
915 if(!flag[BLK]) block_mark();
916 undraw_cursor();
917 if (event.xbutton.y < fheight + 2) {
918 #else
919 if(!flag[BLK] && ! yf) block_mark();
920 undraw_cursor();
921 if (event.xbutton.y < fheight + yf + 2) {
922 #endif
923 moveto();
924 cur_pos = get_cur();
925 scroll_down();
926 scr_update();
927 }
928 else
929 #ifdef TWOBUTN
930 if (event.xbutton.y >= Height-6-font->descent) {
931 #else
932 if (event.xbutton.y >= Height-yf-6-font->descent) {
933 #endif
934 moveto();
935 cur_pos = get_cur();
936 scroll_up();
937 scr_update();
938 }
939 else {
940 #ifndef TWOBUTN
941 if (yf) goto finish;
942 #endif
943 moveto();
944 yf = yp0;
945 if (y<yf) yf = y;
946 if (yp1<yf) yf = yp1;
947 yt = yp0;
948 if (y>yt) yt = y;
949 if (yp1>yt) yt = yp1;
950 show_scr(yf, yt);
951 #ifndef TWOBUTN
952 finish:
953 #endif
954 moveto();
955 cur_pos = get_cur();
956 gotoxy(x-1,y+1);
957 draw_cursor();
958 yp1 = y;
959 }
960 }
961 break;
962 case ButtonPress:
963 if (event.xbutton.button>Button3 &&
964 executive==MAIN) {
965 if (event.xbutton.button==Button4) {
966 ycur -= 3;
967 scroll_text();
968 }
969 if (event.xbutton.button==Button5) {
970 ycur += 3;
971 scroll_text();
972 }
973 break;
974 }
975 help_done = 0;
976 undraw_cursor();
977 if (event.xbutton.x>=Width-10) {
978 buttonpressed = -1;
979 if (executive == MAIN)
980 scroll_text(event.xbutton.y);
981 break;
982 }
983 buttonpressed = event.xbutton.button;
984 #ifndef TWOBUTN
985 if (buttonpressed == Button3) {
986 mark_off();
987 scr_update();
988 goto motion;
989 }
990 #endif
991 if (event.xbutton.time - eve_time < DBLCLICK) break;
992 eve_time = event.xbutton.time;
993 moveto();
994 yp0 = y;
995 flag[SHW] = 1;
996 cur_pos = get_cur();
997 if (flag[BLK]) {
998 mark_off(); /* unmark */
999 scr_update();
1000 } else {
1001 block_mark(); /* start new mark */
1002 draw_cursor();
1003 }
1004 break;
1005 case ButtonRelease:
1006 if (buttonpressed==-1) {
1007 buttonpressed = 0;
1008 break;
1009 }
1010 buttonpressed = 0;
1011 #ifndef TWOBUTN
1012 if (event.xbutton.button == Button3) goto motion;
1013 #endif
1014 switch (event.xbutton.button) {
1015 case Button1:
1016 if (event.xbutton.time - button_release_time < DBLCLICK) {
1017 mark_off(); cursor_right(); word_left(); block_mark(); /* set mark to left end of word */
1018 word_right(); scr_update(); /* set mark to right end of word */
1019 break;
1020 }
1021 else
1022 {
1023
1024 button_release_time = event.xbutton.time;
1025 if (mk == cur_pos)
1026 mark_off();
1027 else
1028 set_selection();
1029 goto setcursor;
1030 }
1031 break;
1032 #ifdef TWOBUTN
1033 case Button2:
1034 case Button3:
1035 #else
1036 case Button2:
1037 #endif
1038 if ((event.xbutton.time - eve_time < DBLCLICK) &&
1039 (event.xbutton.time - eve_time)) {
1040 do_paste();
1041 }
1042 goto setcursor;
1043 }
1044 break;
1045 setcursor:
1046 moveto();
1047 flag[SHW] = 1;
1048 cur_pos = get_cur();
1049 if (flag[BLK])
1050 scr_update();
1051 else
1052 draw_cursor();
1053 break;
1054
1055 case KeyPress:{
1056 int count;
1057 char astr[10];
1058 KeySym skey;
1059 eve_time = keve->time;
1060 astr[0] = 0;
1061 count = XLookupString(keve, astr,
1062 sizeof (astr), &skey, NULL);
1063 astr[count] = 0;
1064 handle_key(astr, skey, keve->state);
1065 }
1066 break;
1067 case SelectionClear:
1068 break;
1069 case SelectionRequest:
1070 send_selection((XSelectionRequestEvent *) &
1071 event);
1072 break;
1073 case SelectionNotify:
1074 paste_primary(event.xselection.requestor,
1075 event.xselection.property, True);
1076 break;
1077 case ConfigureNotify:
1078 Width = event.xconfigure.width;
1079 screen_width = (Width-16)/fwidth;
1080 Height = event.xconfigure.height;
1081 screen_height = (Height/fheight) -1 ;
1082 update();
1083 break;
1084 case ClientMessage:
1085 if(event.xclient.message_type == WM_PROTOCOLS) {
1086 if(event.xclient.data.l[0] == DeleteWindow) {
1087 XCloseDisplay(dpy);
1088 flag[CHG] = 0;
1089 sys_exit(0);
1090 }
1091 }
1092 break;
1093
1094 case DestroyNotify:
1095 XCloseDisplay(dpy);
1096 exit(0);
1097
1098 }
1099
1100 }
1101 }
1102