home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / AP / JED / JED097-1.TAR / jed / src / xterm.c < prev   
Encoding:
C/C++ Source or Header  |  1994-12-12  |  42.0 KB  |  1,695 lines

  1. /* This is my first attempt at X for JED. */
  2. /*
  3.  *  Copyright (c) 1992, 1994 John E. Davis  (davis@amy.tch.harvard.edu)
  4.  *  All Rights Reserved.
  5.  */
  6.  
  7. #ifndef VMS
  8. #include <X11/Xlib.h>
  9. #include <X11/Xutil.h>
  10. /* #include <X11/Xos.h> */
  11. #include <X11/Xatom.h>
  12. #include <X11/keysym.h>
  13. #include <X11/cursorfont.h>
  14. #else
  15. #include <decw$include/Xlib.h>
  16. #include <decw$include/Xutil.h>
  17. /* #include <decw$include/Xos.h> */
  18. #include <decw$include/Xatom.h>
  19. #include <decw$include/keysym.h>
  20. #include <decw$include/cursorfont.h>
  21. #endif
  22. #include <stdio.h>
  23.  
  24. #include "config.h"
  25. /* #include "xterm.h"*/
  26. #include "display.h"
  27. #include "sysdep.h"
  28. #include "screen.h"
  29. #include "keymap.h"
  30. #include "slang.h"
  31. #include "hooks.h"
  32. #include "ins.h"
  33. #include "ledit.h"
  34. #include "misc.h"
  35. #include "cmds.h"
  36.  
  37. int JX_Screen_Cols;
  38. int JX_Screen_Rows;
  39. int JX_Term_Cannot_Scroll = 0;
  40. int JX_Term_Cannot_Insert = 0;
  41. int JX_Baud_Rate = 0;
  42. int JX_Use_Ansi_Colors = 1;
  43. int JX_Ignore_Beep = 3;
  44.  
  45.  
  46. typedef struct 
  47. {
  48.    GC gc;
  49.    unsigned long fg, bg;
  50.    char *fg_name;
  51.    char *bg_name;
  52. } GC_Info_Type;
  53.  
  54. typedef struct
  55. {
  56.    Window w;
  57.    
  58.    int height, width;
  59.    int border;                   /* inside border */
  60.    int o_border;               /* outside border */
  61.    Colormap color_map;
  62.    
  63.    /* font information */
  64.    XFontStruct *font;
  65.    char *font_name;
  66.    int font_height, font_width, font_base;
  67.    
  68.    /* GC info */
  69.    GC_Info_Type *text_gc;
  70.    GC current_gc;
  71.    GC_Info_Type pointer_gc;
  72.    
  73.    int vis_curs_row, vis_curs_col;     /* position of VISIBLE cursor */
  74.    
  75.    /* flags */
  76.    int cursor_showing;               /* true if widow has cursor showing */
  77.    int focus;                   /* true if window has focus */
  78.    int window_mapped;               /* true if window is mapped */
  79.    
  80.    /* Window tty parameters */
  81.    int insert_mode;               /* true if inserting */
  82.    int scroll_r1,  scroll_r2;           /* scrolling region */
  83.    int cursor_row, cursor_col;           /* row column of cursor (0, 0) origin */
  84.    
  85.    int visible;                   /* from visibilitynotify */
  86.    Cursor mouse;
  87.    
  88. } JXWindow_Type;
  89.    
  90. static JXWindow_Type This_X_Window;
  91. static JXWindow_Type *XWin;
  92.  
  93. static Display *This_XDisplay;
  94. static Window This_XWindow;
  95. static int This_XScreen;
  96. static int Performing_Update;
  97. static int No_XEvents;               /* if true, do nothing */
  98.  
  99. typedef struct 
  100. {
  101.    char *name;
  102.    char *name1;
  103.    int type;
  104.    char *value;
  105.    char **dflt;
  106. }
  107. XWindow_Arg_Type;
  108.  
  109. static char *This_App_Name = "XJed";
  110. static char *This_App_Title = "XJed";
  111. #define Default_Geometry "80x24+0-0"
  112. static char *This_Geometry = NULL;
  113. static char *This_Font_Name = "fixed";
  114. static char *This_Border_Width_Name = "0";
  115. static char *This_MFG = "green";
  116. static char *This_MBG = "white";
  117.  
  118. static GC_Info_Type Default_GC_Info[JMAX_COLORS] = 
  119. {
  120.    {NULL, 0, 0, "black", "white"},     /* NORMAL */
  121.    {NULL, 0, 0, "green", "red"},       /* CURSOR */
  122.    {NULL, 0, 0, "black", "skyblue"},   /* STATUS */
  123.    {NULL, 0, 0, "black", "magenta"},      /* REGION */
  124.    {NULL, 0, 0, "black", "skyblue"},      /* MENU */
  125.    {NULL, 0, 0, "black", "white"},     /* operator */
  126.    {NULL, 0, 0, "green", "white"},     /* numbers */
  127.    {NULL, 0, 0, "blue", "white"},      /* strings */
  128.    {NULL, 0, 0, "black", "gray"},      /* comments */
  129.    {NULL, 0, 0, "red", "white"},       /* keyword */
  130.    {NULL, 0, 0, "black", "white"},      /* delimeters */
  131.    {NULL, 0, 0, "magenta", "white"}      /* preprocess */
  132. };
  133.  
  134. static XWindow_Arg_Type X_Arg_List[] =
  135. {
  136.    /* These MUST be in this order!!! */
  137.    {"Display",        "d",     STRING_TYPE,    NULL,    NULL},
  138.    {"Name",        NULL,    STRING_TYPE,    NULL,    &This_App_Name},
  139.    {"Geometry",        NULL,     STRING_TYPE,    NULL,    &This_Geometry},
  140.  
  141.    /* These are in arbitrary order */
  142.    {"Font",        "fn",    STRING_TYPE,    NULL,    &This_Font_Name},
  143.    {"Mouse_fg",        "mfg",     STRING_TYPE,    NULL,    &This_MFG},
  144.    {"Mouse_bg",        "mbg",     STRING_TYPE,    NULL,    &This_MBG},
  145.    {"Background",    "bg",     STRING_TYPE,    NULL,    &Default_GC_Info[JNORMAL_COLOR].bg_name},
  146.    {"Foreground",    "fg",    STRING_TYPE,    NULL,    &Default_GC_Info[JNORMAL_COLOR].fg_name},
  147.    {"Status_fg",    "sfg",     STRING_TYPE,    NULL,    &Default_GC_Info[JSTATUS_COLOR].fg_name},
  148.    {"Status_bg",    "sbg",     STRING_TYPE,    NULL,    &Default_GC_Info[JSTATUS_COLOR].bg_name},
  149.    {"Region_fg",    "rfg",     STRING_TYPE,    NULL,    &Default_GC_Info[JREGION_COLOR].fg_name},
  150.    {"Region_bg",    "rbg",     STRING_TYPE,    NULL,    &Default_GC_Info[JREGION_COLOR].bg_name},
  151.    {"Cursor_fg",    "cfg",     STRING_TYPE,    NULL,    &Default_GC_Info[JCURSOR_COLOR].fg_name},
  152.    {"Cursor_bg",    "cbg",     STRING_TYPE,    NULL,    &Default_GC_Info[JCURSOR_COLOR].bg_name},
  153.    {"Menu_fg",        "mfg",     STRING_TYPE,    NULL,    &Default_GC_Info[JMENU_COLOR].fg_name},
  154.    {"Menu_bg",        "mbg",     STRING_TYPE,    NULL,    &Default_GC_Info[JMENU_COLOR].bg_name},
  155.    {"Operator_fg",    "opfg",    STRING_TYPE,    NULL,    &Default_GC_Info[JOP_COLOR].fg_name},
  156.    {"Operator_bg",    "opbg",    STRING_TYPE,    NULL,    &Default_GC_Info[JOP_COLOR].bg_name},
  157.    {"Number_fg",    "nmfg",    STRING_TYPE,    NULL,    &Default_GC_Info[JNUM_COLOR].fg_name},
  158.    {"Number_bg",    "nmbg",    STRING_TYPE,    NULL,    &Default_GC_Info[JNUM_COLOR].bg_name},
  159.    {"String_fg",    "stfg",    STRING_TYPE,    NULL,    &Default_GC_Info[JSTR_COLOR].fg_name},
  160.    {"String_bg",    "stbg",    STRING_TYPE,    NULL,    &Default_GC_Info[JSTR_COLOR].bg_name},
  161.    {"Comments_fg",    "cofg",    STRING_TYPE,    NULL,    &Default_GC_Info[JCOM_COLOR].fg_name},
  162.    {"Comments_bg",    "cobg",    STRING_TYPE,    NULL,    &Default_GC_Info[JCOM_COLOR].bg_name},
  163.    {"Keyword_fg",    "kwfg",    STRING_TYPE,    NULL,    &Default_GC_Info[JKEY_COLOR].fg_name},
  164.    {"Keyword_bg",    "kwbg",    STRING_TYPE,    NULL,    &Default_GC_Info[JKEY_COLOR].bg_name},
  165.    {"Delimiter_fg",    "defg",    STRING_TYPE,    NULL,    &Default_GC_Info[JDELIM_COLOR].fg_name},
  166.    {"Delimiter_bg",    "debg",    STRING_TYPE,    NULL,    &Default_GC_Info[JDELIM_COLOR].bg_name},
  167.    {"Preprocess_fg",    "prfg",    STRING_TYPE,    NULL,    &Default_GC_Info[JPREPROC_COLOR].fg_name},
  168.    {"Preprocess_bg",    "prbg",    STRING_TYPE,    NULL,    &Default_GC_Info[JPREPROC_COLOR].bg_name},
  169.  
  170.    {"Borderwidth",    "bw",     STRING_TYPE,    NULL,    &This_Border_Width_Name},
  171.    {"Title",        NULL,    STRING_TYPE,    NULL,    &This_App_Title},
  172.    {"Bordercolor",    "bd",     STRING_TYPE,    NULL,    NULL},
  173.    {"Iconic",        NULL,    VOID_TYPE,    NULL,    NULL},
  174.    {"xrm",        NULL,    STRING_TYPE,    NULL,    NULL},
  175.    {NULL,        NULL,    0,        NULL,    NULL}
  176. };
  177.  
  178.  
  179. static void hide_cursor (void)
  180. {
  181.    unsigned short *s;
  182.    char ch;
  183.    int b = XWin->border, col = XWin->vis_curs_col, row = XWin->vis_curs_row;
  184.  
  185.    if (No_XEvents) return;
  186.    if (XWin->cursor_showing == 0) return;
  187.    XWin->cursor_showing = 0;
  188.    
  189.    s = JScreen[row].old;
  190.    if (s == NULL) return;
  191.    s += col;
  192.    ch = (char) (*s & 0xFF);
  193.    
  194.    XDrawImageString(This_XDisplay, XWin->w,
  195.             XWin->text_gc[*s >> 8].gc,
  196.             col * XWin->font_width + b,
  197.             row * XWin->font_height + b + XWin->font_base,
  198.             &ch, 1);
  199.    
  200. }
  201.  
  202. /* This routine assumes that cursor is in the correct location.  The 
  203.    cursor is placed at the end of the string. */
  204. static void tt_write(char *s, int n)
  205. {
  206.    int b = XWin->border;
  207.    if (XWin->window_mapped == 0) return;
  208.    if (No_XEvents) return;
  209.    if (XWin->cursor_showing) hide_cursor ();
  210.    XDrawImageString(This_XDisplay, This_XWindow, XWin->current_gc,
  211.             (XWin->cursor_col) * XWin->font_width + b,
  212.             (XWin->cursor_row) * XWin->font_height + b + XWin->font_base,
  213.             s, n);
  214.            
  215.    XWin->cursor_col += n;
  216.    if (XWin->cursor_col >= JX_Screen_Cols) XWin->cursor_col = JX_Screen_Cols - 1;
  217. }
  218.  
  219.  
  220.  
  221. static void copy_rect(int x1, int y1, int x2, int y2, int x3, int y3)
  222. {
  223.    int w, h;
  224.    
  225.    if (No_XEvents) return;
  226.    if (XWin->window_mapped == 0) return;
  227.  
  228.    w = (x2 - x1) * XWin->font_width;
  229.    h = (y2 - y1) * XWin->font_height;
  230.    
  231.    if ((w <= 0) || (h <= 0)) return;
  232.    
  233.    x3 = XWin->border + x3 * XWin->font_width; 
  234.    x1 = XWin->border + x1 * XWin->font_width; 
  235.    y3 = XWin->border + y3 * XWin->font_height;
  236.    y1 = XWin->border + y1 * XWin->font_height;
  237.    hide_cursor ();
  238.    XCopyArea (This_XDisplay, This_XWindow, This_XWindow, XWin->current_gc,
  239.           x1, y1, w, h, x3, y3);
  240. }
  241.  
  242. static void blank_rect (int x1,  int y1, int x2, int y2)
  243. {
  244.    int w, h;
  245.    
  246.    if (No_XEvents) return;
  247.    if (XWin->window_mapped == 0) return;
  248.  
  249.    w = (x2 - x1) * XWin->font_width;
  250.    h = (y2 - y1) * XWin->font_height;
  251.    
  252.    if ((w <= 0) || (h <= 0)) return;
  253.    
  254.    x1 = XWin->border + x1 * XWin->font_width; 
  255.    y1 = XWin->border + y1 * XWin->font_height;
  256.    hide_cursor ();
  257.    XClearArea (This_XDisplay, This_XWindow, x1, y1, w, h, 0);
  258. }
  259.  
  260. void JX_set_scroll_region(int r1, int r2)
  261. {
  262.     XWin->scroll_r1 = r1;
  263.     XWin->scroll_r2 = r2;
  264. }
  265.  
  266. void JX_reset_scroll_region (void)
  267. {
  268.    XWin->scroll_r1 = 0;
  269.    XWin->scroll_r2 = JX_Screen_Rows - 1;
  270. }
  271.  
  272.  
  273. static void show_cursor (void)
  274. {
  275.    unsigned short *s;
  276.    char ch;
  277.    int c, r, b;
  278.    GC gc;
  279.    
  280.    if (No_XEvents) return;
  281.    if (XWin->cursor_showing) hide_cursor ();
  282.  
  283.    XWin->cursor_showing = 1;
  284.    r = XWin->vis_curs_row = XWin->cursor_row;
  285.    c = XWin->vis_curs_col = XWin->cursor_col;
  286.    b = XWin->border;
  287.    
  288.    s = JScreen[r].old;
  289.    if (s == NULL) return;
  290.    
  291.    s += c;
  292.    ch = (char) (*s & 0xFF);
  293.    gc = XWin->text_gc[JCURSOR_COLOR].gc;
  294.       
  295.    if (XWin->focus)
  296.      {
  297.     XDrawImageString(This_XDisplay, This_XWindow, 
  298.              gc, 
  299.              c * XWin->font_width + b,
  300.              r * XWin->font_height + b + XWin->font_base,
  301.              &ch, 1);
  302.      }
  303.    else
  304.      {
  305.     XDrawRectangle( This_XDisplay, This_XWindow, 
  306.                gc,
  307.                c * XWin->font_width + b,
  308.                r * XWin->font_height + b,
  309.                XWin->font_width - 1,
  310.                XWin->font_height - 1);
  311.      }
  312.    
  313.    XFlush(This_XDisplay);
  314. }
  315.  
  316.  
  317. static void toggle_cursor (int on)
  318. {
  319.    if (on)
  320.      {
  321.     if (XWin->focus) return;
  322.     XWin->focus = 1;
  323.      }
  324.    else 
  325.      {
  326.     if (XWin->focus == 0) return;
  327.     XWin->focus = 0;
  328.      }
  329.    show_cursor ();
  330. }
  331.  
  332.    
  333. void JX_write_string (char *s)
  334. {
  335.    tt_write(s, strlen(s));
  336.    if (Performing_Update) return;
  337.    show_cursor ();
  338. }
  339.    
  340.  
  341. void JX_goto_rc(int r, int c)
  342. {
  343.    if (XWin == NULL) return;
  344.    if (XWin->cursor_showing) hide_cursor ();
  345.    if (r >= JX_Screen_Rows) r = JX_Screen_Rows - 1; 
  346.    if (c >= JX_Screen_Cols) c = JX_Screen_Cols - 1; 
  347.    XWin->cursor_row = r + XWin->scroll_r1;
  348.    XWin->cursor_col = c;
  349.    if (Performing_Update) return;
  350.    show_cursor ();
  351. }
  352.  
  353. void JX_begin_insert(void)
  354. {
  355.    XEvent ev;
  356.    
  357.    if (No_XEvents) return;
  358.    hide_cursor ();
  359.    copy_rect(XWin->cursor_col, XWin->cursor_row, JX_Screen_Cols - 1, XWin->cursor_row + 1,
  360.          XWin->cursor_col + 1, XWin->cursor_row);
  361.    XWin->insert_mode = 1;
  362.    
  363.    /* The noexpose events really mess up input pending timing.  
  364.       Stop them now. */
  365.    XFlush(This_XDisplay);
  366.    if (!XPeekEvent(This_XDisplay, &ev) || (ev.type != NoExpose)) return;
  367.    XNextEvent(This_XDisplay, &ev);
  368. }
  369.  
  370. void JX_end_insert(void)
  371. {
  372.    XWin->insert_mode = 0;
  373. }
  374.  
  375. void JX_delete_char (void)
  376. {
  377.    copy_rect(XWin->cursor_col + 1, XWin->cursor_row, JX_Screen_Cols, XWin->cursor_row + 1,
  378.          XWin->cursor_col, XWin->cursor_row);
  379. }
  380.  
  381. void JX_erase_line(void)
  382. {
  383.    if (XWin == NULL) return;
  384.    blank_rect(0, XWin->cursor_row, JX_Screen_Cols, XWin->cursor_row + 1);
  385. }
  386.  
  387. /* Must respect scrolling region */
  388. void JX_delete_nlines(int n)
  389. {
  390.    int r1, r2;
  391.    r1 = XWin->cursor_row;
  392.    r2 = XWin->scroll_r2;
  393.    
  394.    if (r1 <= r2 - n) copy_rect(0, r1 + n, JX_Screen_Cols, r2 + 1,
  395.                    0, r1);
  396.    
  397.    if (Scroll_By_Copying == 0) blank_rect(0, r2 - n, JX_Screen_Cols, r2);
  398. }
  399.  
  400.  
  401. void JX_reverse_index(int n)
  402. {
  403.    int r1, r2;
  404.    r1 = XWin->scroll_r1;
  405.    r2 = XWin->scroll_r2;
  406.    
  407.    if (r2 >= r1 + n) copy_rect(0, r1, JX_Screen_Cols, r2 - n + 1,
  408.                    0, r1 + n);
  409.    
  410.    if (Scroll_By_Copying == 0) blank_rect(0, r1, JX_Screen_Cols, r1 + n); 
  411. }
  412.  
  413. void JX_beep(void)
  414. {
  415.    GC gc;
  416.    XGCValues gcv;
  417.    
  418.    if (No_XEvents) return;
  419.    flush_input();
  420.    if (JX_Ignore_Beep & 0x1) XBell (This_XDisplay, 50);
  421.    
  422.    /* visible bell */
  423.  
  424.    if (JX_Ignore_Beep & 0x2)
  425.      {
  426.     gc = XCreateGC(This_XDisplay, This_XWindow, 0, &gcv);
  427.     
  428.         XSetState(This_XDisplay, gc, 
  429.           WhitePixel (This_XDisplay, This_XScreen),
  430.                   BlackPixel(This_XDisplay, This_XScreen), 
  431.           GXinvert, AllPlanes);
  432.  
  433.         XFillRectangle (This_XDisplay, This_XWindow, gc, 
  434.                         0, 0,
  435.             XWin->font_width * JX_Screen_Cols,
  436.             XWin->font_height * JX_Screen_Rows);
  437.                         
  438.         XFlush (This_XDisplay);
  439.     
  440.     /* I attempted to put a pause in here but it was too slow. */
  441.     
  442.     
  443.         XFillRectangle (This_XDisplay, This_XWindow, gc, 
  444.                         0, 0,
  445.             XWin->font_width * JX_Screen_Cols,
  446.             XWin->font_height * JX_Screen_Rows);
  447.     
  448.     XFreeGC(This_XDisplay, gc);
  449.      }   
  450.    XFlush (This_XDisplay);
  451. }
  452.  
  453. void JX_del_eol(void)
  454. {
  455.    blank_rect(XWin->cursor_col, XWin->cursor_row, JX_Screen_Cols, XWin->cursor_row + 1);
  456. }
  457.  
  458. static int Rev_Vid_Flag;
  459. void JX_reverse_video(int color)
  460. {
  461.    Rev_Vid_Flag = color;
  462.    XWin->current_gc = XWin->text_gc[color].gc;
  463. }
  464.  
  465. void JX_normal_video(void)
  466. {
  467.    if (XWin == NULL) return;
  468.    Rev_Vid_Flag = JNORMAL_COLOR;
  469.    XWin->current_gc = XWin->text_gc[JNORMAL_COLOR].gc;
  470. }
  471.  
  472.  
  473.  
  474.  
  475. static void send_attr_str(unsigned short *s, unsigned short *smax)
  476. {
  477.    unsigned char out[250], ch, attr, *p;
  478.    register unsigned short sh;
  479.    
  480.    p = out;
  481.    while (s < smax)
  482.      {
  483.     sh = (unsigned short) *s++;
  484.     ch = sh & 0xFF;
  485.     attr = sh >> 8;
  486.     if ((attr == 0) && (Rev_Vid_Flag != 0))
  487.       {
  488.          if (p != out)
  489.            {
  490.           *p = 0;
  491.           JX_write_string ((char *) out);
  492.           p = out;
  493.            }
  494.          tt_normal_video();
  495.          /* Rev_Vid_Flag = 0; */
  496.       }
  497.     else if ((attr != 0) && (Rev_Vid_Flag != attr))
  498.       {
  499.          if (p != out)
  500.            {
  501.           *p = 0;
  502.           JX_write_string ((char *) out);
  503.           p = out;
  504.            }
  505.          JX_reverse_video(attr);
  506.          /* Rev_Vid_Flag = 1; */
  507.       }
  508.     *p++ = ch;
  509.      }
  510.    *p = 0;
  511.    if (p != out) JX_write_string ((char *) out);
  512.    /* if (Rev_Vid_Flag) tt_normal_video(); */
  513. }
  514.  
  515.  
  516.  
  517. #define SPACE_CHAR (32 | (JNORMAL_COLOR << 8))
  518.  
  519. static void forward_cursor (int n, int row)
  520. {
  521.    JX_goto_rc (row, XWin->cursor_col + n);
  522. }
  523.  
  524. void JX_smart_puts(unsigned short *neww,unsigned short *oldd, int len, int row)
  525. {
  526.    register unsigned short *p, *q, *qmax, *pmax, *buf;
  527.    unsigned short buffer[256];
  528.    int n_spaces;
  529.    unsigned short *space_match, *last_buffered_match;
  530.    
  531.    q = oldd; p = neww;
  532.    qmax = oldd + len;
  533.    pmax = p + len;
  534.    
  535.    /* Find out where to begin --- while they match, we are ok */
  536.    for (;;)
  537.      {
  538.     if (q == qmax) return;
  539.     if (*q != *p) break;
  540.     q++; p++;
  541.      }
  542.  
  543.    /*position the cursor */
  544.    JX_goto_rc (row, (int) (p - neww));
  545.  
  546.    /* Find where the last non-blank character on old/new screen is */
  547.    
  548.    while (qmax > q)
  549.      {
  550.     qmax--;
  551.     if (*qmax != SPACE_CHAR) 
  552.       {
  553.          qmax++;
  554.          break;
  555.       }
  556.      }
  557.    /* if (*qmax != SPACE_CHAR) qmax++; */
  558.    while (pmax > p)
  559.      {
  560.     pmax--;
  561.     if (*pmax != SPACE_CHAR) 
  562.       {
  563.          pmax++;
  564.          break;
  565.       }
  566.      }
  567.    
  568.    last_buffered_match = buf = buffer;               /* buffer is empty */
  569.    
  570.    /* loop using overwrite then skip algorithm until done */
  571.    while (1)
  572.      {
  573.     /* while they do not match and we do not hit a space, buffer them up */
  574.     n_spaces = 0;
  575.     while (p < pmax)
  576.       {
  577.          if ((*q == SPACE_CHAR) && (*p == SPACE_CHAR))
  578.            {
  579.           /* If *q is not a space, we would have to overwrite it.  
  580.            * However, if *q is a space, then while *p is also one, 
  581.            * we only need to skip over the blank field.
  582.            */
  583.           space_match = p;
  584.           p++; q++;
  585.           while ((p < pmax) 
  586.              && (*p == SPACE_CHAR) && (*q == SPACE_CHAR))
  587.             {
  588.                p++;
  589.                q++;
  590.             }
  591.           n_spaces = (int) (p - space_match);
  592.           break;
  593.            }
  594.          if (*q == *p) break;
  595.          *buf++ = *p++;
  596.          q++;
  597.       }
  598.     *buf = 0;
  599.     
  600.     if (buf != buffer) send_attr_str (buffer, buf);
  601.     buf = buffer;
  602.     
  603.     if (n_spaces && (p < pmax)) 
  604.       {
  605.          forward_cursor (n_spaces, row);
  606.       }
  607.     
  608.     /* Now we overwrote what we could and cursor is placed at position 
  609.      * of a possible match of new and old.  If this is the case, skip 
  610.      * some more.
  611.      */
  612.     
  613.     while ((p < pmax) && (*p == *q))
  614.       {
  615.          *buf++ = *p++;
  616.          q++;
  617.       }
  618.     
  619.     last_buffered_match = buf;
  620.     if (p >= pmax) break;
  621.     
  622.     /* jump to new position is it is greater than 5 otherwise
  623.      * let it sit in the buffer and output it later.
  624.      */
  625.     if ((int) (buf - buffer) >= 5) 
  626.       {
  627.          forward_cursor (buf - buffer, row);
  628.          last_buffered_match = buf = buffer;
  629.       }
  630.      }
  631.    if (buf != buffer)
  632.      {
  633.     if (q < qmax)
  634.       {
  635.          if ((buf == last_buffered_match) 
  636.          && ((int) (buf - buffer) >= 5))
  637.            {
  638.           forward_cursor (buf - buffer, row);
  639.            }
  640.          else
  641.            {
  642.           *buf = 0;
  643.           send_attr_str (buffer, buf);
  644.            }
  645.       }
  646.      }
  647.    if (q < qmax) JX_del_eol ();
  648. }  
  649.  
  650. static int push_mouse_event (int type, int x, int y, unsigned int button, unsigned int state )
  651. {
  652.    register unsigned int s = 0, but;
  653.    int ch;
  654.    static int last_button;
  655.  
  656.    if (button == 0) button = last_button;
  657.    JMouse.type = (type == ButtonPress) ? 1 : 0;
  658.    if (JMouse.type) last_button = button;
  659.    
  660.    JMouse.x = 1 + (x - XWin->border) / XWin->font_width;
  661.    JMouse.y = 1 + (y - XWin->border) / XWin->font_height;
  662.    but = JMouse.button = (int) button;
  663.    if (but == Button1) ch = 'l'; else if (but == Button2) ch = 'm'; else ch = 'r';
  664.    if (state & Button1Mask) s |= 1;
  665.    if (state & Button2Mask) s |= 2;
  666.    if (state & Button3Mask) s |= 4;
  667.    if (state & ShiftMask) 
  668.      {
  669.     s |= 16;
  670.     ch = 'A' + (ch - 'a');
  671.      }
  672.    if (state & ControlMask) 
  673.      {
  674.     s |= 8;
  675.     if (ch >= 'a') ch = ch - 'a' + 1;
  676.      }
  677.    JMouse.state = s;
  678.    return ch;
  679. }
  680.  
  681. static void cover_exposed_area (int x, int y, int width, int height, int count)
  682. {
  683.    unsigned short *s, *smax;
  684.    int row, save_row, save_col, max_col, max_row, col;
  685.    
  686.    Performing_Update++;
  687.    hide_cursor ();
  688.    save_row = XWin->cursor_row;
  689.    save_col = XWin->cursor_col;
  690.    col = (x - XWin->border) / XWin->font_width;
  691.    row = (y - XWin->border) / XWin->font_height;
  692.    
  693.    max_col = 2 + col + width / XWin->font_width;
  694.    max_row = 2 + row + height / XWin->font_height;
  695.    if (max_col > JX_Screen_Cols) max_col = JX_Screen_Cols;
  696.    if (max_row > JX_Screen_Rows) max_row = JX_Screen_Rows;
  697.    
  698.    for (XWin->cursor_row = row; XWin->cursor_row < max_row; XWin->cursor_row++)
  699.      {
  700.     XWin->cursor_col = col;
  701.     s = JScreen[XWin->cursor_row].old + XWin->cursor_col;
  702.     smax = JScreen[XWin->cursor_row].old + max_col;
  703.     send_attr_str(s, smax);
  704.      }
  705.    XWin->cursor_row = save_row;
  706.    XWin->cursor_col = save_col;
  707.    Performing_Update--;
  708.  
  709.    if (count == 0) show_cursor ();
  710. }
  711.  
  712. #include "xkeys.c"
  713.  
  714. /* Return 1 if event is listed in the switch or zero otherwise.  The switch
  715.  * events are considered harmless--- that is, processing them does not really
  716.  * interfere with internal JED state (redisplay, etc...).  More bluntly, 
  717.  * harmless means that the events can be processesed while checking for 
  718.  * pending input.
  719.  */
  720. static int x_handle_harmless_events (XEvent *report)
  721. {
  722.    switch (report->type)
  723.      {
  724.       case EnterNotify:
  725.     toggle_cursor(report->xcrossing.focus);
  726.     break;
  727.          
  728.       case LeaveNotify:
  729.     /* toggle_cursor(0); */
  730.     break;
  731.          
  732.       case UnmapNotify: 
  733.     XWin->window_mapped = 0;
  734.     break;
  735.       case MapNotify:
  736.     XWin->window_mapped = 1;
  737.     break;
  738.     
  739.       case FocusIn:
  740.     toggle_cursor(1);
  741.     break;         
  742.     
  743.       case FocusOut:
  744.     toggle_cursor(0);
  745.     break;
  746.     
  747.       case VisibilityNotify: XWin->visible = report->xvisibility.state;
  748.     break;
  749.     
  750.       case GraphicsExpose: 
  751.     cover_exposed_area (report->xgraphicsexpose.x,
  752.                 report->xgraphicsexpose.y,
  753.                 report->xgraphicsexpose.width,
  754.                 report->xgraphicsexpose.height,
  755.                 report->xgraphicsexpose.count);
  756.     break;
  757.          
  758.       case NoExpose: break;
  759.  
  760.       default:
  761.     /* fprintf(stderr, "harmless: %d\n", report->type); */
  762.     return 0;
  763.      }
  764.    return 1;
  765. }
  766.  
  767. static int X_Alt_Char = 27;
  768.  
  769. /* if force is true, wait for an event.  If force is false, only
  770.  *  process events that exist.  This will return either when there 
  771.  *  are no more events or a key/mouse event is processed returning
  772.  *  1 in the process */
  773. static int X_process_events (int force, char *buf, int *n_chars)
  774. {
  775.    XEvent report;
  776.    int ch1;
  777.    int block_expose = 0;
  778.    char *bufp;
  779.    KeySym ks;
  780.    int esc = 27;
  781.    
  782.  
  783.    Window root, child;
  784.    int posx, posy, rootx, rooty;
  785.    unsigned int keys_buttons;
  786.    int last_x, last_y;
  787.    static int last_event, motion_button;
  788.    static unsigned int motion_state;
  789.    
  790.    int width, height;
  791.    
  792.    while (force || XPending(This_XDisplay))
  793.      {
  794.     XNextEvent(This_XDisplay, &report);
  795.     
  796.     switch  (report.type) 
  797.       {
  798.        case MotionNotify:
  799.          
  800.          while (XCheckMaskEvent (This_XDisplay, ButtonMotionMask, &report));
  801.          if (!XQueryPointer(This_XDisplay, report.xmotion.window,
  802.                 &root, &child, &rootx, &rooty, &posx, &posy,
  803.                 &keys_buttons)) break;
  804.  
  805.          /* This will ensure that modifier keys are not pressed while
  806.             we are in motion. */
  807.  
  808.          if ((last_event == MotionNotify) && (motion_state != keys_buttons)) break;
  809.          motion_state = keys_buttons;
  810.  
  811.          last_x = JMouse.x;
  812.          last_y = JMouse.y;
  813.          
  814.          
  815.          ch1 = push_mouse_event (ButtonPress,
  816.                      posx, posy,
  817.                      0,
  818.                      keys_buttons);
  819.  
  820.          if ((last_x == JMouse.x) && (last_y == JMouse.y)) break;
  821.  
  822.          /* return ESC ^@ ^@ .... */
  823.          *buf++ = esc; *buf++ = 0; *buf++ = 0; *buf++ = ch1;
  824.          *n_chars = 4;
  825.          
  826.          last_event = MotionNotify;
  827.          motion_button = JMouse.button;
  828.          return 1;
  829.          
  830.          
  831.        case Expose:
  832.          
  833.          if (block_expose == 0) cover_exposed_area (report.xexpose.x,
  834.                             report.xexpose.y,
  835.                             report.xexpose.width,
  836.                             report.xexpose.height,
  837.                             report.xexpose.count);
  838.          else 
  839.            {
  840.           if (report.xexpose.count == 0)
  841.             {
  842.                redraw_screen (1);
  843.                block_expose = 0;
  844.             }
  845.            }
  846.          break;
  847.          
  848.        case ConfigureNotify:
  849.          width = report.xconfigure.width;
  850.          height = report.xconfigure.height;
  851.          if ((width != XWin->width) || 
  852.          (height != XWin->height))
  853.            {
  854.           XWin->width = width;
  855.           XWin->height = height;
  856.           reset_display ();
  857.           init_display(1);
  858.           block_expose = -1;
  859.            }
  860.          break;
  861.          
  862.        case ButtonPress:
  863.          /* Prohibit dragging more than one button at a time. */
  864.          if (last_event == MotionNotify) break;
  865.          /* drop */
  866.          
  867.        case ButtonRelease:
  868.          if ((last_event == MotionNotify) && 
  869.          (report.xbutton.button != motion_button)) break;
  870.          
  871.          last_event = 0;
  872.          
  873.          /* ESC ^@ U/D is a  mouse prefix */
  874.          *buf++ = esc; *buf++ = 0;
  875.          if (report.type == ButtonPress) ch1 = 'D'; else ch1 = 'U';
  876.          *buf++ = ch1;
  877.          
  878.          *buf++ = push_mouse_event (report.xbutton.type,
  879.                     report.xbutton.x, report.xbutton.y,
  880.                     report.xbutton.button,
  881.                     report.xbutton.state);
  882.          *n_chars = 4;
  883.          return 1;
  884.          break;
  885.          
  886.        case KeyPress:
  887.          bufp = buf;
  888.          *n_chars = XLookupString(&report.xkey, buf, 20, &ks, NULL);
  889.          
  890.          ks = ks & 0xFFFF;
  891.          if (ks >= 0xFF00)
  892.            {
  893.           ks = ks & 0xFF;
  894.           if (report.xkey.state & ShiftMask) bufp = Shift_KeySym_Mapping [ks];
  895.           else if (report.xkey.state & ControlMask) bufp = Control_KeySym_Mapping [ks];
  896.           else bufp = KeySym_Mapping [ks];
  897.           
  898.           if (0 != (*n_chars = (int) *bufp++)) MEMCPY(buf, bufp, *n_chars);
  899.            }
  900.          else if ((*n_chars == 1) && (report.xkey.state & Mod1Mask))
  901.            {
  902.           if (X_Alt_Char <= 0)
  903.             {
  904.                *buf |= 0x80;
  905.             }
  906.           else
  907.             {
  908.                ch1 = *bufp;
  909.                *bufp++ = (unsigned char) X_Alt_Char;
  910.                *bufp = (unsigned char) ch1;
  911.                *n_chars = 2;
  912.             }
  913.            }
  914.          
  915.          if (*n_chars == 0) break;
  916.          return 1;
  917.       
  918.        default:
  919.          (void) x_handle_harmless_events (&report);
  920.       }   
  921.      }
  922.    return 0;
  923. }
  924.  
  925. static int X_read_key (void)
  926. {
  927.    int nread;
  928.    char buf[30];
  929.    (void) X_process_events (1, buf, &nread);
  930.    if (nread > 1) ungetkey_string(buf + 1, nread - 1);
  931.    return (int) *buf;
  932. }
  933.  
  934. static int X_input_pending (void)
  935. {
  936.    XEvent ev;
  937.    int n;
  938.    
  939.    if (No_XEvents) return 0;
  940.  
  941.    n = XPending (This_XDisplay);
  942.    if (!n) return (0);
  943.    
  944.    /* I need some way of getting only kbd events. */ 
  945.    while (n--)
  946.      {
  947.     XPeekEvent(This_XDisplay, &ev);
  948.     if (0 == x_handle_harmless_events (&ev)) return 1;
  949.     XNextEvent(This_XDisplay, &ev);
  950.      }
  951.    return 0;
  952. }
  953.  
  954.  
  955. static void X_Get_Term_Size(int *cols, int *rows)
  956. {
  957.    *cols = (XWin->width - XWin->border) / XWin->font_width;
  958.    *rows = (XWin->height - XWin->border) / XWin->font_height;
  959. }
  960.  
  961. void JX_set_term_vtxxx (int *n)
  962. {
  963. }
  964.  
  965.  
  966. void JX_narrow_width (void)
  967. {
  968. }
  969. void  JX_wide_width (void)
  970. {
  971. }
  972.  
  973. void JX_enable_cursor_keys(void)
  974. {
  975. }
  976.  
  977. void JX_cls(void)
  978. {
  979.    if (No_XEvents) return;
  980.    if (XWin->window_mapped == 0) return;
  981.    XClearWindow(This_XDisplay, This_XWindow);
  982. }
  983.  
  984. /* This function is called assuming that cursor is in correct 
  985.    position */
  986. void JX_putchar(char ch)
  987. {
  988.    if (ch == '\b')
  989.      {
  990.     ch = ' ';
  991.     if (XWin->cursor_col == 0) return;
  992.     XWin->cursor_col--;
  993.      }
  994.    
  995.    if (Rev_Vid_Flag != JNORMAL_COLOR) tt_normal_video();
  996.    tt_write(&ch, 1);
  997.    show_cursor ();
  998. }
  999.  
  1000. /* This routine is called from S-Lang inner interpreter.  It serves
  1001.    as a poor mans version of an interrupt 9 handler */
  1002. static void xjed_check_kbd(void)
  1003. {
  1004.    char buf[30];
  1005.    int n;
  1006.    
  1007.    if (Batch || No_XEvents) return;
  1008.    while (XPending(This_XDisplay))
  1009.      {
  1010.     if (X_process_events (0, buf, &n) == 0) continue;
  1011.     
  1012.     if (*buf == Abort_Char) 
  1013.       {
  1014.          SLang_Error = USER_BREAK;
  1015.          return;
  1016.       }
  1017.     buffer_keystring (buf, n);
  1018.      }
  1019. }
  1020.  
  1021. static void xjed_suspend (void)
  1022. {
  1023.    if (No_XEvents) return;
  1024.    /* XIconifyWindow (This_XDisplay, XWin->w, This_XScreen); */
  1025.    if (XWin->visible == VisibilityUnobscured) XLowerWindow (This_XDisplay, This_XWindow);
  1026.    else XRaiseWindow (This_XDisplay, This_XWindow);
  1027.    return;
  1028. }
  1029.  
  1030. static int load_font (char *font)
  1031. {   
  1032.    static XFontStruct *xfont;
  1033.  
  1034.    xfont = XLoadQueryFont(This_XDisplay, font);
  1035.    if (xfont == NULL) return 0;
  1036.    
  1037.    XWin->font = xfont;
  1038.    XWin->font_name = font;
  1039.    XWin->font_height = XWin->font->ascent + XWin->font->descent;
  1040.    XWin->font_width = XWin->font->max_bounds.width;
  1041.    XWin->font_base = XWin->font->ascent;
  1042.    return 1;
  1043. }
  1044.  
  1045.  
  1046.  
  1047. static void get_xdefaults (void)
  1048. {
  1049.    XWindow_Arg_Type *xargs = X_Arg_List + 2;  /* skip display, name, etc */
  1050.    
  1051.    while (xargs->name != NULL)
  1052.      {
  1053.     if ((xargs->type != VOID_TYPE) && (xargs->dflt != NULL))
  1054.       {
  1055.          if (xargs->value == NULL)
  1056.            {
  1057.           xargs->value = XGetDefault(This_XDisplay, This_App_Name, xargs->name);
  1058.            }
  1059.  
  1060.          if (xargs->value != NULL) 
  1061.            {
  1062.           *xargs->dflt = xargs->value;
  1063.            }
  1064.       }
  1065.     xargs++;
  1066.      }
  1067. }
  1068.  
  1069.  
  1070.  
  1071. static void set_window_name (char *s)
  1072. {
  1073.    if (Batch) return;
  1074.    XStoreName (This_XDisplay, XWin->w, s);
  1075.    XSetIconName(This_XDisplay, XWin->w, s);
  1076. }
  1077.  
  1078. static void set_wm_hints (JXWindow_Type *w, int xpos,  int ypos, int orflags)
  1079. {
  1080.    XSizeHints h;
  1081.    XWMHints h1;
  1082. #if 0
  1083.    XClassHint ch = {"xjed", "XJed"};
  1084. #endif
  1085.    
  1086.    h.width_inc = w->font_width;
  1087.    h.height_inc = w->font_height;
  1088.    h.min_width = 5 * w->font_width + w->border;
  1089.    h.min_height = 5 * w->font_height + w->border;
  1090.    h.base_height = 0;
  1091.    h.base_width = 0;
  1092.    h.x = xpos; h.y = ypos;
  1093.    h.height = w->height;
  1094.    h.width = w->width;
  1095.    
  1096.    h.flags = PMinSize | PResizeInc | PBaseSize;
  1097.    h.flags |= orflags;
  1098.    
  1099.    XSetWMNormalHints(This_XDisplay, w->w, &h);
  1100.    
  1101.    /* This bit allows me to track the focus.  It is not at all clear from 
  1102.       the documentation. */
  1103.    h1.input = 1;
  1104.    h1.flags = InputHint;
  1105.    XSetWMHints(This_XDisplay, w->w, &h1);
  1106. #if 0
  1107.    XSetClassHint(This_XDisplay, w->w, &ch);
  1108. #endif
  1109. }
  1110.  
  1111. /* This parses the colors in the XWin structure and setting 
  1112.    defaults to fg, bg upon failure */
  1113. static void setup_ith_color (int i, unsigned long fg, unsigned long bg)
  1114. {
  1115.    XColor xcol;
  1116.    
  1117.    if (Term_Supports_Color &&
  1118.        XParseColor(This_XDisplay, XWin->color_map, XWin->text_gc[i].fg_name, &xcol)
  1119.        && XAllocColor(This_XDisplay, XWin->color_map, &xcol))
  1120.      {
  1121.     fg = xcol.pixel;
  1122.      }
  1123.    
  1124.    XWin->text_gc[i].fg = fg;
  1125.    
  1126.    if (Term_Supports_Color &&
  1127.        XParseColor(This_XDisplay, XWin->color_map, XWin->text_gc[i].bg_name, &xcol)
  1128.        && XAllocColor(This_XDisplay, XWin->color_map, &xcol))
  1129.      {
  1130.     bg = xcol.pixel;
  1131.      }
  1132.    
  1133.    XWin->text_gc[i].bg = bg;
  1134. }
  1135.  
  1136.  
  1137. /* This is used to set the colors in the Win structure and if f is non-zero,
  1138.    the previous definitions are freed.  f is 0 when the colors correspond to the 
  1139.    default. */
  1140.  
  1141. static void x_set_color_free (int i, char *fgcolor, char *bgcolor, int do_free)
  1142. {
  1143.    char *save_fg, *save_bg, *fg, *bg;
  1144.    unsigned long old_fg, old_bg;
  1145.    
  1146.    if (NULL == (fg = (char *) SLMALLOC(strlen(fgcolor) + 1)))
  1147.      {
  1148.     SLang_Error = SL_MALLOC_ERROR;
  1149.     return;
  1150.      }
  1151.    strcpy (fg, fgcolor);
  1152.    if (NULL == (bg = (char *) SLMALLOC(strlen(bgcolor) + 1)))
  1153.      {
  1154.     SLang_Error = SL_MALLOC_ERROR;
  1155.     SLFREE (fg);
  1156.     return;
  1157.      }
  1158.    strcpy (bg, bgcolor);
  1159.    
  1160.    old_fg = XWin->text_gc[i].fg;
  1161.    old_bg = XWin->text_gc[i].bg;
  1162.    
  1163.    save_fg = XWin->text_gc[i].fg_name;
  1164.    XWin->text_gc[i].fg_name = fg;
  1165.    save_bg = XWin->text_gc[i].bg_name;
  1166.    XWin->text_gc[i].bg_name = bg;
  1167.    
  1168.    setup_ith_color (i, old_fg, old_bg);
  1169.    if (do_free)
  1170.      {
  1171.     if (save_fg != NULL) SLFREE (save_fg);
  1172.     if (save_bg != NULL) SLFREE (save_bg);
  1173.      }
  1174. }
  1175.  
  1176.  
  1177.  
  1178. static void setup_and_parse_colors (void)
  1179. {
  1180.    unsigned long fg, bg, tmp;
  1181.    char *fg_name, *bg_name;
  1182.  
  1183.    int i;
  1184.    GC_Info_Type *d;
  1185.    
  1186.    /* Check to see if this is a color display */
  1187.    
  1188.    bg = WhitePixel (This_XDisplay, This_XScreen); bg_name = "white";
  1189.    fg = BlackPixel (This_XDisplay, This_XScreen); fg_name = "black";
  1190.  
  1191.    XWin->color_map = DefaultColormap (This_XDisplay, This_XScreen);
  1192.  
  1193.    if (DisplayCells (This_XDisplay, This_XScreen) > 2) 
  1194.      {
  1195.     Term_Supports_Color = 1;
  1196.      }
  1197.    else Term_Supports_Color = 0;
  1198.    
  1199.    for (i = 0; i < JMAX_COLORS; i++)
  1200.      {
  1201.     d = Default_GC_Info + i;
  1202.     /* The assumption here is that ALL colors beyond JNORMAL_COLOR (0)
  1203.      * take reversed fg, bgs.  I really ought to have flags if this is
  1204.      * not the case. */
  1205.     d->fg = fg;
  1206.     d->bg = bg;
  1207.     if (d->fg_name == NULL) d->fg_name = fg_name;
  1208.     if (d->bg_name == NULL) d->bg_name = bg_name;
  1209.     
  1210.     if (i == JNORMAL_COLOR)
  1211.       {
  1212.          tmp = fg; fg = bg; bg = tmp;
  1213.          fg_name = bg_name;
  1214.          bg_name = "black";
  1215.       }
  1216.     
  1217.     x_set_color_free (i, d->fg_name, d->bg_name, 0);
  1218.      }
  1219. }
  1220.  
  1221. static void set_mouse_color (char *fgc, char *bgc)
  1222. {
  1223.    XColor xfg, xbg;
  1224.    
  1225.    if (!Term_Supports_Color) return;
  1226.    if (!XParseColor(This_XDisplay, XWin->color_map, fgc, &xfg)
  1227.        || !XAllocColor(This_XDisplay, XWin->color_map, &xfg))
  1228.      {
  1229.     return;
  1230.      }
  1231.  
  1232.    if (!XParseColor(This_XDisplay, XWin->color_map, bgc, &xbg)
  1233.        || !XAllocColor(This_XDisplay, XWin->color_map, &xbg))
  1234.      {
  1235.     return;
  1236.      }
  1237.    XRecolorCursor (This_XDisplay, XWin->mouse, &xfg, &xbg);
  1238. }
  1239.  
  1240.  
  1241.  
  1242. static void create_needed_gcs (void)
  1243. {
  1244.    int i;
  1245.    XGCValues xgcv;
  1246.    xgcv.font = XWin->font->fid;
  1247.    for (i = 0; i < JMAX_COLORS; i++)
  1248.      {
  1249.     xgcv.foreground = XWin->text_gc[i].fg;
  1250.     xgcv.background = XWin->text_gc[i].bg;
  1251.     
  1252.     XWin->text_gc[i].gc = XCreateGC(This_XDisplay, This_XWindow,
  1253.                     GCForeground | GCBackground | GCFont,
  1254.                     &xgcv);
  1255.      }
  1256. }
  1257.  
  1258.  
  1259.  
  1260. static Window create_XWindow (JXWindow_Type *win, char *geom, int orflags)
  1261. {
  1262.    int bdr, xpos, ypos;
  1263.    int width, height, geo;
  1264.    Window w;
  1265.    
  1266.    bdr = atoi(This_Border_Width_Name);
  1267.    
  1268.    width = JX_Screen_Cols; height = JX_Screen_Rows;   
  1269.    xpos = 0, ypos = 0;
  1270.    if (geom != NULL)
  1271.      {
  1272.     geo = XGeometry (This_XDisplay, This_XScreen,
  1273.               geom, Default_Geometry,
  1274.               bdr,
  1275.               win->font_width, win->font_height,
  1276.               win->border, win->border,
  1277.               &xpos, &ypos, 
  1278.               &width, &height);
  1279.         if ((geo & XValue) && (geo & YValue)) orflags |= USPosition;
  1280.         if ((geo & WidthValue) && (geo & HeightValue)) orflags |= USSize;
  1281.      }
  1282.    
  1283.    win->width = width * win->font_width + 2 * win->border;
  1284.    win->height = height * win->font_height + 2 * win->border;
  1285.  
  1286.    /* create and display window */
  1287.    w = XCreateSimpleWindow(This_XDisplay, RootWindow(This_XDisplay, This_XScreen),
  1288.                xpos, ypos,     /* xpos, ypos */
  1289.                win->width,     /* width, height */
  1290.                win->height,     /* width, height */
  1291.                bdr,           /* border width */
  1292.                win->text_gc[JNORMAL_COLOR].fg,
  1293.                win->text_gc[JNORMAL_COLOR].bg 
  1294.                );
  1295.    
  1296.    win->w = w;
  1297.    
  1298.    set_wm_hints (win, xpos, ypos, orflags);
  1299.    
  1300.    /* select event types */
  1301.    XSelectInput(This_XDisplay, w, 
  1302.         ExposureMask | KeyPressMask 
  1303.         | ButtonPressMask | ButtonReleaseMask
  1304.         | StructureNotifyMask
  1305.         | PointerMotionHintMask | ButtonMotionMask
  1306.         | EnterWindowMask
  1307.         /* | LeaveWindowMask */
  1308.         | FocusChangeMask
  1309.         | VisibilityChangeMask
  1310.         );
  1311.    
  1312.    if (XWin->mouse) XDefineCursor(This_XDisplay, w, XWin->mouse);
  1313.    return w;
  1314. }
  1315.  
  1316.  
  1317.  
  1318. static int x_err_handler (Display *d, XErrorEvent *ev)
  1319. {
  1320.    char errmsg[256];
  1321.    No_XEvents = 1;
  1322.    XGetErrorText (d, ev->error_code, errmsg, 255);
  1323.    exit_error (errmsg, 0);
  1324.    return 1;
  1325. }
  1326.  
  1327. static int x_ioerr_handler (Display *d)
  1328. {
  1329.    No_XEvents = 1;
  1330.    exit_error("XWindows IO error", 0);
  1331.    return d == NULL;  /* just use d to avoid a warning */
  1332. }
  1333.  
  1334. /* returns socket descriptor */
  1335. static int init_Xdisplay (void)
  1336. {
  1337.    int orflags = 0;
  1338.    char dname[80], *n;
  1339.    
  1340.    n = X_Arg_List[0].value;
  1341.    if (n != NULL)
  1342.      {
  1343.     strncpy (dname, X_Arg_List[0].value, 70);
  1344.     dname[70] = 0;
  1345.     n = dname;
  1346.     while (*n && (*n != ':')) n++;
  1347.     if (*n == 0) strcpy(n, ":0.0");
  1348.     n = dname;
  1349.      }
  1350.    
  1351.    XSetIOErrorHandler (x_ioerr_handler);
  1352.  
  1353.    if ( (This_XDisplay = XOpenDisplay(n)) == NULL )
  1354.      {
  1355.       (void) fprintf( stderr, "XJED: cannot connect to X server %s\n", 
  1356.                XDisplayName(n));
  1357.     exit( -1 );
  1358.      }
  1359.    
  1360.    XSetErrorHandler (x_err_handler);
  1361.  
  1362.    if (X_Arg_List[1].value != NULL) This_App_Name = X_Arg_List[1].value;
  1363.    XWin = &This_X_Window;
  1364.    get_xdefaults ();
  1365.    
  1366.    XWin->font_name = This_Font_Name;
  1367.  
  1368.    This_XScreen = DefaultScreen(This_XDisplay);
  1369.  
  1370.    if (!load_font(XWin->font_name))
  1371.      {
  1372.     (void) fprintf( stderr, "XJED: cannot load font %s, using fixed.\n", XWin->font_name);
  1373.     if (!load_font("fixed"))
  1374.       {
  1375.          (void) fprintf( stderr, "XJED: cannot load fixed font.\n");
  1376.          exit( -1 );
  1377.       }
  1378.      }
  1379.    
  1380.    
  1381.    XWin->text_gc = Default_GC_Info;
  1382.    setup_and_parse_colors ();               /* This allocs and parses colors */
  1383.    
  1384.    XWin->mouse = XCreateFontCursor (This_XDisplay, XC_xterm);
  1385.    set_mouse_color (This_MFG, This_MBG);
  1386.    
  1387.    /* USPosition and USSize are now set in create_XWindow depending on
  1388.     * what the user specified in the geometry string */
  1389.    /* if (X_Arg_List[2].value != NULL) orflags = USPosition | USSize; */
  1390.    
  1391.    This_XWindow = create_XWindow(XWin, This_Geometry, orflags);
  1392.    
  1393.    set_window_name (This_App_Title);
  1394.    
  1395.    /* GCs and their colors */
  1396.    create_needed_gcs ();               /* This uses info from previous call */
  1397.    
  1398.    XWin->current_gc = XWin->text_gc[JNORMAL_COLOR].gc;
  1399.    
  1400.    XSetFont (This_XDisplay, XWin->current_gc, XWin->font->fid);
  1401.  
  1402.    /* display window */
  1403.    
  1404.    XMapWindow(This_XDisplay, This_XWindow);
  1405.    
  1406.    return ConnectionNumber (This_XDisplay);
  1407. }
  1408.  
  1409.  
  1410. static void reset_Xdisplay (void)
  1411. {
  1412.    if (This_XDisplay != NULL) XCloseDisplay(This_XDisplay);
  1413. }
  1414.  
  1415.  
  1416. #define UPCSE(x)  (((x) <= 'z') && ((x) >= 'a') ? (x) - 32 : (x))
  1417. static int myXstrcmp(char *a, char *b)
  1418. {
  1419.    register char cha, chb;
  1420.    /* do simple comparison */
  1421.    
  1422.    cha = *a++;  chb = *b++;
  1423.    if ((cha != chb) && (UPCSE(cha) != UPCSE(chb))) return 0;
  1424.    while ((cha = *a++), (chb = *b++), (cha && chb) != 0)
  1425.      {
  1426.     if (cha != chb) return 0;
  1427.      }
  1428.    
  1429.    return (cha == chb);
  1430. }
  1431.  
  1432. #define STREQS(a, b) myXstrcmp(a, b)
  1433.  
  1434. static int X_eval_command_line (int argc, char **argv)
  1435. {
  1436.    char *arg;
  1437.    int i;
  1438.    XWindow_Arg_Type *opt;
  1439.    
  1440.    for (i = 1; i < argc; i++)
  1441.      {
  1442.     arg = argv[i];
  1443.     if (*arg != '-') break;
  1444.     arg++;
  1445.     opt = X_Arg_List;
  1446.     while (opt->name != NULL)
  1447.       {
  1448.          if (STREQS(opt->name, arg) 
  1449.          || ((opt->name1 != NULL) && STREQS(opt->name1, arg))) break;
  1450.          opt++;
  1451.       }
  1452.     
  1453.     if (opt->name == NULL) break;
  1454.     
  1455.     if (opt->type == VOID_TYPE) opt->value = "on";
  1456.     else if (i + 1 < argc)
  1457.       {
  1458.          i++;
  1459.          opt->value = argv[i];
  1460.       }
  1461.     else break;
  1462.      }
  1463.    
  1464.    /* Out of this loop, argv[i] is the last unprocessed argument */
  1465.    return i;
  1466. }
  1467.  
  1468.  
  1469.  
  1470. void JX_set_color (int i, char *what, char *fg, char *bg)
  1471. {
  1472.    if (!Term_Supports_Color) return;
  1473.  
  1474.    if (i == -1)
  1475.      {
  1476.     if (!strcmp("mouse", what))
  1477.       {
  1478.          set_mouse_color (fg, bg);
  1479.       }
  1480.     
  1481.     return;
  1482.      }
  1483.    
  1484.    x_set_color_free (i, fg, bg, 1);
  1485.    XSetForeground(This_XDisplay, XWin->text_gc[i].gc, XWin->text_gc[i].fg);
  1486.    XSetBackground(This_XDisplay, XWin->text_gc[i].gc, XWin->text_gc[i].bg);
  1487. }
  1488.  
  1489. static int X_Warp_Pending = 0;
  1490. static void x_warp_pointer (void)
  1491. {
  1492.    X_Warp_Pending = 1;
  1493. }
  1494.  
  1495. static void x_region_2_cutbuffer (void)
  1496. {
  1497.    int nbytes;
  1498.    char *dat;
  1499.  
  1500.    dat = make_buffer_substring(&nbytes);
  1501.    if (dat == NULL) return;
  1502.  
  1503.    XStoreBytes (This_XDisplay, dat, nbytes);
  1504.    XSetSelectionOwner (This_XDisplay, XA_PRIMARY, None, CurrentTime);
  1505.    SLFREE (dat);
  1506. }
  1507.  
  1508. static int x_insert_cutbuffer (void)
  1509. {
  1510.    int nbytes;
  1511.    char *dat;
  1512.  
  1513.    CHECK_READ_ONLY
  1514.    dat = XFetchBytes (This_XDisplay, &nbytes);
  1515.    if (nbytes && (dat != NULL)) ins_chars ((unsigned char *) dat, nbytes);
  1516.    if (dat != NULL) XFree (dat);
  1517.    return nbytes;
  1518. }
  1519.  
  1520. static void x_set_keysym (int *np, int *shift, char *str)
  1521. {
  1522.    unsigned int n = (unsigned int) *np;
  1523.    KeySym_Mapping_Type *map;
  1524.    
  1525.    n &= 0xFF;
  1526.    str = SLang_process_keystring (str);
  1527.    if (*shift == '$') map = Shift_KeySym_Mapping;
  1528.    else if (*shift == '^') map = Control_KeySym_Mapping;
  1529.    else map = KeySym_Mapping;
  1530.    MEMCPY (map[n], str, MAX_KEYSYM_STRING_LEN);
  1531.    
  1532.    *(map[n]) -= 1;
  1533. }
  1534.  
  1535.   
  1536.    
  1537. static SLang_Name_Type sl_x_table[] =
  1538. {
  1539.    MAKE_INTRINSIC(".x_set_window_name", set_window_name, VOID_TYPE, 1),
  1540.    MAKE_INTRINSIC(".x_warp_pointer", x_warp_pointer, VOID_TYPE, 0),
  1541.    MAKE_INTRINSIC(".x_insert_cutbuffer", x_insert_cutbuffer, INT_TYPE, 0),
  1542.    /*Prototype: Integer x_insert_cut_buffer ();
  1543.      Inserts cutbuffer into the current buffer and returns the number
  1544.      of characters inserted.
  1545.      */
  1546.    MAKE_INTRINSIC(".x_copy_region_to_cutbuffer", x_region_2_cutbuffer, VOID_TYPE, 0),
  1547.    /*Prototype: Void x_copy_region_to_cutbuffer();
  1548.     */
  1549.    MAKE_INTRINSIC(".x_set_keysym", x_set_keysym, VOID_TYPE, 3),
  1550.   /*Prototype Void x_set_keysym (Integer keysym, Integer shift, String str);
  1551.    * 
  1552.    * This function may be used to assocate a string 'str' with a key 'keysym'
  1553.    * modified by mask 'shift'. Pressing the key associated with 'keysym' will
  1554.    * then generate the keysequence given by 'str'. The function keys are
  1555.    * mapped to integers in the range 0xFF00 to 0xFFFF.  On most systems, the
  1556.    * keys that these mappings refer to are located in the file
  1557.    * /usr/include/X11/keysymdef.h. For example, on my system, the keysyms for
  1558.    * the function keys XK_F1 to XK_F35 fall in the range 0xFFBE to 0xFFE0.
  1559.    * So to make the 'F1' key correspond to the string given by the two
  1560.    * characters Ctrl-X Ctrl-C, simply use:
  1561.    * 
  1562.    *      x_set_keysym (0xFFBE, 0, "^X^C");
  1563.    *      
  1564.    * The 'shift' argument is an integer with the following meanings:
  1565.    * 
  1566.    *     0   : unmodified key
  1567.    *    '$'  : shifted
  1568.    *    '^'  : control
  1569.    *    
  1570.    * Any other value for shift will default to 0 (unshifted).
  1571.    *      
  1572.    */
  1573.    MAKE_VARIABLE(".ALT_CHAR", &X_Alt_Char, INT_TYPE, 0),
  1574.  
  1575.      
  1576.    /*Prototype: Void x_copy_region_to_cutbuffer();
  1577.     */
  1578.       
  1579.    SLANG_END_TABLE
  1580. };
  1581.  
  1582.  
  1583. static int X_init_slang (void)
  1584. {
  1585.    return (SLang_add_table(sl_x_table, "XJed") && SLdefine_for_ifdef("XWINDOWS"));
  1586. }
  1587.  
  1588.  
  1589. static void X_update_open (void)
  1590. {
  1591.    hide_cursor ();
  1592.    Performing_Update = 1;
  1593. }
  1594.  
  1595. static void X_update_close (void)
  1596. {
  1597.    Performing_Update = 0;
  1598.    if (XWin->window_mapped == 0) JWindow->trashed = 1;
  1599.    if (JWindow->trashed) return;
  1600.    show_cursor ();
  1601.    if (X_Warp_Pending) XWarpPointer (This_XDisplay, None, XWin->w, 0, 0, 0, 0,
  1602.                      XWin->vis_curs_col * XWin->font_width + XWin->border,
  1603.                      (XWin->vis_curs_row + 1) * XWin->font_height + XWin->border);
  1604.    X_Warp_Pending = 0;
  1605. }
  1606.  
  1607. static void x_define_xkeys (SLKeyMap_List_Type *map)
  1608. {
  1609.    SLang_define_key1("^[[^D", (VOID *) scroll_right, SLKEY_F_INTRINSIC, map);
  1610.    SLang_define_key1("^[[d", (VOID *) scroll_right, SLKEY_F_INTRINSIC, map);
  1611.    SLang_define_key1("^[[^C", (VOID *) scroll_left, SLKEY_F_INTRINSIC, map);
  1612.    SLang_define_key1("^[[c", (VOID *) scroll_left, SLKEY_F_INTRINSIC, map);
  1613.    SLang_define_key1("^[[a", (VOID *) bob, SLKEY_F_INTRINSIC, map);
  1614.    SLang_define_key1("^[[^A", (VOID *) bob, SLKEY_F_INTRINSIC, map);
  1615.    SLang_define_key1("^[[b", (VOID *) eob, SLKEY_F_INTRINSIC, map);
  1616.    SLang_define_key1("^[[^B", (VOID *) eob, SLKEY_F_INTRINSIC, map);
  1617. }
  1618.  
  1619. void JX_reset_video (void)
  1620. {
  1621.    tt_normal_video ();
  1622. }
  1623.  
  1624.  
  1625. void JX_init_video (void)
  1626. {
  1627. }
  1628.  
  1629.  
  1630. void flush_output (void)
  1631. {
  1632.    fflush (stdout);
  1633. }
  1634.  
  1635.  
  1636. void JX_get_terminfo (void)
  1637. {
  1638.    JX_Screen_Cols = 80;
  1639.    JX_Screen_Rows = 24;
  1640.    Scroll_By_Copying = 1;
  1641.    
  1642.    /* init hooks */
  1643.    X_Read_Hook = X_read_key;
  1644.    X_Input_Pending_Hook = X_input_pending; 
  1645.    X_Get_Term_Size_Hook = X_Get_Term_Size;
  1646.    X_Update_Open_Hook = X_update_open;
  1647.    X_Update_Close_Hook = X_update_close;
  1648.    X_Suspend_Hook = xjed_suspend;
  1649.    X_Argc_Argv_Hook = X_eval_command_line;
  1650.    X_Init_SLang_Hook = X_init_slang;
  1651.    X_Init_Term_Hook = init_Xdisplay;
  1652.    X_Reset_Term_Hook = reset_Xdisplay;
  1653.    X_Define_Keys_Hook = x_define_xkeys;
  1654.    SLang_Interrupt = xjed_check_kbd;   
  1655. }
  1656.  
  1657. /* the links to functions and variables here */
  1658. void (*tt_goto_rc)(int, int)          = JX_goto_rc;
  1659. void (*tt_begin_insert)(void)          = JX_begin_insert;
  1660. void (*tt_end_insert)(void)          = JX_end_insert;
  1661. void (*tt_del_eol)(void)          = JX_del_eol;
  1662. void (*tt_delete_nlines)(int)          = JX_delete_nlines;
  1663. void (*tt_delete_char)(void)          = JX_delete_char;
  1664. void (*tt_erase_line)(void)          = JX_erase_line;
  1665. void (*tt_tt_normal_video)(void)      = JX_normal_video;
  1666. void (*tt_cls)(void)              = JX_cls;
  1667. void (*tt_beep)(void)              = JX_beep;
  1668. void (*tt_reverse_index)(int)         = JX_reverse_index;
  1669. void (*tt_smart_puts)(unsigned short *, unsigned short *, int, int)  = JX_smart_puts;
  1670. void (*tt_write_string)(char *)      = JX_write_string;
  1671. void (*tt_putchar)(char)          = JX_putchar;
  1672. void (*tt_init_video)(void)          = JX_init_video;
  1673. void (*tt_reset_video)(void)          = JX_reset_video;
  1674. void (*tt_normal_video)(void)          = JX_normal_video;
  1675. void (*tt_set_scroll_region)(int, int)  = JX_set_scroll_region;
  1676. void (*tt_reset_scroll_region)(void)      = JX_reset_scroll_region;
  1677. void (*tt_get_terminfo)(void)          = JX_get_terminfo;
  1678. void (*tt_set_color)(int, char *, char *, char *) = JX_set_color;
  1679. void (*tt_set_color_esc)(int, char *);
  1680.  
  1681. void (*tt_wide_width)(void)          = JX_wide_width;
  1682. void (*tt_narrow_width)(void)          = JX_narrow_width;
  1683. void (*tt_enable_cursor_keys)(void)      = JX_enable_cursor_keys;
  1684. void (*tt_set_term_vtxxx)(int *)      = JX_set_term_vtxxx;
  1685.  
  1686. int *tt_Ignore_Beep          = &JX_Ignore_Beep;
  1687. int *tt_Use_Ansi_Colors      = &JX_Use_Ansi_Colors;
  1688. int *tt_Term_Cannot_Scroll      = &JX_Term_Cannot_Scroll;
  1689. int *tt_Term_Cannot_Insert      = &JX_Term_Cannot_Insert;
  1690. int *tt_Screen_Rows          = &JX_Screen_Rows;
  1691. int *tt_Screen_Cols          = &JX_Screen_Cols;
  1692.  
  1693. static int Not_Used;
  1694. int *tt_Baud_Rate               = &Not_Used;
  1695.