This is xterm.c in view mode; [Download] [Up]
/* This is my first attempt at X for JED. */ /* * Copyright (c) 1992, 1995 John E. Davis (davis@space.mit.edu) * All Rights Reserved. */ #include <config.h> #ifndef VMS #include <X11/Xlib.h> #include <X11/Xutil.h> /* #include <X11/Xos.h> */ #include <X11/Xatom.h> #include <X11/keysym.h> #include <X11/cursorfont.h> #include <X11/Intrinsic.h> #if XtSpecificationRelease >= 6 # define XJED_USE_R6IM # include <X11/Xlocale.h> #endif #else #include <decw$include/Xlib.h> #include <decw$include/Xutil.h> /* #include <decw$include/Xos.h> */ #include <decw$include/Xatom.h> #include <decw$include/keysym.h> #include <decw$include/cursorfont.h> #endif #include <stdio.h> #include <slang.h> #include <string.h> #include <ctype.h> /* #include "xterm.h"*/ #include "display.h" #include "sysdep.h" #include "screen.h" #include "keymap.h" #include "hooks.h" #include "ins.h" #include "ledit.h" #include "misc.h" #include "cmds.h" #include "sig.h" #include "file.h" static int JX_Screen_Cols; static int JX_Screen_Rows; static int JX_Term_Cannot_Scroll = 0; static int JX_Term_Cannot_Insert = 0; static int JX_Use_Ansi_Colors = 1; static int JX_Ignore_Beep = 3; static int JX_Blink_Mode = 1; #ifdef XJED_USE_R6IM static char *R6IM_Input_Method = NULL; static char *R6IM_Preedit_Type = "Root"; static XIC R6IM_Xic; static void i18init(void); #endif typedef struct { GC gc; unsigned long fg, bg; char *fg_name; char *bg_name; } GC_Info_Type; typedef struct { Window w; Atom wm_del_win; /* delete window protocol */ int height, width; int border; /* inside border */ int o_border; /* outside border */ Colormap color_map; /* font information */ XFontStruct *font; char *font_name; int font_height, font_width, font_base; /* GC info */ GC_Info_Type *text_gc; GC current_gc; GC_Info_Type pointer_gc; int vis_curs_row, vis_curs_col; /* position of VISIBLE cursor */ /* flags */ int cursor_showing; /* true if widow has cursor showing */ int focus; /* true if window has focus */ int window_mapped; /* true if window is mapped */ /* Window tty parameters */ int insert_mode; /* true if inserting */ int scroll_r1, scroll_r2; /* scrolling region */ int cursor_row, cursor_col; /* row column of cursor (0, 0) origin */ int visible; /* from visibilitynotify */ Cursor mouse; } JXWindow_Type; static JXWindow_Type This_X_Window; static JXWindow_Type *XWin; static Display *This_XDisplay; static Window This_XWindow; static int This_XScreen; static int Performing_Update; static int Check_Buffers_Pending; static int No_XEvents; /* if true, do nothing */ typedef struct { char *name; char *name1; int type; char *value; char **dflt; } XWindow_Arg_Type; #define XJED_CLASS "XTerm" #define XJED_RESOURCE "xjed" static char *This_App_Name = XJED_RESOURCE; static char *This_App_Title = "XJed"; /* #define Default_Geometry "80x24+0-0" */ #define Default_Geometry "80x24" static char *This_Geometry = NULL; static char *This_Font_Name = "fixed"; static char *This_Border_Width_Name = "0"; static char *This_MFG = "green"; static char *This_MBG = "white"; static char *Iconic = NULL; static GC_Info_Type Default_GC_Info[JMAX_COLORS] = { {NULL, 0, 0, "black", "white"}, /* NORMAL */ {NULL, 0, 0, "green", "red"}, /* CURSOR */ {NULL, 0, 0, "black", "skyblue"}, /* STATUS */ {NULL, 0, 0, "black", "magenta"}, /* REGION */ {NULL, 0, 0, "black", "skyblue"}, /* MENU */ {NULL, 0, 0, "black", "white"}, /* operator */ {NULL, 0, 0, "green", "white"}, /* numbers */ {NULL, 0, 0, "blue", "white"}, /* strings */ {NULL, 0, 0, "black", "gray"}, /* comments */ {NULL, 0, 0, "black", "white"}, /* delimeters */ {NULL, 0, 0, "magenta", "white"}, /* preprocess */ {NULL, 0, 0, "blue", "white"}, /* message */ {NULL, 0, 0, "red", "white"}, /* error */ {NULL, 0, 0, "magenta", "white"}, /* dollar */ {NULL, 0, 0, "red", "white"}, /* keyword */ {NULL, 0, 0, "green", "white"}, /* keyword1 */ {NULL, 0, 0, "red", "white"} /* keyword2 */ }; /* cheat a little, use VOID_TYPE for boolean arguments */ static XWindow_Arg_Type X_Arg_List[] = { /* These MUST be in this order!!! */ #define XARG_DISPLAY 0 {"Display", "d", STRING_TYPE, NULL, NULL}, #define XARG_NAME 1 {"Name", NULL, STRING_TYPE, NULL, &This_App_Name}, #define XARG_GEOMETRY 2 {"Geometry", NULL, STRING_TYPE, NULL, &This_Geometry}, #define XARG_START 2 #if 1 /* Note: it's good to look for * `font', `background', `foreground' * instead of * `Font', `background', `foreground' * so that XTerm names can be used * (resource vs. class names) * * also, change order of names a little? */ {"font", "fn", STRING_TYPE, NULL, &This_Font_Name}, {"fgMouse", "mfg", STRING_TYPE, NULL, &This_MFG}, {"bgMouse", "mbg", STRING_TYPE, NULL, &This_MBG}, {"background", "bg", STRING_TYPE, NULL, &Default_GC_Info[JNORMAL_COLOR].bg_name}, {"foreground", "fg", STRING_TYPE, NULL, &Default_GC_Info[JNORMAL_COLOR].fg_name}, {"fgStatus", "sfg", STRING_TYPE, NULL, &Default_GC_Info[JSTATUS_COLOR].fg_name}, {"bgStatus", "sbg", STRING_TYPE, NULL, &Default_GC_Info[JSTATUS_COLOR].bg_name}, {"fgRegion", "rfg", STRING_TYPE, NULL, &Default_GC_Info[JREGION_COLOR].fg_name}, {"bgRegion", "rbg", STRING_TYPE, NULL, &Default_GC_Info[JREGION_COLOR].bg_name}, {"fgCursor", "cfg", STRING_TYPE, NULL, &Default_GC_Info[JCURSOR_COLOR].fg_name}, {"bgCursor", "cbg", STRING_TYPE, NULL, &Default_GC_Info[JCURSOR_COLOR].bg_name}, {"fgMenu", "fgm", STRING_TYPE, NULL, &Default_GC_Info[JMENU_COLOR].fg_name}, {"bgMenu", "bgm", STRING_TYPE, NULL, &Default_GC_Info[JMENU_COLOR].bg_name}, {"fgOperator", "fgop", STRING_TYPE, NULL, &Default_GC_Info[JOP_COLOR].fg_name}, {"bgOperator", "bgop", STRING_TYPE, NULL, &Default_GC_Info[JOP_COLOR].bg_name}, {"fgNumber", "fgnm", STRING_TYPE, NULL, &Default_GC_Info[JNUM_COLOR].fg_name}, {"bgNumber", "bgnm", STRING_TYPE, NULL, &Default_GC_Info[JNUM_COLOR].bg_name}, {"fgString", "fgst", STRING_TYPE, NULL, &Default_GC_Info[JSTR_COLOR].fg_name}, {"bgString", "bgst", STRING_TYPE, NULL, &Default_GC_Info[JSTR_COLOR].bg_name}, {"fgComments", "fgco", STRING_TYPE, NULL, &Default_GC_Info[JCOM_COLOR].fg_name}, {"bgComments", "bgco", STRING_TYPE, NULL, &Default_GC_Info[JCOM_COLOR].bg_name}, {"fgKeyword", "fgkw", STRING_TYPE, NULL, &Default_GC_Info[JKEY_COLOR].fg_name}, {"bgKeyword", "bgkw", STRING_TYPE, NULL, &Default_GC_Info[JKEY_COLOR].bg_name}, {"fgKeyword1", "fgkw1",STRING_TYPE, NULL, &Default_GC_Info[JKEY_COLOR + 1].fg_name}, {"bgKeyword1", "bgkw1",STRING_TYPE, NULL, &Default_GC_Info[JKEY_COLOR + 1].bg_name}, {"fgDelimiter", "fgde", STRING_TYPE, NULL, &Default_GC_Info[JDELIM_COLOR].fg_name}, {"bgDelimiter", "bgde", STRING_TYPE, NULL, &Default_GC_Info[JDELIM_COLOR].bg_name}, {"fgPreprocess", "fgpr", STRING_TYPE, NULL, &Default_GC_Info[JPREPROC_COLOR].fg_name}, {"bgPreprocess", "bgpr", STRING_TYPE, NULL, &Default_GC_Info[JPREPROC_COLOR].bg_name}, {"fgMessage", "bgms", STRING_TYPE, NULL, &Default_GC_Info[JMESSAGE_COLOR].bg_name}, {"bgMessage", "fgms", STRING_TYPE, NULL, &Default_GC_Info[JMESSAGE_COLOR].fg_name}, {"fgError", "fger", STRING_TYPE, NULL, &Default_GC_Info[JERROR_COLOR].fg_name}, {"bgError", "bger", STRING_TYPE, NULL, &Default_GC_Info[JERROR_COLOR].bg_name}, {"BorderWidth", "bw", STRING_TYPE, NULL, &This_Border_Width_Name}, {"title", NULL, STRING_TYPE, NULL, &This_App_Title}, {"BorderColor", "bd", STRING_TYPE, NULL, NULL}, {"Iconic", "ic", VOID_TYPE, NULL, &Iconic}, {"xrm", NULL, STRING_TYPE, NULL, NULL}, {NULL, NULL, 0, NULL, NULL} #else {"Font", "fn", STRING_TYPE, NULL, &This_Font_Name}, {"Mouse_fg", "mfg", STRING_TYPE, NULL, &This_MFG}, {"Mouse_bg", "mbg", STRING_TYPE, NULL, &This_MBG}, {"background", "bg", STRING_TYPE, NULL, &Default_GC_Info[JNORMAL_COLOR].bg_name}, {"foreground", "fg", STRING_TYPE, NULL, &Default_GC_Info[JNORMAL_COLOR].fg_name}, {"Status_fg", "sfg", STRING_TYPE, NULL, &Default_GC_Info[JSTATUS_COLOR].fg_name}, {"Status_bg", "sbg", STRING_TYPE, NULL, &Default_GC_Info[JSTATUS_COLOR].bg_name}, {"Region_fg", "rfg", STRING_TYPE, NULL, &Default_GC_Info[JREGION_COLOR].fg_name}, {"Region_bg", "rbg", STRING_TYPE, NULL, &Default_GC_Info[JREGION_COLOR].bg_name}, {"Cursor_fg", "cfg", STRING_TYPE, NULL, &Default_GC_Info[JCURSOR_COLOR].fg_name}, {"Cursor_bg", "cbg", STRING_TYPE, NULL, &Default_GC_Info[JCURSOR_COLOR].bg_name}, {"Menu_fg", "mfg", STRING_TYPE, NULL, &Default_GC_Info[JMENU_COLOR].fg_name}, {"Menu_bg", "mbg", STRING_TYPE, NULL, &Default_GC_Info[JMENU_COLOR].bg_name}, {"Operator_fg", "opfg", STRING_TYPE, NULL, &Default_GC_Info[JOP_COLOR].fg_name}, {"Operator_bg", "opbg", STRING_TYPE, NULL, &Default_GC_Info[JOP_COLOR].bg_name}, {"Number_fg", "nmfg", STRING_TYPE, NULL, &Default_GC_Info[JNUM_COLOR].fg_name}, {"Number_bg", "nmbg", STRING_TYPE, NULL, &Default_GC_Info[JNUM_COLOR].bg_name}, {"String_fg", "stfg", STRING_TYPE, NULL, &Default_GC_Info[JSTR_COLOR].fg_name}, {"String_bg", "stbg", STRING_TYPE, NULL, &Default_GC_Info[JSTR_COLOR].bg_name}, {"Comments_fg", "cofg", STRING_TYPE, NULL, &Default_GC_Info[JCOM_COLOR].fg_name}, {"Comments_bg", "cobg", STRING_TYPE, NULL, &Default_GC_Info[JCOM_COLOR].bg_name}, {"Keyword_fg", "kwfg", STRING_TYPE, NULL, &Default_GC_Info[JKEY_COLOR].fg_name}, {"Keyword_bg", "kwbg", STRING_TYPE, NULL, &Default_GC_Info[JKEY_COLOR].bg_name}, {"Keyword1_fg", "kw1fg",STRING_TYPE, NULL, &Default_GC_Info[JKEY_COLOR + 1].fg_name}, {"Keyword1_bg", "kw1bg",STRING_TYPE, NULL, &Default_GC_Info[JKEY_COLOR + 1].bg_name}, {"Delimiter_fg", "defg", STRING_TYPE, NULL, &Default_GC_Info[JDELIM_COLOR].fg_name}, {"Delimiter_bg", "debg", STRING_TYPE, NULL, &Default_GC_Info[JDELIM_COLOR].bg_name}, {"Preprocess_fg", "prfg", STRING_TYPE, NULL, &Default_GC_Info[JPREPROC_COLOR].fg_name}, {"Preprocess_bg", "prbg", STRING_TYPE, NULL, &Default_GC_Info[JPREPROC_COLOR].bg_name}, {"Message_bg", "msbg", STRING_TYPE, NULL, &Default_GC_Info[JMESSAGE_COLOR].bg_name}, {"Message_fg", "msfg", STRING_TYPE, NULL, &Default_GC_Info[JMESSAGE_COLOR].fg_name}, {"Error_fg", "erfg", STRING_TYPE, NULL, &Default_GC_Info[JERROR_COLOR].fg_name}, {"Error_bg", "erbg", STRING_TYPE, NULL, &Default_GC_Info[JERROR_COLOR].bg_name}, {"Borderwidth", "bw", STRING_TYPE, NULL, &This_Border_Width_Name}, {"Title", NULL, STRING_TYPE, NULL, &This_App_Title}, {"Bordercolor", "bd", STRING_TYPE, NULL, NULL}, {"Iconic", "ic", VOID_TYPE, NULL, &Iconic}, {"xrm", NULL, STRING_TYPE, NULL, NULL}, {NULL, NULL, 0, NULL, NULL} #endif }; static void hide_cursor (void) { unsigned short *s; char ch; int b = XWin->border, col = XWin->vis_curs_col, row = XWin->vis_curs_row; if (No_XEvents) return; if (XWin->cursor_showing == 0) return; XWin->cursor_showing = 0; s = JScreen[row].old; if (s == NULL) return; s += col; ch = (char) (*s & 0xFF); XDrawImageString(This_XDisplay, XWin->w, XWin->text_gc[*s >> 8].gc, col * XWin->font_width + b, row * XWin->font_height + b + XWin->font_base, &ch, 1); } /* This routine assumes that cursor is in the correct location. The cursor is placed at the end of the string. */ static void tt_write(char *s, int n) { int b = XWin->border; if (XWin->window_mapped == 0) return; if (No_XEvents) return; if (XWin->cursor_showing) hide_cursor (); XDrawImageString(This_XDisplay, This_XWindow, XWin->current_gc, (XWin->cursor_col) * XWin->font_width + b, (XWin->cursor_row) * XWin->font_height + b + XWin->font_base, s, n); XWin->cursor_col += n; if (XWin->cursor_col >= JX_Screen_Cols) XWin->cursor_col = JX_Screen_Cols - 1; } static void copy_rect(int x1, int y1, int x2, int y2, int x3, int y3) { int w, h; if (No_XEvents) return; if (XWin->window_mapped == 0) return; w = (x2 - x1) * XWin->font_width; h = (y2 - y1) * XWin->font_height; if ((w <= 0) || (h <= 0)) return; x3 = XWin->border + x3 * XWin->font_width; x1 = XWin->border + x1 * XWin->font_width; y3 = XWin->border + y3 * XWin->font_height; y1 = XWin->border + y1 * XWin->font_height; hide_cursor (); XCopyArea (This_XDisplay, This_XWindow, This_XWindow, XWin->current_gc, x1, y1, w, h, x3, y3); } static void blank_rect (int x1, int y1, int x2, int y2) { int w, h; if (No_XEvents) return; if (XWin->window_mapped == 0) return; w = (x2 - x1) * XWin->font_width; h = (y2 - y1) * XWin->font_height; if ((w <= 0) || (h <= 0)) return; x1 = XWin->border + x1 * XWin->font_width; y1 = XWin->border + y1 * XWin->font_height; hide_cursor (); XClearArea (This_XDisplay, This_XWindow, x1, y1, w, h, 0); } static void JX_set_scroll_region(int r1, int r2) { XWin->scroll_r1 = r1; XWin->scroll_r2 = r2; } static void JX_reset_scroll_region (void) { XWin->scroll_r1 = 0; XWin->scroll_r2 = JX_Screen_Rows - 1; } static void show_cursor (void) { unsigned short *s; char ch; int c, r, b; GC gc; if (No_XEvents) return; if (XWin->cursor_showing) hide_cursor (); XWin->cursor_showing = 1; r = XWin->vis_curs_row = XWin->cursor_row; c = XWin->vis_curs_col = XWin->cursor_col; b = XWin->border; s = JScreen[r].old; if (s == NULL) return; s += c; ch = (char) (*s & 0xFF); gc = XWin->text_gc[JCURSOR_COLOR].gc; if (XWin->focus) { XDrawImageString(This_XDisplay, This_XWindow, gc, c * XWin->font_width + b, r * XWin->font_height + b + XWin->font_base, &ch, 1); } else { XDrawRectangle( This_XDisplay, This_XWindow, gc, c * XWin->font_width + b, r * XWin->font_height + b, XWin->font_width - 1, XWin->font_height - 1); } XFlush(This_XDisplay); } static void toggle_cursor (int on) { if (on) { if (XWin->focus) return; XWin->focus = 1; } else { if (XWin->focus == 0) return; XWin->focus = 0; } show_cursor (); } static void JX_write_string (char *s) { tt_write(s, strlen(s)); if (Performing_Update) return; show_cursor (); } static void JX_goto_rc(int r, int c) { if (XWin == NULL) return; if (XWin->cursor_showing) hide_cursor (); if (r >= JX_Screen_Rows) r = JX_Screen_Rows - 1; if (c >= JX_Screen_Cols) c = JX_Screen_Cols - 1; XWin->cursor_row = r + XWin->scroll_r1; XWin->cursor_col = c; if (Performing_Update) return; show_cursor (); } static void JX_begin_insert(void) { XEvent ev; if (No_XEvents) return; hide_cursor (); copy_rect(XWin->cursor_col, XWin->cursor_row, JX_Screen_Cols - 1, XWin->cursor_row + 1, XWin->cursor_col + 1, XWin->cursor_row); XWin->insert_mode = 1; /* The noexpose events really mess up input pending timing. Stop them now. */ XFlush(This_XDisplay); if (!XPeekEvent(This_XDisplay, &ev) || (ev.type != NoExpose)) return; XNextEvent(This_XDisplay, &ev); } static void JX_end_insert(void) { XWin->insert_mode = 0; } static void JX_delete_char (void) { copy_rect(XWin->cursor_col + 1, XWin->cursor_row, JX_Screen_Cols, XWin->cursor_row + 1, XWin->cursor_col, XWin->cursor_row); } static void JX_erase_line(void) { if (XWin == NULL) return; blank_rect(0, XWin->cursor_row, JX_Screen_Cols, XWin->cursor_row + 1); } /* Must respect scrolling region */ static void JX_delete_nlines(int n) { int r1, r2; r1 = XWin->cursor_row; r2 = XWin->scroll_r2; if (r1 <= r2 - n) copy_rect(0, r1 + n, JX_Screen_Cols, r2 + 1, 0, r1); if (Scroll_By_Copying == 0) blank_rect(0, r2 - n, JX_Screen_Cols, r2); } static void JX_reverse_index(int n) { int r1, r2; r1 = XWin->scroll_r1; r2 = XWin->scroll_r2; if (r2 >= r1 + n) copy_rect(0, r1, JX_Screen_Cols, r2 - n + 1, 0, r1 + n); if (Scroll_By_Copying == 0) blank_rect(0, r1, JX_Screen_Cols, r1 + n); } static void JX_beep(void) { GC gc; XGCValues gcv; if (No_XEvents) return; flush_input(); if (JX_Ignore_Beep & 0x1) XBell (This_XDisplay, 50); /* visible bell */ if (JX_Ignore_Beep & 0x2) { gc = XCreateGC(This_XDisplay, This_XWindow, 0, &gcv); XSetState(This_XDisplay, gc, WhitePixel (This_XDisplay, This_XScreen), BlackPixel(This_XDisplay, This_XScreen), GXinvert, AllPlanes); XFillRectangle (This_XDisplay, This_XWindow, gc, 0, 0, XWin->font_width * JX_Screen_Cols, XWin->font_height * JX_Screen_Rows); XFlush (This_XDisplay); /* I attempted to put a pause in here but it was too slow. */ XFillRectangle (This_XDisplay, This_XWindow, gc, 0, 0, XWin->font_width * JX_Screen_Cols, XWin->font_height * JX_Screen_Rows); XFreeGC(This_XDisplay, gc); } XFlush (This_XDisplay); } static void JX_del_eol(void) { blank_rect(XWin->cursor_col, XWin->cursor_row, JX_Screen_Cols, XWin->cursor_row + 1); } static int Rev_Vid_Flag; static void JX_reverse_video(int color) { Rev_Vid_Flag = color; XWin->current_gc = XWin->text_gc[color].gc; } static void JX_normal_video(void) { if (XWin == NULL) return; Rev_Vid_Flag = JNORMAL_COLOR; XWin->current_gc = XWin->text_gc[JNORMAL_COLOR].gc; } static void send_attr_str(unsigned short *s, unsigned short *smax) { unsigned char out[250], ch, attr, *p; register unsigned short sh; p = out; while (s < smax) { sh = (unsigned short) *s++; ch = sh & 0xFF; attr = sh >> 8; if ((attr == 0) && (Rev_Vid_Flag != 0)) { if (p != out) { *p = 0; JX_write_string ((char *) out); p = out; } tt_normal_video(); /* Rev_Vid_Flag = 0; */ } else if ((attr != 0) && (Rev_Vid_Flag != attr)) { if (p != out) { *p = 0; JX_write_string ((char *) out); p = out; } JX_reverse_video(attr); /* Rev_Vid_Flag = 1; */ } *p++ = ch; } *p = 0; if (p != out) JX_write_string ((char *) out); /* if (Rev_Vid_Flag) tt_normal_video(); */ } #define SPACE_CHAR (32 | (JNORMAL_COLOR << 8)) static void forward_cursor (int n, int row) { JX_goto_rc (row, XWin->cursor_col + n); } static void JX_smart_puts(unsigned short *neww,unsigned short *oldd, int len, int row) { register unsigned short *p, *q, *qmax, *pmax, *buf; unsigned short buffer[256]; int n_spaces; unsigned short *space_match, *last_buffered_match; q = oldd; p = neww; qmax = oldd + len; pmax = p + len; /* Find out where to begin --- while they match, we are ok */ for (;;) { if (q == qmax) return; if (*q != *p) break; q++; p++; } /*position the cursor */ JX_goto_rc (row, (int) (p - neww)); /* Find where the last non-blank character on old/new screen is */ while (qmax > q) { qmax--; if (*qmax != SPACE_CHAR) { qmax++; break; } } /* if (*qmax != SPACE_CHAR) qmax++; */ while (pmax > p) { pmax--; if (*pmax != SPACE_CHAR) { pmax++; break; } } last_buffered_match = buf = buffer; /* buffer is empty */ /* loop using overwrite then skip algorithm until done */ while (1) { /* while they do not match and we do not hit a space, buffer them up */ n_spaces = 0; while (p < pmax) { if ((*q == SPACE_CHAR) && (*p == SPACE_CHAR)) { /* If *q is not a space, we would have to overwrite it. * However, if *q is a space, then while *p is also one, * we only need to skip over the blank field. */ space_match = p; p++; q++; while ((p < pmax) && (*p == SPACE_CHAR) && (*q == SPACE_CHAR)) { p++; q++; } n_spaces = (int) (p - space_match); break; } if (*q == *p) break; *buf++ = *p++; q++; } *buf = 0; if (buf != buffer) send_attr_str (buffer, buf); buf = buffer; if (n_spaces && (p < pmax)) { forward_cursor (n_spaces, row); } /* Now we overwrote what we could and cursor is placed at position * of a possible match of new and old. If this is the case, skip * some more. */ while ((p < pmax) && (*p == *q)) { *buf++ = *p++; q++; } last_buffered_match = buf; if (p >= pmax) break; /* jump to new position is it is greater than 5 otherwise * let it sit in the buffer and output it later. */ if ((int) (buf - buffer) >= 5) { forward_cursor (buf - buffer, row); last_buffered_match = buf = buffer; } } if (buf != buffer) { if (q < qmax) { if ((buf == last_buffered_match) && ((int) (buf - buffer) >= 5)) { forward_cursor (buf - buffer, row); } else { *buf = 0; send_attr_str (buffer, buf); } } } if (q < qmax) JX_del_eol (); } static int push_mouse_event (int type, int x, int y, unsigned int button, unsigned int state ) { register unsigned int s = 0, but; int ch; static int last_button; if (button == 0) button = last_button; JMouse.type = (type == ButtonPress) ? 1 : 0; if (JMouse.type) last_button = button; JMouse.x = 1 + (x - XWin->border) / XWin->font_width; if (y < XWin->border) JMouse.y = 0; else JMouse.y = 1 + (y - XWin->border) / XWin->font_height; but = JMouse.button = (int) button; if (but == Button1) ch = 'l'; else if (but == Button2) ch = 'm'; else ch = 'r'; if (state & Button1Mask) s |= 1; if (state & Button2Mask) s |= 2; if (state & Button3Mask) s |= 4; if (state & ShiftMask) { s |= 16; ch = 'A' + (ch - 'a'); } if (state & ControlMask) { s |= 8; if (ch >= 'a') ch = ch - 'a' + 1; } JMouse.state = s; return ch; } static void cover_exposed_area (int x, int y, int width, int height, int count) { unsigned short *s, *smax; int row, save_row, save_col, max_col, max_row, col; Performing_Update++; hide_cursor (); save_row = XWin->cursor_row; save_col = XWin->cursor_col; col = (x - XWin->border) / XWin->font_width; row = (y - XWin->border) / XWin->font_height; max_col = 2 + col + width / XWin->font_width; max_row = 2 + row + height / XWin->font_height; if (max_col > JX_Screen_Cols) max_col = JX_Screen_Cols; if (max_row > JX_Screen_Rows) max_row = JX_Screen_Rows; for (XWin->cursor_row = row; XWin->cursor_row < max_row; XWin->cursor_row++) { XWin->cursor_col = col; s = JScreen[XWin->cursor_row].old + XWin->cursor_col; smax = JScreen[XWin->cursor_row].old + max_col; send_attr_str(s, smax); } XWin->cursor_row = save_row; XWin->cursor_col = save_col; Performing_Update--; if (count == 0) show_cursor (); } #include "xkeys.c" /* Return 1 if event is listed in the switch or zero otherwise. The switch * events are considered harmless--- that is, processing them does not really * interfere with internal JED state (redisplay, etc...). More bluntly, * harmless means that the events can be processesed while checking for * pending input. */ static int x_handle_harmless_events (XEvent *report) { switch (report->type) { case EnterNotify: toggle_cursor(report->xcrossing.focus); break; case LeaveNotify: /* toggle_cursor(0); */ break; case UnmapNotify: XWin->window_mapped = 0; break; case MapNotify: XWin->window_mapped = 1; break; case FocusIn: toggle_cursor(1); #ifdef XJED_USE_R6IM if (NULL != R6IM_Xic) XSetICFocus (R6IM_Xic); #endif Check_Buffers_Pending = 1; break; case FocusOut: toggle_cursor(0); #ifdef XJED_USE_R6IM if (NULL != R6IM_Xic) XUnsetICFocus (R6IM_Xic); #endif break; case VisibilityNotify: XWin->visible = report->xvisibility.state; break; case GraphicsExpose: cover_exposed_area (report->xgraphicsexpose.x, report->xgraphicsexpose.y, report->xgraphicsexpose.width, report->xgraphicsexpose.height, report->xgraphicsexpose.count); break; case NoExpose: break; case KeyPress: /* Just look for Modifier key presses */ return IsModifierKey (XLookupKeysym (&report->xkey, 0)); default: /* fprintf(stderr, "harmless: %d\n", report->type); */ return 0; } return 1; } static int X_Alt_Char = 27; static KeySym X_Last_Keysym; /* if force is true, wait for an event. If force is false, only * process events that exist. This will return either when there * are no more events or a key/mouse event is processed returning * 1 in the process */ static int X_process_events (int force, char *buf, int *n_chars) { XEvent report; int ch1; int block_expose = 0; char *bufp; KeySym ks = 0; int esc = 27; Window root, child; int posx, posy, rootx, rooty; unsigned int keys_buttons; int last_x, last_y; static int last_event, motion_button; static unsigned int motion_state; int width, height; while (force || XPending(This_XDisplay)) { XNextEvent(This_XDisplay, &report); switch (report.type) { case ClientMessage: if ((report.xclient.format == 32) && (report.xclient.data.l[0] == This_X_Window.wm_del_win)) exit_jed (); break; case MotionNotify: while (XCheckMaskEvent (This_XDisplay, ButtonMotionMask, &report)); if (!XQueryPointer(This_XDisplay, report.xmotion.window, &root, &child, &rootx, &rooty, &posx, &posy, &keys_buttons)) break; /* This will ensure that modifier keys are not pressed while we are in motion. */ if ((last_event == MotionNotify) && (motion_state != keys_buttons)) break; motion_state = keys_buttons; last_x = JMouse.x; last_y = JMouse.y; ch1 = push_mouse_event (ButtonPress, posx, posy, 0, keys_buttons); if ((last_x == JMouse.x) && (last_y == JMouse.y)) break; /* return ESC ^@ ^@ .... */ *buf++ = esc; *buf++ = 0; *buf++ = 0; *buf++ = ch1; *n_chars = 4; last_event = MotionNotify; motion_button = JMouse.button; return 1; case Expose: if (block_expose == 0) cover_exposed_area (report.xexpose.x, report.xexpose.y, report.xexpose.width, report.xexpose.height, report.xexpose.count); else { if (report.xexpose.count == 0) { redraw_screen (1); block_expose = 0; } } break; case ConfigureNotify: width = report.xconfigure.width; height = report.xconfigure.height; if ((width != XWin->width) || (height != XWin->height)) { XWin->width = width; XWin->height = height; reset_display (); init_display(1); block_expose = -1; } break; case ButtonPress: /* Prohibit dragging more than one button at a time. */ if (last_event == MotionNotify) break; /* drop */ case ButtonRelease: if ((last_event == MotionNotify) && (report.xbutton.button != motion_button)) break; last_event = 0; /* ESC ^@ U/D is a mouse prefix */ *buf++ = esc; *buf++ = 0; if (report.type == ButtonPress) ch1 = 'D'; else ch1 = 'U'; *buf++ = ch1; *buf++ = push_mouse_event (report.xbutton.type, report.xbutton.x, report.xbutton.y, report.xbutton.button, report.xbutton.state); *n_chars = 4; return 1; case KeyPress: bufp = buf; #ifndef XJED_USE_R6IM *n_chars = XLookupString(&report.xkey, buf, 20, &ks, NULL); #else if (!XFilterEvent (&report, report.xkey.window)) { Status status_return; if (R6IM_Xic != NULL) *n_chars = XmbLookupString (R6IM_Xic, &report.xkey, buf, 20, &ks, &status_return); else *n_chars = XLookupString(&report.xkey, buf, 20, &ks, NULL); } else *n_chars = 0; #endif ks = ks & 0xFFFF; X_Last_Keysym = ks; if (ks >= 0xFF00) { ks = ks & 0xFF; if (report.xkey.state & ShiftMask) bufp = Shift_KeySym_Mapping [ks]; else if (report.xkey.state & ControlMask) bufp = Control_KeySym_Mapping [ks]; else bufp = KeySym_Mapping [ks]; if (0 != (*n_chars = (int) *bufp++)) MEMCPY(buf, bufp, *n_chars); } else if (*n_chars == 1) { if (report.xkey.state & Mod1Mask) { ch1 = *bufp; #if 0 /* Only do this on alphabetic characters. This * is because, e.g., german keyboards use 'Alt-{' * to generate the '{' character */ if (isalnum (ch1) && (ch1 < 0x80)) { #endif if (X_Alt_Char <= 0) *buf |= 0x80; else { *bufp++ = (unsigned char) X_Alt_Char; *bufp = (unsigned char) ch1; *n_chars = 2; } #if 0 } #endif } else if (report.xkey.state & ControlMask) { if (*buf == ' ') *buf = 0; else if (*buf == '-') *buf = 0x1F; } } if (*n_chars == 0) break; return 1; default: (void) x_handle_harmless_events (&report); } } return 0; } static int X_read_key (void) { int nread; char buf[30]; (void) X_process_events (1, buf, &nread); if (nread > 1) ungetkey_string(buf + 1, nread - 1); return (int) *buf; } static int X_input_pending (void) { XEvent ev; int n; if (No_XEvents) return 0; n = XPending (This_XDisplay); if (!n) return (0); /* I need some way of getting only kbd events. */ while (n--) { XPeekEvent(This_XDisplay, &ev); if (0 == x_handle_harmless_events (&ev)) return 1; XNextEvent(This_XDisplay, &ev); } return 0; } static void X_Get_Term_Size(int *cols, int *rows) { *cols = (XWin->width - XWin->border) / XWin->font_width; *rows = (XWin->height - XWin->border) / XWin->font_height; } static void JX_set_term_vtxxx (int *n) { } static void JX_narrow_width (void) { } static void JX_wide_width (void) { } static void JX_enable_cursor_keys(void) { } static void JX_cls(void) { if (No_XEvents) return; if (XWin->window_mapped == 0) return; XClearWindow(This_XDisplay, This_XWindow); } /* This function is called assuming that cursor is in correct position */ static void JX_putchar(char ch) { if (ch == '\b') { ch = ' '; if (XWin->cursor_col == 0) return; XWin->cursor_col--; } if (Rev_Vid_Flag != JNORMAL_COLOR) tt_normal_video(); tt_write(&ch, 1); show_cursor (); } /* This routine is called from S-Lang inner interpreter. It serves as a poor mans version of an interrupt 9 handler */ static void xjed_check_kbd(void) { char buf[30]; int n; register char *b, *bmax; if (Batch || No_XEvents) return; while (XPending(This_XDisplay)) { if (X_process_events (0, buf, &n) == 0) continue; b = buf; bmax = b + n; while (b < bmax) { if (*b == Abort_Char) { if (Ignore_User_Abort == 0) SLang_Error = USER_BREAK; if (b != buf) buffer_keystring (buf, (int) (b - buf)); SLKeyBoard_Quit = 1; break; } b++; } if (!SLKeyBoard_Quit) buffer_keystring (buf, n); } } static void xjed_suspend (void) { if (No_XEvents) return; if (XWin->focus) { /* XIconifyWindow (This_XDisplay, XWin->w, This_XScreen); */ if (XWin->visible == VisibilityUnobscured) XLowerWindow (This_XDisplay, This_XWindow); else XRaiseWindow (This_XDisplay, This_XWindow); } else { /* The window doesn't have focus which means that this was most * likely called by pressing Ctrl-Z from another window. */ sys_suspend (); } } static int load_font (char *font) { static XFontStruct *xfont; xfont = XLoadQueryFont(This_XDisplay, font); if (xfont == NULL) return 0; XWin->font = xfont; XWin->font_name = font; XWin->font_height = XWin->font->ascent + XWin->font->descent; XWin->font_width = XWin->font->max_bounds.width; XWin->font_base = XWin->font->ascent; return 1; } static void get_xdefaults (void) { XWindow_Arg_Type *xargs = X_Arg_List + XARG_START; /* skip display, name, etc */ while (xargs->name != NULL) { if ((xargs->type != VOID_TYPE) && (xargs->dflt != NULL)) { if (xargs->value == NULL) { char *p; p = XGetDefault(This_XDisplay, This_App_Name, xargs->name); if (p == NULL) p = XGetDefault (This_XDisplay, XJED_CLASS, xargs->name); if (p != NULL) xargs->value = p; /* was: xargs->value = XGetDefault(This_XDisplay, This_App_Name, xargs->name); */ } if (xargs->value != NULL) { *xargs->dflt = xargs->value; } } xargs++; } } static void set_window_name (char *s) { if (Batch) return; XStoreName (This_XDisplay, XWin->w, s); } static void set_icon_name (char *s) { if (Batch) return; XSetIconName(This_XDisplay, XWin->w, s); } #if 0 static void set_wm_hints (JXWindow_Type *w, int xpos, int ypos, unsigned long orflags) { XSizeHints h; XWMHints h1; XClassHint ch; ch.res_name = "xjed"; ch.res_class = "XJed"; h.width_inc = w->font_width; h.height_inc = w->font_height; h.min_width = 5 * w->font_width + w->border; h.min_height = 5 * w->font_height + w->border; h.base_height = 0; h.base_width = 0; h.x = xpos; h.y = ypos; h.height = w->height; h.width = w->width; h.flags = PMinSize | PResizeInc | PBaseSize; h.flags |= orflags; XSetWMNormalHints(This_XDisplay, w->w, &h); /* This bit allows me to track the focus. It is not at all clear from the documentation. */ h1.input = 1; h1.flags = InputHint; XSetWMHints(This_XDisplay, w->w, &h1); #if 0 XSetClassHint(This_XDisplay, w->w, &ch); #endif } #endif /* This parses the colors in the XWin structure and setting defaults to fg, bg upon failure of either one */ static void setup_ith_color (int i, unsigned long fg, unsigned long bg) { XColor xcol; XWin->text_gc[i].fg = fg; XWin->text_gc[i].bg = bg; if (Term_Supports_Color && XParseColor(This_XDisplay, XWin->color_map, XWin->text_gc[i].fg_name, &xcol) && XAllocColor(This_XDisplay, XWin->color_map, &xcol)) { fg = xcol.pixel; if (XParseColor(This_XDisplay, XWin->color_map, XWin->text_gc[i].bg_name, &xcol) && XAllocColor(This_XDisplay, XWin->color_map, &xcol)) { bg = xcol.pixel; XWin->text_gc[i].fg = fg; XWin->text_gc[i].bg = bg; } } } /* This is used to set the colors in the Win structure and if f is non-zero, * the previous definitions are freed. f is 0 when the colors correspond to the * default. */ static void x_set_color_free (int i, char *fgcolor, char *bgcolor, int do_free) { char *save_fg, *save_bg, *fg, *bg; unsigned long old_fg, old_bg; if (NULL == (fg = (char *) SLMALLOC(strlen(fgcolor) + 1))) { SLang_Error = SL_MALLOC_ERROR; return; } strcpy (fg, fgcolor); if (NULL == (bg = (char *) SLMALLOC(strlen(bgcolor) + 1))) { SLang_Error = SL_MALLOC_ERROR; SLFREE (fg); return; } strcpy (bg, bgcolor); old_fg = XWin->text_gc[i].fg; old_bg = XWin->text_gc[i].bg; save_fg = XWin->text_gc[i].fg_name; XWin->text_gc[i].fg_name = fg; save_bg = XWin->text_gc[i].bg_name; XWin->text_gc[i].bg_name = bg; setup_ith_color (i, old_fg, old_bg); if (do_free) { if (save_fg != NULL) SLFREE (save_fg); if (save_bg != NULL) SLFREE (save_bg); } } static void setup_and_parse_colors (void) { unsigned long fg, bg, tmp; char *fg_name, *bg_name; int i; GC_Info_Type *d; /* Check to see if this is a color display */ bg = WhitePixel (This_XDisplay, This_XScreen); bg_name = "white"; fg = BlackPixel (This_XDisplay, This_XScreen); fg_name = "black"; XWin->color_map = DefaultColormap (This_XDisplay, This_XScreen); if (DisplayCells (This_XDisplay, This_XScreen) > 2) { Term_Supports_Color = 1; } else Term_Supports_Color = 0; for (i = 0; i < JMAX_COLORS; i++) { d = Default_GC_Info + i; /* The assumption here is that ALL colors beyond JNORMAL_COLOR (0) * take reversed fg, bgs. I really ought to have flags if this is * not the case. */ d->fg = fg; d->bg = bg; if (d->fg_name == NULL) d->fg_name = fg_name; if (d->bg_name == NULL) d->bg_name = bg_name; if (i == JNORMAL_COLOR) { tmp = fg; fg = bg; bg = tmp; fg_name = bg_name; bg_name = "black"; } x_set_color_free (i, d->fg_name, d->bg_name, 0); } } static void set_mouse_color (char *fgc, char *bgc) { XColor xfg, xbg; if (!Term_Supports_Color) return; if (!XParseColor(This_XDisplay, XWin->color_map, fgc, &xfg) || !XAllocColor(This_XDisplay, XWin->color_map, &xfg)) { return; } if (!XParseColor(This_XDisplay, XWin->color_map, bgc, &xbg) || !XAllocColor(This_XDisplay, XWin->color_map, &xbg)) { return; } XRecolorCursor (This_XDisplay, XWin->mouse, &xfg, &xbg); } static void create_needed_gcs (void) { int i; XGCValues xgcv; xgcv.font = XWin->font->fid; for (i = 0; i < JMAX_COLORS; i++) { xgcv.foreground = XWin->text_gc[i].fg; xgcv.background = XWin->text_gc[i].bg; XWin->text_gc[i].gc = XCreateGC(This_XDisplay, This_XWindow, GCForeground | GCBackground | GCFont, &xgcv); } } static Window create_XWindow (JXWindow_Type *win) { int bdr, x, y, flags; unsigned int width, height; XSizeHints sizehint; XClassHint xcls; XWMHints wmhint; bdr = atoi(This_Border_Width_Name); if (This_Geometry == NULL) This_Geometry = Default_Geometry; sizehint.flags = 0; flags = XParseGeometry (This_Geometry, &x, &y, &width, &height); if (flags & WidthValue) { sizehint.width = width; sizehint.flags |= USSize; } else { width = JX_Screen_Cols; } if (flags & HeightValue) { sizehint.height = height; sizehint.flags |= USSize; } else { height = JX_Screen_Rows; } win->height = height * win->font_height + 2 * win->border; win->width = width * win->font_width + 2 * win->border; sizehint.height = win->height; sizehint.width = win->width; sizehint.width_inc = win->font_width; sizehint.height_inc = win->font_height; sizehint.min_width = 5 * win->font_width + win->border; sizehint.min_height = 5 * win->font_height + win->border; sizehint.base_height = 0; sizehint.base_width = 0; if (flags & XValue) { if (flags & XNegative) { x += (DisplayWidth (This_XDisplay, This_XScreen) - sizehint.width - 2 * win->border); sizehint.win_gravity = NorthEastGravity; } sizehint.x = x; sizehint.flags |= USPosition; } else x = 0; if (flags & YValue) { if (flags & YNegative) { y += (DisplayHeight (This_XDisplay, This_XScreen) - sizehint.height - 2 * win->border); if ((flags&XValue) && (flags&XNegative)) sizehint.win_gravity = SouthEastGravity; else sizehint.win_gravity = SouthWestGravity; } sizehint.y = y; sizehint.flags |= USPosition; } else y = 0; sizehint.flags |= (PMinSize | PResizeInc | PBaseSize); /* create and display window */ win->w = XCreateSimpleWindow(This_XDisplay, RootWindow(This_XDisplay, This_XScreen), x, y, /* xpos, ypos */ win->width, /* width, height */ win->height, /* width, height */ bdr, /* border width */ win->text_gc[JNORMAL_COLOR].fg, win->text_gc[JNORMAL_COLOR].bg ); xcls.res_name = This_App_Name; xcls.res_class = XJED_CLASS; wmhint.input = True; /* track the focus */ if (Iconic != NULL) wmhint.initial_state = IconicState; else wmhint.initial_state = NormalState; wmhint.flags = InputHint | StateHint; XSetWMProperties (This_XDisplay, win->w, NULL, NULL, NULL, 0, &sizehint, &wmhint, &xcls); /* Enable the delete window protocol */ win->wm_del_win = XInternAtom (This_XDisplay, "WM_DELETE_WINDOW", False); XSetWMProtocols (This_XDisplay, win->w, &win->wm_del_win, 1); /* select event types */ XSelectInput(This_XDisplay, win->w, (ExposureMask | KeyPressMask | ButtonPressMask | ButtonReleaseMask | StructureNotifyMask | PointerMotionHintMask | ButtonMotionMask | EnterWindowMask /* | LeaveWindowMask */ | FocusChangeMask | VisibilityChangeMask) ); if (XWin->mouse) XDefineCursor(This_XDisplay, win->w, XWin->mouse); return win->w; } static int x_err_handler (Display *d, XErrorEvent *ev) { char errmsg[256]; No_XEvents = 1; XGetErrorText (d, ev->error_code, errmsg, 255); exit_error (errmsg, 0); return 1; } static int x_ioerr_handler (Display *d) { No_XEvents = 1; exit_error("XWindows IO error", 0); return d == NULL; /* just use d to avoid a warning */ } /* returns socket descriptor */ static int init_Xdisplay (void) { char dname[80], *n; n = X_Arg_List[XARG_DISPLAY].value; if (n != NULL) { strncpy (dname, X_Arg_List[XARG_DISPLAY].value, 70); dname[70] = 0; n = dname; while (*n && (*n != ':')) n++; if (*n == 0) strcpy(n, ":0.0"); n = dname; } XSetIOErrorHandler (x_ioerr_handler); if ( (This_XDisplay = XOpenDisplay(n)) == NULL ) { (void) fprintf( stderr, "XJED: cannot connect to X server %s\n", XDisplayName(n)); exit( -1 ); } XSetErrorHandler (x_err_handler); if (X_Arg_List[XARG_NAME].value != NULL) { This_App_Name = X_Arg_List[XARG_NAME].value; } XWin = &This_X_Window; get_xdefaults (); XWin->font_name = This_Font_Name; This_XScreen = DefaultScreen(This_XDisplay); if (!load_font(XWin->font_name)) { (void) fprintf( stderr, "XJED: cannot load font %s, using fixed.\n", XWin->font_name); if (!load_font("fixed")) { (void) fprintf( stderr, "XJED: cannot load fixed font.\n"); exit( -1 ); } } XWin->text_gc = Default_GC_Info; setup_and_parse_colors (); /* This allocs and parses colors */ XWin->mouse = XCreateFontCursor (This_XDisplay, XC_xterm); set_mouse_color (This_MFG, This_MBG); This_XWindow = create_XWindow(XWin); set_window_name (This_App_Title); set_icon_name (This_App_Name); /* GCs and their colors */ create_needed_gcs (); /* This uses info from previous call */ XWin->current_gc = XWin->text_gc[JNORMAL_COLOR].gc; XSetFont (This_XDisplay, XWin->current_gc, XWin->font->fid); /* display window */ XMapWindow(This_XDisplay, This_XWindow); #ifdef XJED_USE_R6IM i18init (); #endif return ConnectionNumber (This_XDisplay); } static void reset_Xdisplay (void) { if (This_XDisplay != NULL) XCloseDisplay(This_XDisplay); } #define UPCSE(x) (((x) <= 'z') && ((x) >= 'a') ? (x) - 32 : (x)) static int myXstrcmp(char *a, char *b) { register char cha, chb; /* do simple comparison */ cha = *a++; chb = *b++; if ((cha != chb) && (UPCSE(cha) != UPCSE(chb))) return 0; while ((cha = *a++), (chb = *b++), (cha && chb) != 0) { if (cha != chb) return 0; } return (cha == chb); } #define STREQS(a, b) myXstrcmp(a, b) static int X_eval_command_line (int argc, char **argv) { char *arg; int i; XWindow_Arg_Type *opt; for (i = 1; i < argc; i++) { arg = argv[i]; if (*arg != '-') break; arg++; opt = X_Arg_List; while (opt->name != NULL) { if (STREQS(opt->name, arg) || ((opt->name1 != NULL) && STREQS(opt->name1, arg))) break; opt++; } if (opt->name == NULL) break; if (opt->type == VOID_TYPE) opt->value = "on"; else if (i + 1 < argc) { i++; opt->value = argv[i]; } else break; } /* Out of this loop, argv[i] is the last unprocessed argument */ return i; } #ifdef XJED_USE_R6IM /* * This is more or less stolen startight from XFree86 xterm. This should * support all European type languages. */ static void i18init (void) { int i; char *p, *s, *ns, *end, tmp[1024], buf[32]; XIM xim = NULL; XIMStyles *xim_styles = NULL; XIMStyle input_style = 0; int found; if (R6IM_Input_Method != NULL) { strcpy(tmp, R6IM_Input_Method); s=tmp; while (*s) { while (*s && isspace(*s)) s++; if (*s == 0) break; end = s; while (*end && (*end != ',')) end++; ns = end--; while ((end >= s) && isspace(*end)) *end-- = 0; if (*s) { strcpy(buf, "@im="); strcat(buf, s); if (((p = XSetLocaleModifiers(buf)) != NULL) && *p && (NULL != (xim = XOpenIM(This_XDisplay, NULL, NULL, NULL)))) break; } s = ns + 1; } } else { if ((p = XSetLocaleModifiers("@im=none")) != NULL && *p) xim = XOpenIM(This_XDisplay, NULL, NULL, NULL); } if ((xim == NULL) && ((p = XSetLocaleModifiers("")) != NULL) && *p) xim = XOpenIM(This_XDisplay, NULL, NULL, NULL); if (xim == NULL) { fprintf(stderr, "Failed to open input method"); return; } if (XGetIMValues(xim, XNQueryInputStyle, &xim_styles, NULL) || !xim_styles) { fprintf(stderr, "input method doesn't support any style\n"); XCloseIM(xim); return; } found = 0; strcpy(tmp, R6IM_Preedit_Type); s = tmp; while (*s && !found) { while (*s && isspace(*s)) s++; if (*s == 0) break; end = s; while (*end && (*end != ',')) end++; ns = end--; while ((end >= s) && isspace(*end)) *end-- = 0; if (!strcmp(s, "OverTheSpot")) input_style = (XIMPreeditPosition | XIMStatusArea); else if (!strcmp(s, "OffTheSpot")) input_style = (XIMPreeditArea | XIMStatusArea); else if (!strcmp(s, "Root")) input_style = (XIMPreeditNothing | XIMStatusNothing); for (i = 0; (unsigned short)i < xim_styles->count_styles; i++) { if (input_style == xim_styles->supported_styles[i]) { found = 1; break; } } s = ns; } XFree(xim_styles); if (found == 0) { fprintf(stderr, "input method doesn't support my preedit type\n"); XCloseIM(xim); return; } /* * This program only understands the Root preedit_style yet * Then misc.preedit_type should default to: * "OverTheSpot,OffTheSpot,Root" * /MaF */ if (input_style != (XIMPreeditNothing | XIMStatusNothing)) { fprintf(stderr,"This program only supports the 'Root' preedit type\n"); XCloseIM(xim); return; } R6IM_Xic = XCreateIC(xim, XNInputStyle, input_style, XNClientWindow, This_XWindow, XNFocusWindow, This_XWindow, NULL); if (NULL == R6IM_Xic) { fprintf(stderr,"Failed to create input context\n"); XCloseIM(xim); } } #endif static void set_border_color (char *fgc, char *bgc) { XColor xfg; unsigned int bdr = atoi(bgc); if (!Term_Supports_Color) return; if (!XParseColor(This_XDisplay, XWin->color_map, fgc, &xfg) || !XAllocColor(This_XDisplay, XWin->color_map, &xfg)) { return; } /*printf("border pixel = %ld\n",xfg.pixel);*/ XSetWindowBorder (This_XDisplay, XWin->w, xfg.pixel); if (bdr < 1000) XSetWindowBorderWidth (This_XDisplay, XWin->w, bdr); } static void JX_set_color (int i, char *what, char *fg, char *bg) { if (!Term_Supports_Color) return; if (i == -1) { if (!strcmp("mouse", what)) { set_mouse_color (fg, bg); } else if (!strcmp("border", what)) { set_border_color (fg, bg); } return; } x_set_color_free (i, fg, bg, 1); XSetForeground(This_XDisplay, XWin->text_gc[i].gc, XWin->text_gc[i].fg); XSetBackground(This_XDisplay, XWin->text_gc[i].gc, XWin->text_gc[i].bg); if (i == JNORMAL_COLOR) XSetWindowBackground (This_XDisplay, This_XWindow, XWin->text_gc[i].bg); } static int X_Warp_Pending = 0; static void x_warp_pointer (void) { X_Warp_Pending = 1; } static void x_region_2_cutbuffer (void) { int nbytes; char *dat; dat = make_buffer_substring(&nbytes); if (dat == NULL) return; XStoreBytes (This_XDisplay, dat, nbytes); XSetSelectionOwner (This_XDisplay, XA_PRIMARY, None, CurrentTime); #if 0 XChangeProperty (This_XDisplay, DefaultRootWindow (This_XDisplay), XA_CUT_BUFFER0, XA_STRING, 8, PropModeReplace, dat, nbytes); #endif SLFREE (dat); } static int x_insert_cutbuffer (void) { int nbytes; char *dat; CHECK_READ_ONLY dat = XFetchBytes (This_XDisplay, &nbytes); if (nbytes && (dat != NULL)) ins_chars ((unsigned char *) dat, nbytes); if (dat != NULL) XFree (dat); return nbytes; } static void x_set_keysym (int *np, int *shift, char *str) { unsigned int n = (unsigned int) *np; KeySym_Mapping_Type *map; n &= 0xFF; str = SLang_process_keystring (str); if (*shift == '$') map = Shift_KeySym_Mapping; else if (*shift == '^') map = Control_KeySym_Mapping; else map = KeySym_Mapping; MEMCPY (map[n], str, MAX_KEYSYM_STRING_LEN); *(map[n]) -= 1; } static SLang_Name_Type sl_x_table[] = { MAKE_INTRINSIC(".x_set_window_name", set_window_name, VOID_TYPE, 1), MAKE_INTRINSIC(".x_set_icon_name", set_icon_name, VOID_TYPE, 1), MAKE_INTRINSIC(".x_warp_pointer", x_warp_pointer, VOID_TYPE, 0), MAKE_INTRINSIC(".x_insert_cutbuffer", x_insert_cutbuffer, INT_TYPE, 0), /* Prototype: Integer x_insert_cut_buffer (); * Inserts cutbuffer into the current buffer and returns the number * of characters inserted. */ MAKE_INTRINSIC(".x_copy_region_to_cutbuffer", x_region_2_cutbuffer, VOID_TYPE, 0), /*Prototype: Void x_copy_region_to_cutbuffer(); */ MAKE_INTRINSIC(".x_set_keysym", x_set_keysym, VOID_TYPE, 3), /*Prototype: Void x_set_keysym (Integer keysym, Integer shift, String str); * * This function may be used to assocate a string 'str' with a key * 'keysym' modified by mask @shift@. Pressing the key associated with * @keysym@ will then generate the keysequence given by @str@. The * function keys are mapped to integers in the range @0xFF00@ to @0xFFFF@. * On most systems, the keys that these mappings refer to are located in * the file @/usr/include/X11/keysymdef.h@. For example, on my system, the * keysyms for the function keys @XK_F1@ to @XK_F35@ fall in the range * @0xFFBE@ to @0xFFE0@. So to make the @F1@ key correspond to the string * given by the two characters @Ctrl-X@ @Ctrl-C@, simply use: * @ x_set_keysym (0xFFBE, 0, "^X^C"); * The @shift@ argument is an integer with the following meanings: * @ 0 : unmodified key * @ '$' : shifted * @ '^' : control * Any other value for shift will default to 0 (unshifted). */ MAKE_VARIABLE(".ALT_CHAR", &X_Alt_Char, INT_TYPE, 0), MAKE_VARIABLE(".X_LAST_KEYSYM", &X_Last_Keysym, INT_TYPE, 0), SLANG_END_TABLE }; static int X_init_slang (void) { return (SLang_add_table(sl_x_table, "XJed") && SLdefine_for_ifdef("XWINDOWS")); } static void X_update_open (void) { hide_cursor (); if (Check_Buffers_Pending) { check_buffers(); Check_Buffers_Pending = 0; } Performing_Update = 1; } static void X_update_close (void) { Performing_Update = 0; if (XWin->window_mapped == 0) JWindow->trashed = 1; if (JWindow->trashed) return; show_cursor (); if (X_Warp_Pending) XWarpPointer (This_XDisplay, None, XWin->w, 0, 0, 0, 0, XWin->vis_curs_col * XWin->font_width + XWin->border, (XWin->vis_curs_row + 1) * XWin->font_height + XWin->border); X_Warp_Pending = 0; } static void x_define_xkeys (SLKeyMap_List_Type *map) { SLkm_define_key ("^[[^D", (FVOID_STAR) scroll_right, map); SLkm_define_key ("^[[d", (FVOID_STAR) scroll_right, map); SLkm_define_key ("^[[^C", (FVOID_STAR) scroll_left, map); SLkm_define_key ("^[[c", (FVOID_STAR) scroll_left, map); SLkm_define_key ("^[[a", (FVOID_STAR) bob, map); SLkm_define_key ("^[[^A", (FVOID_STAR) bob, map); SLkm_define_key ("^[[b", (FVOID_STAR) eob, map); SLkm_define_key ("^[[^B", (FVOID_STAR) eob, map); } static void JX_reset_video (void) { tt_normal_video (); } static void JX_init_video (void) { } void flush_output (void) { fflush (stdout); } /* a hook to parse some command line args. */ int (*X_Argc_Argv_Hook)(int, char **) = X_eval_command_line; static void JX_get_terminfo (void) { JX_Screen_Cols = 80; JX_Screen_Rows = 24; Scroll_By_Copying = 1; /* init hooks */ X_Read_Hook = X_read_key; X_Input_Pending_Hook = X_input_pending; X_Get_Term_Size_Hook = X_Get_Term_Size; X_Update_Open_Hook = X_update_open; X_Update_Close_Hook = X_update_close; X_Suspend_Hook = xjed_suspend; X_Init_SLang_Hook = X_init_slang; X_Init_Term_Hook = init_Xdisplay; X_Reset_Term_Hook = reset_Xdisplay; X_Define_Keys_Hook = x_define_xkeys; SLang_Interrupt = xjed_check_kbd; /* Set this so that main will not try to read from stdin. It is quite * likely that this is started from a menu or something. */ Stdin_Is_TTY = -1; /* We do not need this since we do not have to worry about incoming * eight bit escape sequences. */ DEC_8Bit_Hack = 0; } /* the links to functions and variables here */ void (*tt_goto_rc)(int, int) = JX_goto_rc; void (*tt_begin_insert)(void) = JX_begin_insert; void (*tt_end_insert)(void) = JX_end_insert; void (*tt_del_eol)(void) = JX_del_eol; void (*tt_delete_nlines)(int) = JX_delete_nlines; void (*tt_delete_char)(void) = JX_delete_char; void (*tt_erase_line)(void) = JX_erase_line; void (*tt_tt_normal_video)(void) = JX_normal_video; void (*tt_cls)(void) = JX_cls; void (*tt_beep)(void) = JX_beep; void (*tt_reverse_index)(int) = JX_reverse_index; void (*tt_smart_puts)(unsigned short *, unsigned short *, int, int) = JX_smart_puts; void (*tt_write_string)(char *) = JX_write_string; void (*tt_putchar)(char) = JX_putchar; void (*tt_init_video)(void) = JX_init_video; void (*tt_reset_video)(void) = JX_reset_video; void (*tt_normal_video)(void) = JX_normal_video; void (*tt_set_scroll_region)(int, int) = JX_set_scroll_region; void (*tt_reset_scroll_region)(void) = JX_reset_scroll_region; void (*tt_get_terminfo)(void) = JX_get_terminfo; void (*tt_set_color)(int, char *, char *, char *) = JX_set_color; void (*tt_set_color_esc)(int, char *); void (*tt_wide_width)(void) = JX_wide_width; void (*tt_narrow_width)(void) = JX_narrow_width; void (*tt_enable_cursor_keys)(void) = JX_enable_cursor_keys; void (*tt_set_term_vtxxx)(int *) = JX_set_term_vtxxx; int *tt_Ignore_Beep = &JX_Ignore_Beep; int *tt_Use_Ansi_Colors = &JX_Use_Ansi_Colors; int *tt_Term_Cannot_Scroll = &JX_Term_Cannot_Scroll; int *tt_Term_Cannot_Insert = &JX_Term_Cannot_Insert; int *tt_Screen_Rows = &JX_Screen_Rows; int *tt_Screen_Cols = &JX_Screen_Cols; int *tt_Blink_Mode = &JX_Blink_Mode; static int Not_Used; int *tt_Baud_Rate = &Not_Used; /* Unused but required. */ int (*X_Open_Mouse_Hook)(void); void (*X_Close_Mouse_Hook)(void); int (*JMouse_Event_Hook)(void); void (*JMouse_Hide_Mouse_Hook)(int);
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.