misc.c revision c219fbeb
1c219fbebSmrg/* $XTermId: misc.c,v 1.520 2011/02/13 21:03:21 tom Exp $ */ 2d522f475Smrg 3d522f475Smrg/* 4c219fbebSmrg * Copyright 1999-2010,2011 by Thomas E. Dickey 5d522f475Smrg * 6cd3331d0Smrg * All Rights Reserved 7d522f475Smrg * 8d522f475Smrg * Permission is hereby granted, free of charge, to any person obtaining a 9d522f475Smrg * copy of this software and associated documentation files (the 10d522f475Smrg * "Software"), to deal in the Software without restriction, including 11d522f475Smrg * without limitation the rights to use, copy, modify, merge, publish, 12d522f475Smrg * distribute, sublicense, and/or sell copies of the Software, and to 13d522f475Smrg * permit persons to whom the Software is furnished to do so, subject to 14d522f475Smrg * the following conditions: 15d522f475Smrg * 16d522f475Smrg * The above copyright notice and this permission notice shall be included 17d522f475Smrg * in all copies or substantial portions of the Software. 18d522f475Smrg * 19d522f475Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20d522f475Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21d522f475Smrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 22d522f475Smrg * IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY 23d522f475Smrg * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24d522f475Smrg * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25d522f475Smrg * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26d522f475Smrg * 27d522f475Smrg * Except as contained in this notice, the name(s) of the above copyright 28d522f475Smrg * holders shall not be used in advertising or otherwise to promote the 29d522f475Smrg * sale, use or other dealings in this Software without prior written 30d522f475Smrg * authorization. 31d522f475Smrg * 32d522f475Smrg * 33d522f475Smrg * Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. 34d522f475Smrg * 35d522f475Smrg * All Rights Reserved 36d522f475Smrg * 37d522f475Smrg * Permission to use, copy, modify, and distribute this software and its 38d522f475Smrg * documentation for any purpose and without fee is hereby granted, 39d522f475Smrg * provided that the above copyright notice appear in all copies and that 40d522f475Smrg * both that copyright notice and this permission notice appear in 41d522f475Smrg * supporting documentation, and that the name of Digital Equipment 42d522f475Smrg * Corporation not be used in advertising or publicity pertaining to 43d522f475Smrg * distribution of the software without specific, written prior permission. 44d522f475Smrg * 45d522f475Smrg * 46d522f475Smrg * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 47d522f475Smrg * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 48d522f475Smrg * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 49d522f475Smrg * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 50d522f475Smrg * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 51d522f475Smrg * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 52d522f475Smrg * SOFTWARE. 53d522f475Smrg */ 54d522f475Smrg 55d522f475Smrg#include <version.h> 56b7c89284Ssnj#include <main.h> 57d522f475Smrg#include <xterm.h> 58d522f475Smrg 59d522f475Smrg#include <sys/stat.h> 60d522f475Smrg#include <stdio.h> 61d522f475Smrg#include <signal.h> 62d522f475Smrg#include <ctype.h> 63d522f475Smrg#include <pwd.h> 64d522f475Smrg#include <sys/wait.h> 65d522f475Smrg 66d522f475Smrg#include <X11/keysym.h> 67d522f475Smrg#include <X11/Xatom.h> 68d522f475Smrg#include <X11/cursorfont.h> 69d522f475Smrg#include <X11/Xlocale.h> 70d522f475Smrg 71d522f475Smrg#include <X11/Xmu/Error.h> 72d522f475Smrg#include <X11/Xmu/SysUtil.h> 73d522f475Smrg#include <X11/Xmu/WinUtil.h> 74d522f475Smrg#include <X11/Xmu/Xmu.h> 75d522f475Smrg#if HAVE_X11_SUNKEYSYM_H 76d522f475Smrg#include <X11/Sunkeysym.h> 77d522f475Smrg#endif 78d522f475Smrg 79d522f475Smrg#ifdef HAVE_LANGINFO_CODESET 80d522f475Smrg#include <langinfo.h> 81d522f475Smrg#endif 82d522f475Smrg 83d522f475Smrg#include <xutf8.h> 84d522f475Smrg 85d522f475Smrg#include <data.h> 86d522f475Smrg#include <error.h> 87d522f475Smrg#include <menu.h> 88d522f475Smrg#include <fontutils.h> 89d522f475Smrg#include <xcharmouse.h> 90d522f475Smrg#include <xstrings.h> 91d522f475Smrg#include <xtermcap.h> 92d522f475Smrg#include <VTparse.h> 93d522f475Smrg 94d522f475Smrg#include <assert.h> 95d522f475Smrg 96d522f475Smrg#if (XtSpecificationRelease < 6) 97d522f475Smrg#ifndef X_GETTIMEOFDAY 98d522f475Smrg#define X_GETTIMEOFDAY(t) gettimeofday(t,(struct timezone *)0) 99d522f475Smrg#endif 100d522f475Smrg#endif 101d522f475Smrg 102d522f475Smrg#ifdef VMS 103d522f475Smrg#define XTERM_VMS_LOGFILE "SYS$SCRATCH:XTERM_LOG.TXT" 104d522f475Smrg#ifdef ALLOWLOGFILEEXEC 105d522f475Smrg#undef ALLOWLOGFILEEXEC 106d522f475Smrg#endif 107d522f475Smrg#endif /* VMS */ 108d522f475Smrg 109d522f475Smrg#if OPT_TEK4014 110d522f475Smrg#define OUR_EVENT(event,Type) \ 111d522f475Smrg (event.type == Type && \ 112d522f475Smrg (event.xcrossing.window == XtWindow(XtParent(xw)) || \ 113d522f475Smrg (tekWidget && \ 114d522f475Smrg event.xcrossing.window == XtWindow(XtParent(tekWidget))))) 115d522f475Smrg#else 116d522f475Smrg#define OUR_EVENT(event,Type) \ 117d522f475Smrg (event.type == Type && \ 118d522f475Smrg (event.xcrossing.window == XtWindow(XtParent(xw)))) 119d522f475Smrg#endif 120d522f475Smrg 121d522f475Smrgstatic Cursor make_hidden_cursor(XtermWidget); 122d522f475Smrg 123d522f475Smrg#if OPT_EXEC_XTERM 124d522f475Smrg/* Like readlink(2), but returns a malloc()ed buffer, or NULL on 125d522f475Smrg error; adapted from libc docs */ 126d522f475Smrgstatic char * 127d522f475SmrgReadlink(const char *filename) 128d522f475Smrg{ 129d522f475Smrg char *buf = NULL; 130cd3331d0Smrg size_t size = 100; 131d522f475Smrg int n; 132d522f475Smrg 133d522f475Smrg for (;;) { 134d522f475Smrg buf = TypeRealloc(char, size, buf); 135d522f475Smrg memset(buf, 0, size); 136d522f475Smrg 137cd3331d0Smrg n = (int) readlink(filename, buf, size); 138d522f475Smrg if (n < 0) { 139d522f475Smrg free(buf); 140d522f475Smrg return NULL; 141d522f475Smrg } 142d522f475Smrg 143d522f475Smrg if ((unsigned) n < size) { 144d522f475Smrg return buf; 145d522f475Smrg } 146d522f475Smrg 147d522f475Smrg size *= 2; 148d522f475Smrg } 149d522f475Smrg} 150d522f475Smrg#endif /* OPT_EXEC_XTERM */ 151d522f475Smrg 152d522f475Smrgstatic void 153d522f475SmrgSleep(int msec) 154d522f475Smrg{ 155d522f475Smrg static struct timeval select_timeout; 156d522f475Smrg 157d522f475Smrg select_timeout.tv_sec = 0; 158d522f475Smrg select_timeout.tv_usec = msec * 1000; 159d522f475Smrg select(0, 0, 0, 0, &select_timeout); 160d522f475Smrg} 161d522f475Smrg 162d522f475Smrgstatic void 163d522f475Smrgselectwindow(TScreen * screen, int flag) 164d522f475Smrg{ 165d522f475Smrg TRACE(("selectwindow(%d) flag=%d\n", screen->select, flag)); 166d522f475Smrg 167d522f475Smrg#if OPT_TEK4014 168d522f475Smrg if (TEK4014_ACTIVE(term)) { 169d522f475Smrg if (!Ttoggled) 170d522f475Smrg TCursorToggle(tekWidget, TOGGLE); 171d522f475Smrg screen->select |= flag; 172d522f475Smrg if (!Ttoggled) 173d522f475Smrg TCursorToggle(tekWidget, TOGGLE); 174d522f475Smrg } else 175d522f475Smrg#endif 176d522f475Smrg { 177d522f475Smrg if (screen->xic) 178d522f475Smrg XSetICFocus(screen->xic); 179d522f475Smrg 180d522f475Smrg if (screen->cursor_state && CursorMoved(screen)) 181d522f475Smrg HideCursor(); 182d522f475Smrg screen->select |= flag; 183d522f475Smrg if (screen->cursor_state) 184d522f475Smrg ShowCursor(); 185d522f475Smrg } 186cd3331d0Smrg GetScrollLock(screen); 187d522f475Smrg} 188d522f475Smrg 189d522f475Smrgstatic void 190d522f475Smrgunselectwindow(TScreen * screen, int flag) 191d522f475Smrg{ 192d522f475Smrg TRACE(("unselectwindow(%d) flag=%d\n", screen->select, flag)); 193d522f475Smrg 194d522f475Smrg if (screen->hide_pointer) { 195d522f475Smrg screen->hide_pointer = False; 196d522f475Smrg xtermDisplayCursor(term); 197d522f475Smrg } 198d522f475Smrg 199d522f475Smrg if (!screen->always_highlight) { 200d522f475Smrg#if OPT_TEK4014 201d522f475Smrg if (TEK4014_ACTIVE(term)) { 202d522f475Smrg if (!Ttoggled) 203d522f475Smrg TCursorToggle(tekWidget, TOGGLE); 204d522f475Smrg screen->select &= ~flag; 205d522f475Smrg if (!Ttoggled) 206d522f475Smrg TCursorToggle(tekWidget, TOGGLE); 207d522f475Smrg } else 208d522f475Smrg#endif 209d522f475Smrg { 210d522f475Smrg if (screen->xic) 211d522f475Smrg XUnsetICFocus(screen->xic); 212d522f475Smrg 213d522f475Smrg screen->select &= ~flag; 214d522f475Smrg if (screen->cursor_state && CursorMoved(screen)) 215d522f475Smrg HideCursor(); 216d522f475Smrg if (screen->cursor_state) 217d522f475Smrg ShowCursor(); 218d522f475Smrg } 219d522f475Smrg } 220d522f475Smrg} 221d522f475Smrg 222d522f475Smrgstatic void 223d522f475SmrgDoSpecialEnterNotify(XtermWidget xw, XEnterWindowEvent * ev) 224d522f475Smrg{ 225d522f475Smrg TScreen *screen = TScreenOf(xw); 226d522f475Smrg 227d522f475Smrg TRACE(("DoSpecialEnterNotify(%d)\n", screen->select)); 228cd3331d0Smrg TRACE_FOCUS(xw, ev); 229cd3331d0Smrg if (((ev->detail) != NotifyInferior) && 230cd3331d0Smrg ev->focus && 231cd3331d0Smrg !(screen->select & FOCUS)) 232cd3331d0Smrg selectwindow(screen, INWINDOW); 233d522f475Smrg} 234d522f475Smrg 235d522f475Smrgstatic void 236d522f475SmrgDoSpecialLeaveNotify(XtermWidget xw, XEnterWindowEvent * ev) 237d522f475Smrg{ 238d522f475Smrg TScreen *screen = TScreenOf(xw); 239d522f475Smrg 240d522f475Smrg TRACE(("DoSpecialLeaveNotify(%d)\n", screen->select)); 241cd3331d0Smrg TRACE_FOCUS(xw, ev); 242cd3331d0Smrg if (((ev->detail) != NotifyInferior) && 243cd3331d0Smrg ev->focus && 244cd3331d0Smrg !(screen->select & FOCUS)) 245cd3331d0Smrg unselectwindow(screen, INWINDOW); 246d522f475Smrg} 247d522f475Smrg 248d522f475Smrg#ifndef XUrgencyHint 249d522f475Smrg#define XUrgencyHint (1L << 8) /* X11R5 does not define */ 250d522f475Smrg#endif 251d522f475Smrg 252d522f475Smrgstatic void 253c219fbebSmrgsetXUrgency(XtermWidget xw, Bool enable) 254d522f475Smrg{ 255c219fbebSmrg TScreen *screen = TScreenOf(xw); 256c219fbebSmrg 257d522f475Smrg if (screen->bellIsUrgent) { 258c219fbebSmrg XWMHints *h = XGetWMHints(screen->display, VShellWindow(xw)); 259d522f475Smrg if (h != 0) { 260c219fbebSmrg if (enable && !(screen->select & FOCUS)) { 261d522f475Smrg h->flags |= XUrgencyHint; 262d522f475Smrg } else { 263d522f475Smrg h->flags &= ~XUrgencyHint; 264d522f475Smrg } 265c219fbebSmrg XSetWMHints(screen->display, VShellWindow(xw), h); 266d522f475Smrg } 267d522f475Smrg } 268d522f475Smrg} 269d522f475Smrg 270d522f475Smrgvoid 271d522f475Smrgdo_xevents(void) 272d522f475Smrg{ 273d522f475Smrg TScreen *screen = TScreenOf(term); 274d522f475Smrg 275d522f475Smrg if (XtAppPending(app_con) 276d522f475Smrg || 277d522f475Smrg#if defined(VMS) || defined(__VMS) 278d522f475Smrg screen->display->qlen > 0 279d522f475Smrg#else 280d522f475Smrg GetBytesAvailable(ConnectionNumber(screen->display)) > 0 281d522f475Smrg#endif 282d522f475Smrg ) 283d522f475Smrg xevents(); 284d522f475Smrg} 285d522f475Smrg 286d522f475Smrgvoid 287d522f475SmrgxtermDisplayCursor(XtermWidget xw) 288d522f475Smrg{ 289d522f475Smrg TScreen *screen = TScreenOf(xw); 290d522f475Smrg 291d522f475Smrg if (screen->Vshow) { 292d522f475Smrg if (screen->hide_pointer) { 293d522f475Smrg TRACE(("Display hidden_cursor\n")); 294d522f475Smrg XDefineCursor(screen->display, VWindow(screen), screen->hidden_cursor); 295d522f475Smrg } else { 296d522f475Smrg TRACE(("Display pointer_cursor\n")); 297d522f475Smrg recolor_cursor(screen, 298d522f475Smrg screen->pointer_cursor, 299d522f475Smrg T_COLOR(screen, MOUSE_FG), 300d522f475Smrg T_COLOR(screen, MOUSE_BG)); 301d522f475Smrg XDefineCursor(screen->display, VWindow(screen), screen->pointer_cursor); 302d522f475Smrg } 303d522f475Smrg } 304d522f475Smrg} 305d522f475Smrg 306d522f475Smrgvoid 307d522f475SmrgxtermShowPointer(XtermWidget xw, Bool enable) 308d522f475Smrg{ 309d522f475Smrg static int tried = -1; 310d522f475Smrg TScreen *screen = TScreenOf(xw); 311d522f475Smrg 312d522f475Smrg#if OPT_TEK4014 313d522f475Smrg if (TEK4014_SHOWN(xw)) 314d522f475Smrg enable = True; 315d522f475Smrg#endif 316d522f475Smrg 317d522f475Smrg /* 318d522f475Smrg * Whether we actually hide the pointer depends on the pointer-mode and 319d522f475Smrg * the mouse-mode: 320d522f475Smrg */ 321d522f475Smrg if (!enable) { 322d522f475Smrg switch (screen->pointer_mode) { 323d522f475Smrg case pNever: 324d522f475Smrg enable = True; 325d522f475Smrg break; 326d522f475Smrg case pNoMouse: 327d522f475Smrg if (screen->send_mouse_pos != MOUSE_OFF) 328d522f475Smrg enable = True; 329d522f475Smrg break; 330d522f475Smrg case pAlways: 331d522f475Smrg break; 332d522f475Smrg } 333d522f475Smrg } 334d522f475Smrg 335d522f475Smrg if (enable) { 336d522f475Smrg if (screen->hide_pointer) { 337d522f475Smrg screen->hide_pointer = False; 338d522f475Smrg xtermDisplayCursor(xw); 339d522f475Smrg switch (screen->send_mouse_pos) { 340d522f475Smrg case ANY_EVENT_MOUSE: 341d522f475Smrg break; 342d522f475Smrg default: 343d522f475Smrg MotionOff(screen, xw); 344d522f475Smrg break; 345d522f475Smrg } 346d522f475Smrg } 347d522f475Smrg } else if (!(screen->hide_pointer) && (tried <= 0)) { 348d522f475Smrg if (screen->hidden_cursor == 0) { 349d522f475Smrg screen->hidden_cursor = make_hidden_cursor(xw); 350d522f475Smrg } 351d522f475Smrg if (screen->hidden_cursor == 0) { 352d522f475Smrg tried = 1; 353d522f475Smrg } else { 354d522f475Smrg tried = 0; 355d522f475Smrg screen->hide_pointer = True; 356d522f475Smrg xtermDisplayCursor(xw); 357d522f475Smrg MotionOn(screen, xw); 358d522f475Smrg } 359d522f475Smrg } 360d522f475Smrg} 361d522f475Smrg 362d522f475Smrgvoid 363d522f475Smrgxevents(void) 364d522f475Smrg{ 365d522f475Smrg XtermWidget xw = term; 366d522f475Smrg TScreen *screen = TScreenOf(xw); 367d522f475Smrg XEvent event; 368d522f475Smrg XtInputMask input_mask; 369d522f475Smrg 370d522f475Smrg if (need_cleanup) 371d522f475Smrg Cleanup(0); 372d522f475Smrg 373d522f475Smrg if (screen->scroll_amt) 374d522f475Smrg FlushScroll(xw); 375d522f475Smrg /* 376d522f475Smrg * process timeouts, relying on the fact that XtAppProcessEvent 377d522f475Smrg * will process the timeout and return without blockng on the 378cd3331d0Smrg * XEvent queue. Other sources i.e., the pty are handled elsewhere 379d522f475Smrg * with select(). 380d522f475Smrg */ 381cd3331d0Smrg while ((input_mask = XtAppPending(app_con)) != 0) { 382cd3331d0Smrg if (input_mask & XtIMTimer) 383cd3331d0Smrg XtAppProcessEvent(app_con, (XtInputMask) XtIMTimer); 384d522f475Smrg#if OPT_SESSION_MGT 385cd3331d0Smrg /* 386cd3331d0Smrg * Session management events are alternative input events. Deal with 387cd3331d0Smrg * them in the same way. 388cd3331d0Smrg */ 389cd3331d0Smrg else if (input_mask & XtIMAlternateInput) 390cd3331d0Smrg XtAppProcessEvent(app_con, (XtInputMask) XtIMAlternateInput); 391d522f475Smrg#endif 392cd3331d0Smrg else 393cd3331d0Smrg break; 394cd3331d0Smrg } 395d522f475Smrg 396d522f475Smrg /* 397d522f475Smrg * If there's no XEvents, don't wait around... 398d522f475Smrg */ 399d522f475Smrg if ((input_mask & XtIMXEvent) != XtIMXEvent) 400d522f475Smrg return; 401d522f475Smrg do { 402d522f475Smrg /* 403d522f475Smrg * This check makes xterm hang when in mouse hilite tracking mode. 404d522f475Smrg * We simply ignore all events except for those not passed down to 405d522f475Smrg * this function, e.g., those handled in in_put(). 406d522f475Smrg */ 407d522f475Smrg if (screen->waitingForTrackInfo) { 408d522f475Smrg Sleep(10); 409d522f475Smrg return; 410d522f475Smrg } 411d522f475Smrg XtAppNextEvent(app_con, &event); 412d522f475Smrg /* 413d522f475Smrg * Hack to get around problems with the toolkit throwing away 414d522f475Smrg * eventing during the exclusive grab of the menu popup. By 415d522f475Smrg * looking at the event ourselves we make sure that we can 416d522f475Smrg * do the right thing. 417d522f475Smrg */ 418d522f475Smrg if (OUR_EVENT(event, EnterNotify)) { 419d522f475Smrg DoSpecialEnterNotify(xw, &event.xcrossing); 420d522f475Smrg } else if (OUR_EVENT(event, LeaveNotify)) { 421d522f475Smrg DoSpecialLeaveNotify(xw, &event.xcrossing); 422d522f475Smrg } else if ((screen->send_mouse_pos == ANY_EVENT_MOUSE 423d522f475Smrg#if OPT_DEC_LOCATOR 424d522f475Smrg || screen->send_mouse_pos == DEC_LOCATOR 425d522f475Smrg#endif /* OPT_DEC_LOCATOR */ 426d522f475Smrg ) 427d522f475Smrg && event.xany.type == MotionNotify 428d522f475Smrg && event.xcrossing.window == XtWindow(xw)) { 429d522f475Smrg SendMousePosition(xw, &event); 430cb4a1343Smrg xtermShowPointer(xw, True); 431d522f475Smrg continue; 432d522f475Smrg } 433d522f475Smrg 434cb4a1343Smrg /* 435cb4a1343Smrg * If the event is interesting (and not a keyboard event), turn the 436cb4a1343Smrg * mouse pointer back on. 437cb4a1343Smrg */ 438cb4a1343Smrg if (screen->hide_pointer) { 439cb4a1343Smrg switch (event.xany.type) { 440cb4a1343Smrg case KeyPress: 441cb4a1343Smrg case KeyRelease: 442cb4a1343Smrg case ButtonPress: 443cb4a1343Smrg case ButtonRelease: 444cb4a1343Smrg /* also these... */ 445cb4a1343Smrg case Expose: 446cb4a1343Smrg case NoExpose: 447cb4a1343Smrg case PropertyNotify: 448cb4a1343Smrg case ClientMessage: 449cb4a1343Smrg break; 450cb4a1343Smrg default: 451cb4a1343Smrg xtermShowPointer(xw, True); 452cb4a1343Smrg break; 453cb4a1343Smrg } 454cb4a1343Smrg } 455cb4a1343Smrg 456d522f475Smrg if (!event.xany.send_event || 457d522f475Smrg screen->allowSendEvents || 458d522f475Smrg ((event.xany.type != KeyPress) && 459d522f475Smrg (event.xany.type != KeyRelease) && 460d522f475Smrg (event.xany.type != ButtonPress) && 461d522f475Smrg (event.xany.type != ButtonRelease))) { 462d522f475Smrg 463d522f475Smrg XtDispatchEvent(&event); 464d522f475Smrg } 465cd3331d0Smrg } while (XtAppPending(app_con) & XtIMXEvent); 466d522f475Smrg} 467d522f475Smrg 468d522f475Smrgstatic Cursor 469d522f475Smrgmake_hidden_cursor(XtermWidget xw) 470d522f475Smrg{ 471d522f475Smrg TScreen *screen = TScreenOf(xw); 472d522f475Smrg Cursor c; 473d522f475Smrg Display *dpy = screen->display; 474d522f475Smrg XFontStruct *fn; 475d522f475Smrg 476d522f475Smrg static XColor dummy; 477d522f475Smrg 478d522f475Smrg /* 479d522f475Smrg * Prefer nil2 (which is normally available) to "fixed" (which is supposed 480d522f475Smrg * to be "always" available), since it's a smaller glyph in case the 481b7c89284Ssnj * server insists on drawing _something_. 482d522f475Smrg */ 483d522f475Smrg TRACE(("Ask for nil2 font\n")); 484d522f475Smrg if ((fn = XLoadQueryFont(dpy, "nil2")) == 0) { 485d522f475Smrg TRACE(("...Ask for fixed font\n")); 486b7c89284Ssnj fn = XLoadQueryFont(dpy, DEFFONT); 487d522f475Smrg } 488d522f475Smrg 489d522f475Smrg if (fn != 0) { 490d522f475Smrg /* a space character seems to work as a cursor (dots are not needed) */ 491d522f475Smrg c = XCreateGlyphCursor(dpy, fn->fid, fn->fid, 'X', ' ', &dummy, &dummy); 492d522f475Smrg XFreeFont(dpy, fn); 493d522f475Smrg } else { 494d522f475Smrg c = 0; 495d522f475Smrg } 496d522f475Smrg TRACE(("XCreateGlyphCursor ->%#lx\n", c)); 497d522f475Smrg return (c); 498d522f475Smrg} 499d522f475Smrg 500d522f475SmrgCursor 501d522f475Smrgmake_colored_cursor(unsigned cursorindex, /* index into font */ 502d522f475Smrg unsigned long fg, /* pixel value */ 503d522f475Smrg unsigned long bg) /* pixel value */ 504d522f475Smrg{ 505d522f475Smrg TScreen *screen = TScreenOf(term); 506d522f475Smrg Cursor c; 507d522f475Smrg Display *dpy = screen->display; 508d522f475Smrg 509d522f475Smrg c = XCreateFontCursor(dpy, cursorindex); 510d522f475Smrg if (c != None) { 511d522f475Smrg recolor_cursor(screen, c, fg, bg); 512d522f475Smrg } 513d522f475Smrg return (c); 514d522f475Smrg} 515d522f475Smrg 516d522f475Smrg/* ARGSUSED */ 517d522f475Smrgvoid 518d522f475SmrgHandleKeyPressed(Widget w GCC_UNUSED, 519d522f475Smrg XEvent * event, 520d522f475Smrg String * params GCC_UNUSED, 521d522f475Smrg Cardinal *nparams GCC_UNUSED) 522d522f475Smrg{ 523cd3331d0Smrg TRACE(("Handle insert-seven-bit for %p\n", (void *) w)); 524cd3331d0Smrg Input(term, &event->xkey, False); 525d522f475Smrg} 526d522f475Smrg 527d522f475Smrg/* ARGSUSED */ 528d522f475Smrgvoid 529d522f475SmrgHandleEightBitKeyPressed(Widget w GCC_UNUSED, 530d522f475Smrg XEvent * event, 531d522f475Smrg String * params GCC_UNUSED, 532d522f475Smrg Cardinal *nparams GCC_UNUSED) 533d522f475Smrg{ 534cd3331d0Smrg TRACE(("Handle insert-eight-bit for %p\n", (void *) w)); 535cd3331d0Smrg Input(term, &event->xkey, True); 536d522f475Smrg} 537d522f475Smrg 538d522f475Smrg/* ARGSUSED */ 539d522f475Smrgvoid 540d522f475SmrgHandleStringEvent(Widget w GCC_UNUSED, 541d522f475Smrg XEvent * event GCC_UNUSED, 542d522f475Smrg String * params, 543d522f475Smrg Cardinal *nparams) 544d522f475Smrg{ 545d522f475Smrg 546d522f475Smrg if (*nparams != 1) 547d522f475Smrg return; 548d522f475Smrg 549d522f475Smrg if ((*params)[0] == '0' && (*params)[1] == 'x' && (*params)[2] != '\0') { 5500d92cbfdSchristos const char *abcdef = "ABCDEF"; 5510d92cbfdSchristos const char *xxxxxx; 552cd3331d0Smrg Char c; 553cd3331d0Smrg UString p; 5540d92cbfdSchristos unsigned value = 0; 5550d92cbfdSchristos 556cd3331d0Smrg for (p = (UString) (*params + 2); (c = CharOf(x_toupper(*p))) != 5570d92cbfdSchristos '\0'; p++) { 5580d92cbfdSchristos value *= 16; 559d522f475Smrg if (c >= '0' && c <= '9') 5600d92cbfdSchristos value += (unsigned) (c - '0'); 5610d92cbfdSchristos else if ((xxxxxx = strchr(abcdef, c)) != 0) 5620d92cbfdSchristos value += (unsigned) (xxxxxx - abcdef) + 10; 563d522f475Smrg else 564d522f475Smrg break; 565d522f475Smrg } 5660d92cbfdSchristos if (c == '\0') { 5670d92cbfdSchristos Char hexval[2]; 5680d92cbfdSchristos hexval[0] = (Char) value; 5690d92cbfdSchristos hexval[1] = 0; 570b7c89284Ssnj StringInput(term, hexval, (size_t) 1); 5710d92cbfdSchristos } 572d522f475Smrg } else { 573cd3331d0Smrg StringInput(term, (const Char *) *params, strlen(*params)); 574d522f475Smrg } 575d522f475Smrg} 576d522f475Smrg 577d522f475Smrg#if OPT_EXEC_XTERM 578d522f475Smrg 579d522f475Smrg#ifndef PROCFS_ROOT 580d522f475Smrg#define PROCFS_ROOT "/proc" 581d522f475Smrg#endif 582d522f475Smrg 583d522f475Smrg/* ARGSUSED */ 584d522f475Smrgvoid 585d522f475SmrgHandleSpawnTerminal(Widget w GCC_UNUSED, 586d522f475Smrg XEvent * event GCC_UNUSED, 587d522f475Smrg String * params, 588d522f475Smrg Cardinal *nparams) 589d522f475Smrg{ 590cd3331d0Smrg TScreen *screen = TScreenOf(term); 591d522f475Smrg char *child_cwd = NULL; 592d522f475Smrg char *child_exe; 593d522f475Smrg pid_t pid; 594d522f475Smrg 595d522f475Smrg /* 596d522f475Smrg * Try to find the actual program which is running in the child process. 597d522f475Smrg * This works for Linux. If we cannot find the program, fall back to the 598d522f475Smrg * xterm program (which is usually adequate). Give up if we are given only 599d522f475Smrg * a relative path to xterm, since that would not always match $PATH. 600d522f475Smrg */ 601d522f475Smrg child_exe = Readlink(PROCFS_ROOT "/self/exe"); 602d522f475Smrg if (!child_exe) { 603cd3331d0Smrg if (strncmp(ProgramName, "./", (size_t) 2) 604cd3331d0Smrg && strncmp(ProgramName, "../", (size_t) 3)) { 605d522f475Smrg child_exe = xtermFindShell(ProgramName, True); 606d522f475Smrg } else { 607d522f475Smrg fprintf(stderr, "Cannot exec-xterm given %s\n", ProgramName); 608d522f475Smrg } 609d522f475Smrg if (child_exe == 0) 610d522f475Smrg return; 611d522f475Smrg } 612d522f475Smrg 613d522f475Smrg /* 614d522f475Smrg * Determine the current working directory of the child so that we can 615d522f475Smrg * spawn a new terminal in the same directory. 616d522f475Smrg * 617d522f475Smrg * If we cannot get the CWD of the child, just use our own. 618d522f475Smrg */ 619d522f475Smrg if (screen->pid) { 620d522f475Smrg char child_cwd_link[sizeof(PROCFS_ROOT) + 80]; 621d522f475Smrg sprintf(child_cwd_link, PROCFS_ROOT "/%lu/cwd", (unsigned long) screen->pid); 622d522f475Smrg child_cwd = Readlink(child_cwd_link); 623d522f475Smrg } 624d522f475Smrg 625d522f475Smrg /* The reaper will take care of cleaning up the child */ 626d522f475Smrg pid = fork(); 627d522f475Smrg if (pid == -1) { 628d522f475Smrg fprintf(stderr, "Could not fork: %s\n", SysErrorMsg(errno)); 629d522f475Smrg } else if (!pid) { 630d522f475Smrg /* We are the child */ 631d522f475Smrg if (child_cwd) { 632cd3331d0Smrg IGNORE_RC(chdir(child_cwd)); /* We don't care if this fails */ 633d522f475Smrg } 634d522f475Smrg 635d522f475Smrg if (setuid(screen->uid) == -1 636d522f475Smrg || setgid(screen->gid) == -1) { 637d522f475Smrg fprintf(stderr, "Cannot reset uid/gid\n"); 638d522f475Smrg } else { 6390d92cbfdSchristos unsigned myargc = *nparams + 1; 640d522f475Smrg char **myargv = TypeMallocN(char *, myargc + 1); 6410d92cbfdSchristos unsigned n = 0; 642d522f475Smrg 643d522f475Smrg myargv[n++] = child_exe; 644d522f475Smrg 645d522f475Smrg while (n < myargc) { 646d522f475Smrg myargv[n++] = *params++; 647d522f475Smrg } 648d522f475Smrg 649d522f475Smrg myargv[n] = 0; 650d522f475Smrg execv(child_exe, myargv); 651d522f475Smrg 652d522f475Smrg /* If we get here, we've failed */ 653d522f475Smrg fprintf(stderr, "exec of '%s': %s\n", child_exe, SysErrorMsg(errno)); 654d522f475Smrg } 655d522f475Smrg _exit(0); 656d522f475Smrg } else { 657d522f475Smrg /* We are the parent; clean up */ 658d522f475Smrg if (child_cwd) 659d522f475Smrg free(child_cwd); 660d522f475Smrg if (child_exe) 661d522f475Smrg free(child_exe); 662d522f475Smrg } 663d522f475Smrg} 664d522f475Smrg#endif /* OPT_EXEC_XTERM */ 665d522f475Smrg 666d522f475Smrg/* 667d522f475Smrg * Rather than sending characters to the host, put them directly into our 668d522f475Smrg * input queue. That lets a user have access to any of the control sequences 669d522f475Smrg * for a key binding. This is the equivalent of local function key support. 670d522f475Smrg * 671d522f475Smrg * NOTE: This code does not support the hexadecimal kludge used in 672d522f475Smrg * HandleStringEvent because it prevents us from sending an arbitrary string 673d522f475Smrg * (but it appears in a lot of examples - so we are stuck with it). The 674d522f475Smrg * standard string converter does recognize "\" for newline ("\n") and for 675d522f475Smrg * octal constants (e.g., "\007" for BEL). So we assume the user can make do 676d522f475Smrg * without a specialized converter. (Don't try to use \000, though). 677d522f475Smrg */ 678d522f475Smrg/* ARGSUSED */ 679d522f475Smrgvoid 680d522f475SmrgHandleInterpret(Widget w GCC_UNUSED, 681d522f475Smrg XEvent * event GCC_UNUSED, 682d522f475Smrg String * params, 683d522f475Smrg Cardinal *param_count) 684d522f475Smrg{ 685d522f475Smrg if (*param_count == 1) { 686cd3331d0Smrg const char *value = params[0]; 687b7c89284Ssnj int need = (int) strlen(value); 688cd3331d0Smrg int used = (int) (VTbuffer->next - VTbuffer->buffer); 689cd3331d0Smrg int have = (int) (VTbuffer->last - VTbuffer->buffer); 690d522f475Smrg 691d522f475Smrg if (have - used + need < BUF_SIZE) { 692d522f475Smrg 693cd3331d0Smrg fillPtyData(term, VTbuffer, value, (int) strlen(value)); 694d522f475Smrg 695d522f475Smrg TRACE(("Interpret %s\n", value)); 696d522f475Smrg VTbuffer->update++; 697d522f475Smrg } 698d522f475Smrg } 699d522f475Smrg} 700d522f475Smrg 701d522f475Smrg/*ARGSUSED*/ 702d522f475Smrgvoid 703d522f475SmrgHandleEnterWindow(Widget w GCC_UNUSED, 704d522f475Smrg XtPointer eventdata GCC_UNUSED, 705d522f475Smrg XEvent * event GCC_UNUSED, 706d522f475Smrg Boolean * cont GCC_UNUSED) 707d522f475Smrg{ 708d522f475Smrg /* NOP since we handled it above */ 709d522f475Smrg TRACE(("HandleEnterWindow ignored\n")); 710cd3331d0Smrg TRACE_FOCUS(w, event); 711d522f475Smrg} 712d522f475Smrg 713d522f475Smrg/*ARGSUSED*/ 714d522f475Smrgvoid 715d522f475SmrgHandleLeaveWindow(Widget w GCC_UNUSED, 716d522f475Smrg XtPointer eventdata GCC_UNUSED, 717d522f475Smrg XEvent * event GCC_UNUSED, 718d522f475Smrg Boolean * cont GCC_UNUSED) 719d522f475Smrg{ 720d522f475Smrg /* NOP since we handled it above */ 721d522f475Smrg TRACE(("HandleLeaveWindow ignored\n")); 722cd3331d0Smrg TRACE_FOCUS(w, event); 723d522f475Smrg} 724d522f475Smrg 725d522f475Smrg/*ARGSUSED*/ 726d522f475Smrgvoid 727d522f475SmrgHandleFocusChange(Widget w GCC_UNUSED, 728d522f475Smrg XtPointer eventdata GCC_UNUSED, 729d522f475Smrg XEvent * ev, 730d522f475Smrg Boolean * cont GCC_UNUSED) 731d522f475Smrg{ 732d522f475Smrg XFocusChangeEvent *event = (XFocusChangeEvent *) ev; 733d522f475Smrg XtermWidget xw = term; 734d522f475Smrg TScreen *screen = TScreenOf(xw); 735d522f475Smrg 736d522f475Smrg TRACE(("HandleFocusChange type=%s, mode=%d, detail=%d\n", 737d522f475Smrg visibleEventType(event->type), 738d522f475Smrg event->mode, 739d522f475Smrg event->detail)); 740cd3331d0Smrg TRACE_FOCUS(xw, event); 741d522f475Smrg 742d522f475Smrg if (screen->quiet_grab 743d522f475Smrg && (event->mode == NotifyGrab || event->mode == NotifyUngrab)) { 744c219fbebSmrg /* EMPTY */ ; 745d522f475Smrg } else if (event->type == FocusIn) { 746c219fbebSmrg setXUrgency(xw, False); 747d522f475Smrg 748d522f475Smrg /* 749d522f475Smrg * NotifyNonlinear only happens (on FocusIn) if the pointer was not in 750d522f475Smrg * one of our windows. Use this to reset a case where one xterm is 751d522f475Smrg * partly obscuring another, and X gets (us) confused about whether the 752d522f475Smrg * pointer was in the window. In particular, this can happen if the 753d522f475Smrg * user is resizing the obscuring window, causing some events to not be 754d522f475Smrg * delivered to the obscured window. 755d522f475Smrg */ 756d522f475Smrg if (event->detail == NotifyNonlinear 757d522f475Smrg && (screen->select & INWINDOW) != 0) { 758d522f475Smrg unselectwindow(screen, INWINDOW); 759d522f475Smrg } 760d522f475Smrg selectwindow(screen, 761d522f475Smrg ((event->detail == NotifyPointer) 762d522f475Smrg ? INWINDOW 763d522f475Smrg : FOCUS)); 764d522f475Smrg SendFocusButton(xw, event); 765d522f475Smrg } else { 766d522f475Smrg#if OPT_FOCUS_EVENT 767d522f475Smrg if (event->type == FocusOut) { 768d522f475Smrg SendFocusButton(xw, event); 769d522f475Smrg } 770d522f475Smrg#endif 771d522f475Smrg /* 772d522f475Smrg * XGrabKeyboard() will generate NotifyGrab event that we want to 773d522f475Smrg * ignore. 774d522f475Smrg */ 775d522f475Smrg if (event->mode != NotifyGrab) { 776d522f475Smrg unselectwindow(screen, 777d522f475Smrg ((event->detail == NotifyPointer) 778d522f475Smrg ? INWINDOW 779d522f475Smrg : FOCUS)); 780d522f475Smrg } 781d522f475Smrg if (screen->grabbedKbd && (event->mode == NotifyUngrab)) { 782cd3331d0Smrg Bell(xw, XkbBI_Info, 100); 783d522f475Smrg ReverseVideo(xw); 784d522f475Smrg screen->grabbedKbd = False; 785d522f475Smrg update_securekbd(); 786d522f475Smrg } 787d522f475Smrg } 788d522f475Smrg} 789d522f475Smrg 790d522f475Smrgstatic long lastBellTime; /* in milliseconds */ 791d522f475Smrg 792b7c89284Ssnj#if defined(HAVE_XKB_BELL_EXT) 793b7c89284Ssnjstatic Atom 794b7c89284SsnjAtomBell(XtermWidget xw, int which) 795b7c89284Ssnj{ 796b7c89284Ssnj#define DATA(name) { XkbBI_##name, XkbBN_##name } 797b7c89284Ssnj static struct { 798b7c89284Ssnj int value; 799b7c89284Ssnj const char *name; 800b7c89284Ssnj } table[] = { 801b7c89284Ssnj DATA(Info), 802b7c89284Ssnj DATA(MarginBell), 803b7c89284Ssnj DATA(MinorError), 804b7c89284Ssnj DATA(TerminalBell) 805b7c89284Ssnj }; 806b7c89284Ssnj Cardinal n; 807b7c89284Ssnj Atom result = None; 808b7c89284Ssnj 809b7c89284Ssnj for (n = 0; n < XtNumber(table); ++n) { 810b7c89284Ssnj if (table[n].value == which) { 811cd3331d0Smrg result = XInternAtom(XtDisplay(xw), table[n].name, False); 812b7c89284Ssnj break; 813b7c89284Ssnj } 814b7c89284Ssnj } 815b7c89284Ssnj return result; 816b7c89284Ssnj} 817b7c89284Ssnj#endif 818b7c89284Ssnj 819d522f475Smrgvoid 820b7c89284SsnjxtermBell(XtermWidget xw, int which, int percent) 821d522f475Smrg{ 822b7c89284Ssnj TScreen *screen = TScreenOf(xw); 823b7c89284Ssnj#if defined(HAVE_XKB_BELL_EXT) 824b7c89284Ssnj Atom tony = AtomBell(xw, which); 825cd3331d0Smrg#endif 826cd3331d0Smrg 827cd3331d0Smrg switch (which) { 828cd3331d0Smrg case XkbBI_Info: 829cd3331d0Smrg case XkbBI_MinorError: 830cd3331d0Smrg case XkbBI_MajorError: 831cd3331d0Smrg case XkbBI_TerminalBell: 832cd3331d0Smrg switch (screen->warningVolume) { 833cd3331d0Smrg case bvOff: 834cd3331d0Smrg percent = -100; 835cd3331d0Smrg break; 836cd3331d0Smrg case bvLow: 837cd3331d0Smrg break; 838cd3331d0Smrg case bvHigh: 839cd3331d0Smrg percent = 100; 840cd3331d0Smrg break; 841cd3331d0Smrg } 842cd3331d0Smrg break; 843cd3331d0Smrg case XkbBI_MarginBell: 844cd3331d0Smrg switch (screen->marginVolume) { 845cd3331d0Smrg case bvOff: 846cd3331d0Smrg percent = -100; 847cd3331d0Smrg break; 848cd3331d0Smrg case bvLow: 849cd3331d0Smrg break; 850cd3331d0Smrg case bvHigh: 851cd3331d0Smrg percent = 100; 852cd3331d0Smrg break; 853cd3331d0Smrg } 854cd3331d0Smrg break; 855cd3331d0Smrg default: 856cd3331d0Smrg break; 857cd3331d0Smrg } 858cd3331d0Smrg 859cd3331d0Smrg#if defined(HAVE_XKB_BELL_EXT) 860b7c89284Ssnj if (tony != None) { 861c219fbebSmrg XkbBell(screen->display, VShellWindow(xw), percent, tony); 862b7c89284Ssnj } else 863b7c89284Ssnj#endif 864b7c89284Ssnj XBell(screen->display, percent); 865b7c89284Ssnj} 866b7c89284Ssnj 867b7c89284Ssnjvoid 868cd3331d0SmrgBell(XtermWidget xw, int which, int percent) 869b7c89284Ssnj{ 870b7c89284Ssnj TScreen *screen = TScreenOf(xw); 871d522f475Smrg struct timeval curtime; 872d522f475Smrg long now_msecs; 873d522f475Smrg 874b7c89284Ssnj TRACE(("BELL %d %d%%\n", which, percent)); 875b7c89284Ssnj if (!XtIsRealized((Widget) xw)) { 876d522f475Smrg return; 877d522f475Smrg } 878d522f475Smrg 879c219fbebSmrg setXUrgency(xw, True); 880d522f475Smrg 881d522f475Smrg /* has enough time gone by that we are allowed to ring 882d522f475Smrg the bell again? */ 883d522f475Smrg if (screen->bellSuppressTime) { 884d522f475Smrg if (screen->bellInProgress) { 885d522f475Smrg do_xevents(); 886d522f475Smrg if (screen->bellInProgress) { /* even after new events? */ 887d522f475Smrg return; 888d522f475Smrg } 889d522f475Smrg } 890d522f475Smrg X_GETTIMEOFDAY(&curtime); 891d522f475Smrg now_msecs = 1000 * curtime.tv_sec + curtime.tv_usec / 1000; 892d522f475Smrg if (lastBellTime != 0 && now_msecs - lastBellTime >= 0 && 893d522f475Smrg now_msecs - lastBellTime < screen->bellSuppressTime) { 894d522f475Smrg return; 895d522f475Smrg } 896d522f475Smrg lastBellTime = now_msecs; 897d522f475Smrg } 898d522f475Smrg 899d522f475Smrg if (screen->visualbell) { 900d522f475Smrg VisualBell(); 901d522f475Smrg } else { 902b7c89284Ssnj xtermBell(xw, which, percent); 903d522f475Smrg } 904d522f475Smrg 905d522f475Smrg if (screen->poponbell) 906c219fbebSmrg XRaiseWindow(screen->display, VShellWindow(xw)); 907d522f475Smrg 908d522f475Smrg if (screen->bellSuppressTime) { 909d522f475Smrg /* now we change a property and wait for the notify event to come 910d522f475Smrg back. If the server is suspending operations while the bell 911d522f475Smrg is being emitted (problematic for audio bell), this lets us 912d522f475Smrg know when the previous bell has finished */ 913d522f475Smrg Widget w = CURRENT_EMU(); 914d522f475Smrg XChangeProperty(XtDisplay(w), XtWindow(w), 915d522f475Smrg XA_NOTICE, XA_NOTICE, 8, PropModeAppend, NULL, 0); 916d522f475Smrg screen->bellInProgress = True; 917d522f475Smrg } 918d522f475Smrg} 919d522f475Smrg 920d522f475Smrg#define VB_DELAY screen->visualBellDelay 921d522f475Smrg 922d522f475Smrgstatic void 923d522f475SmrgflashWindow(TScreen * screen, Window window, GC visualGC, unsigned width, unsigned height) 924d522f475Smrg{ 925d522f475Smrg XFillRectangle(screen->display, window, visualGC, 0, 0, width, height); 926d522f475Smrg XFlush(screen->display); 927d522f475Smrg Sleep(VB_DELAY); 928d522f475Smrg XFillRectangle(screen->display, window, visualGC, 0, 0, width, height); 929d522f475Smrg} 930d522f475Smrg 931d522f475Smrgvoid 932d522f475SmrgVisualBell(void) 933d522f475Smrg{ 934d522f475Smrg TScreen *screen = TScreenOf(term); 935d522f475Smrg 936d522f475Smrg if (VB_DELAY > 0) { 937d522f475Smrg Pixel xorPixel = (T_COLOR(screen, TEXT_FG) ^ 938d522f475Smrg T_COLOR(screen, TEXT_BG)); 939d522f475Smrg XGCValues gcval; 940d522f475Smrg GC visualGC; 941d522f475Smrg 942d522f475Smrg gcval.function = GXxor; 943d522f475Smrg gcval.foreground = xorPixel; 944d522f475Smrg visualGC = XtGetGC((Widget) term, GCFunction + GCForeground, &gcval); 945d522f475Smrg#if OPT_TEK4014 946d522f475Smrg if (TEK4014_ACTIVE(term)) { 947cd3331d0Smrg TekScreen *tekscr = TekScreenOf(tekWidget); 948d522f475Smrg flashWindow(screen, TWindow(tekscr), visualGC, 949d522f475Smrg TFullWidth(tekscr), 950d522f475Smrg TFullHeight(tekscr)); 951d522f475Smrg } else 952d522f475Smrg#endif 953d522f475Smrg { 954d522f475Smrg flashWindow(screen, VWindow(screen), visualGC, 955d522f475Smrg FullWidth(screen), 956d522f475Smrg FullHeight(screen)); 957d522f475Smrg } 958d522f475Smrg XtReleaseGC((Widget) term, visualGC); 959d522f475Smrg } 960d522f475Smrg} 961d522f475Smrg 962d522f475Smrg/* ARGSUSED */ 963d522f475Smrgvoid 964d522f475SmrgHandleBellPropertyChange(Widget w GCC_UNUSED, 965d522f475Smrg XtPointer data GCC_UNUSED, 966d522f475Smrg XEvent * ev, 967d522f475Smrg Boolean * more GCC_UNUSED) 968d522f475Smrg{ 969d522f475Smrg TScreen *screen = TScreenOf(term); 970d522f475Smrg 971d522f475Smrg if (ev->xproperty.atom == XA_NOTICE) { 972d522f475Smrg screen->bellInProgress = False; 973d522f475Smrg } 974d522f475Smrg} 975d522f475Smrg 976d522f475SmrgWindow 977c219fbebSmrgWMFrameWindow(XtermWidget xw) 978d522f475Smrg{ 979d522f475Smrg Window win_root, win_current, *children; 980d522f475Smrg Window win_parent = 0; 981d522f475Smrg unsigned int nchildren; 982d522f475Smrg 983c219fbebSmrg win_current = XtWindow(xw); 984d522f475Smrg 985d522f475Smrg /* find the parent which is child of root */ 986d522f475Smrg do { 987d522f475Smrg if (win_parent) 988d522f475Smrg win_current = win_parent; 989c219fbebSmrg XQueryTree(TScreenOf(xw)->display, 990d522f475Smrg win_current, 991d522f475Smrg &win_root, 992d522f475Smrg &win_parent, 993d522f475Smrg &children, 994d522f475Smrg &nchildren); 995d522f475Smrg XFree(children); 996d522f475Smrg } while (win_root != win_parent); 997d522f475Smrg 998d522f475Smrg return win_current; 999d522f475Smrg} 1000d522f475Smrg 1001d522f475Smrg#if OPT_DABBREV 1002d522f475Smrg/* 1003d522f475Smrg * The following code implements `dynamic abbreviation' expansion a la 1004d522f475Smrg * Emacs. It looks in the preceding visible screen and its scrollback 1005d522f475Smrg * to find expansions of a typed word. It compares consecutive 1006d522f475Smrg * expansions and ignores one of them if they are identical. 1007d522f475Smrg * (Tomasz J. Cholewo, t.cholewo@ieee.org) 1008d522f475Smrg */ 1009d522f475Smrg 1010d522f475Smrg#define IS_WORD_CONSTITUENT(x) ((x) != ' ' && (x) != '\0') 1011d522f475Smrg#define MAXWLEN 1024 /* maximum word length as in tcsh */ 1012d522f475Smrg 1013d522f475Smrgstatic int 1014b7c89284Ssnjdabbrev_prev_char(TScreen * screen, CELL * cell, LineData ** ld) 1015d522f475Smrg{ 1016b7c89284Ssnj int result = -1; 1017b7c89284Ssnj int firstLine = -(screen->savedlines); 1018d522f475Smrg 1019b7c89284Ssnj *ld = getLineData(screen, cell->row); 1020b7c89284Ssnj while (cell->row >= firstLine) { 1021b7c89284Ssnj if (--(cell->col) >= 0) { 1022b7c89284Ssnj result = (int) (*ld)->charData[cell->col]; 1023b7c89284Ssnj break; 1024b7c89284Ssnj } 1025b7c89284Ssnj if (--(cell->row) < firstLine) 1026b7c89284Ssnj break; /* ...there is no previous line */ 1027b7c89284Ssnj *ld = getLineData(screen, cell->row); 1028b7c89284Ssnj cell->col = MaxCols(screen); 1029b7c89284Ssnj if (!LineTstWrapped(*ld)) { 1030b7c89284Ssnj result = ' '; /* treat lines as separate */ 1031d522f475Smrg break; 1032b7c89284Ssnj } 1033d522f475Smrg } 1034b7c89284Ssnj return result; 1035d522f475Smrg} 1036d522f475Smrg 1037d522f475Smrgstatic char * 1038b7c89284Ssnjdabbrev_prev_word(TScreen * screen, CELL * cell, LineData ** ld) 1039d522f475Smrg{ 1040d522f475Smrg static char ab[MAXWLEN]; 1041b7c89284Ssnj 1042d522f475Smrg char *abword; 1043d522f475Smrg int c; 1044b7c89284Ssnj char *ab_end = (ab + MAXWLEN - 1); 1045b7c89284Ssnj char *result = 0; 1046d522f475Smrg 1047b7c89284Ssnj abword = ab_end; 1048d522f475Smrg *abword = '\0'; /* end of string marker */ 1049d522f475Smrg 1050b7c89284Ssnj while ((c = dabbrev_prev_char(screen, cell, ld)) >= 0 && 1051b7c89284Ssnj IS_WORD_CONSTITUENT(c)) { 1052d522f475Smrg if (abword > ab) /* store only |MAXWLEN| last chars */ 1053b7c89284Ssnj *(--abword) = (char) c; 1054d522f475Smrg } 1055d522f475Smrg 1056b7c89284Ssnj if (c >= 0) { 1057b7c89284Ssnj result = abword; 1058b7c89284Ssnj } else if (abword != ab_end) { 1059b7c89284Ssnj result = abword; 1060b7c89284Ssnj } 1061b7c89284Ssnj 1062b7c89284Ssnj if (result != 0) { 1063b7c89284Ssnj while ((c = dabbrev_prev_char(screen, cell, ld)) >= 0 && 1064b7c89284Ssnj !IS_WORD_CONSTITUENT(c)) { 1065b7c89284Ssnj ; /* skip preceding spaces */ 1066b7c89284Ssnj } 1067b7c89284Ssnj (cell->col)++; /* can be | > screen->max_col| */ 1068b7c89284Ssnj } 1069b7c89284Ssnj return result; 1070d522f475Smrg} 1071d522f475Smrg 1072d522f475Smrgstatic int 1073d522f475Smrgdabbrev_expand(TScreen * screen) 1074d522f475Smrg{ 1075d522f475Smrg int pty = screen->respond; /* file descriptor of pty */ 1076d522f475Smrg 1077b7c89284Ssnj static CELL cell; 1078d522f475Smrg static char *dabbrev_hint = 0, *lastexpansion = 0; 1079d522f475Smrg static unsigned int expansions; 1080d522f475Smrg 1081d522f475Smrg char *expansion; 1082d522f475Smrg Char *copybuffer; 1083d522f475Smrg size_t hint_len; 1084cd3331d0Smrg size_t del_cnt; 1085cd3331d0Smrg size_t buf_cnt; 1086b7c89284Ssnj int result = 0; 1087b7c89284Ssnj LineData *ld; 1088d522f475Smrg 1089d522f475Smrg if (!screen->dabbrev_working) { /* initialize */ 1090d522f475Smrg expansions = 0; 1091b7c89284Ssnj cell.col = screen->cur_col; 1092b7c89284Ssnj cell.row = screen->cur_row; 1093b7c89284Ssnj 1094b7c89284Ssnj if (dabbrev_hint != 0) 1095b7c89284Ssnj free(dabbrev_hint); 1096b7c89284Ssnj 1097b7c89284Ssnj if ((dabbrev_hint = dabbrev_prev_word(screen, &cell, &ld)) != 0) { 1098b7c89284Ssnj 1099b7c89284Ssnj if (lastexpansion != 0) 1100b7c89284Ssnj free(lastexpansion); 1101b7c89284Ssnj 1102b7c89284Ssnj if ((lastexpansion = strdup(dabbrev_hint)) != 0) { 1103b7c89284Ssnj 1104b7c89284Ssnj /* make own copy */ 1105b7c89284Ssnj if ((dabbrev_hint = strdup(dabbrev_hint)) != 0) { 1106b7c89284Ssnj screen->dabbrev_working = True; 1107b7c89284Ssnj /* we are in the middle of dabbrev process */ 1108b7c89284Ssnj } 1109cd3331d0Smrg } else { 1110cd3331d0Smrg return result; 1111b7c89284Ssnj } 1112cd3331d0Smrg } else { 1113cd3331d0Smrg return result; 1114d522f475Smrg } 1115b7c89284Ssnj if (!screen->dabbrev_working) { 1116b7c89284Ssnj if (lastexpansion != 0) { 1117b7c89284Ssnj free(lastexpansion); 1118b7c89284Ssnj lastexpansion = 0; 1119b7c89284Ssnj } 1120b7c89284Ssnj return result; 1121b7c89284Ssnj } 1122d522f475Smrg } 1123d522f475Smrg 1124cd3331d0Smrg if (dabbrev_hint == 0) 1125cd3331d0Smrg return result; 1126cd3331d0Smrg 1127d522f475Smrg hint_len = strlen(dabbrev_hint); 1128d522f475Smrg for (;;) { 1129b7c89284Ssnj if ((expansion = dabbrev_prev_word(screen, &cell, &ld)) == 0) { 1130d522f475Smrg if (expansions >= 2) { 1131d522f475Smrg expansions = 0; 1132b7c89284Ssnj cell.col = screen->cur_col; 1133b7c89284Ssnj cell.row = screen->cur_row; 1134d522f475Smrg continue; 1135d522f475Smrg } 1136d522f475Smrg break; 1137d522f475Smrg } 1138d522f475Smrg if (!strncmp(dabbrev_hint, expansion, hint_len) && /* empty hint matches everything */ 1139d522f475Smrg strlen(expansion) > hint_len && /* trivial expansion disallowed */ 1140d522f475Smrg strcmp(expansion, lastexpansion)) /* different from previous */ 1141d522f475Smrg break; 1142d522f475Smrg } 1143d522f475Smrg 1144b7c89284Ssnj if (expansion != 0) { 1145b7c89284Ssnj del_cnt = strlen(lastexpansion) - hint_len; 1146b7c89284Ssnj buf_cnt = del_cnt + strlen(expansion) - hint_len; 1147b7c89284Ssnj 1148b7c89284Ssnj if ((copybuffer = TypeMallocN(Char, buf_cnt)) != 0) { 1149b7c89284Ssnj /* delete previous expansion */ 1150b7c89284Ssnj memset(copybuffer, screen->dabbrev_erase_char, del_cnt); 1151b7c89284Ssnj memmove(copybuffer + del_cnt, 1152b7c89284Ssnj expansion + hint_len, 1153b7c89284Ssnj strlen(expansion) - hint_len); 1154cd3331d0Smrg v_write(pty, copybuffer, (unsigned) buf_cnt); 1155b7c89284Ssnj /* v_write() just reset our flag */ 1156b7c89284Ssnj screen->dabbrev_working = True; 1157b7c89284Ssnj free(copybuffer); 1158b7c89284Ssnj 1159b7c89284Ssnj free(lastexpansion); 1160b7c89284Ssnj 1161b7c89284Ssnj if ((lastexpansion = strdup(expansion)) != 0) { 1162b7c89284Ssnj result = 1; 1163b7c89284Ssnj expansions++; 1164b7c89284Ssnj } 1165b7c89284Ssnj } 1166b7c89284Ssnj } 1167b7c89284Ssnj 1168b7c89284Ssnj return result; 1169d522f475Smrg} 1170d522f475Smrg 1171d522f475Smrg/*ARGSUSED*/ 1172d522f475Smrgvoid 1173b7c89284SsnjHandleDabbrevExpand(Widget w, 1174d522f475Smrg XEvent * event GCC_UNUSED, 1175d522f475Smrg String * params GCC_UNUSED, 1176d522f475Smrg Cardinal *nparams GCC_UNUSED) 1177d522f475Smrg{ 1178b7c89284Ssnj XtermWidget xw; 1179b7c89284Ssnj 1180cd3331d0Smrg TRACE(("Handle dabbrev-expand for %p\n", (void *) w)); 1181b7c89284Ssnj if ((xw = getXtermWidget(w)) != 0) { 1182cd3331d0Smrg TScreen *screen = TScreenOf(xw); 1183d522f475Smrg if (!dabbrev_expand(screen)) 1184cd3331d0Smrg Bell(xw, XkbBI_TerminalBell, 0); 1185d522f475Smrg } 1186d522f475Smrg} 1187d522f475Smrg#endif /* OPT_DABBREV */ 1188d522f475Smrg 1189d522f475Smrg#if OPT_MAXIMIZE 1190d522f475Smrg/*ARGSUSED*/ 1191d522f475Smrgvoid 1192b7c89284SsnjHandleDeIconify(Widget w, 1193d522f475Smrg XEvent * event GCC_UNUSED, 1194d522f475Smrg String * params GCC_UNUSED, 1195d522f475Smrg Cardinal *nparams GCC_UNUSED) 1196d522f475Smrg{ 1197b7c89284Ssnj XtermWidget xw; 1198b7c89284Ssnj 1199b7c89284Ssnj if ((xw = getXtermWidget(w)) != 0) { 1200b7c89284Ssnj TScreen *screen = TScreenOf(xw); 1201c219fbebSmrg XMapWindow(screen->display, VShellWindow(xw)); 1202d522f475Smrg } 1203d522f475Smrg} 1204d522f475Smrg 1205d522f475Smrg/*ARGSUSED*/ 1206d522f475Smrgvoid 1207b7c89284SsnjHandleIconify(Widget w, 1208d522f475Smrg XEvent * event GCC_UNUSED, 1209d522f475Smrg String * params GCC_UNUSED, 1210d522f475Smrg Cardinal *nparams GCC_UNUSED) 1211d522f475Smrg{ 1212b7c89284Ssnj XtermWidget xw; 1213b7c89284Ssnj 1214b7c89284Ssnj if ((xw = getXtermWidget(w)) != 0) { 1215b7c89284Ssnj TScreen *screen = TScreenOf(xw); 1216d522f475Smrg XIconifyWindow(screen->display, 1217c219fbebSmrg VShellWindow(xw), 1218d522f475Smrg DefaultScreen(screen->display)); 1219d522f475Smrg } 1220d522f475Smrg} 1221d522f475Smrg 1222d522f475Smrgint 1223c219fbebSmrgQueryMaximize(XtermWidget xw, unsigned *width, unsigned *height) 1224d522f475Smrg{ 1225c219fbebSmrg TScreen *screen = TScreenOf(xw); 1226d522f475Smrg XSizeHints hints; 1227d522f475Smrg long supp = 0; 1228d522f475Smrg Window root_win; 1229d522f475Smrg int root_x = -1; /* saved co-ordinates */ 1230d522f475Smrg int root_y = -1; 1231d522f475Smrg unsigned root_border; 1232d522f475Smrg unsigned root_depth; 1233d522f475Smrg 1234d522f475Smrg if (XGetGeometry(screen->display, 1235c219fbebSmrg RootWindowOfScreen(XtScreen(xw)), 1236d522f475Smrg &root_win, 1237d522f475Smrg &root_x, 1238d522f475Smrg &root_y, 1239d522f475Smrg width, 1240d522f475Smrg height, 1241d522f475Smrg &root_border, 1242d522f475Smrg &root_depth)) { 1243d522f475Smrg TRACE(("QueryMaximize: XGetGeometry position %d,%d size %d,%d border %d\n", 1244d522f475Smrg root_x, 1245d522f475Smrg root_y, 1246d522f475Smrg *width, 1247d522f475Smrg *height, 1248d522f475Smrg root_border)); 1249d522f475Smrg 1250d522f475Smrg *width -= (root_border * 2); 1251d522f475Smrg *height -= (root_border * 2); 1252d522f475Smrg 1253d522f475Smrg hints.flags = PMaxSize; 1254d522f475Smrg if (XGetWMNormalHints(screen->display, 1255c219fbebSmrg VShellWindow(xw), 1256d522f475Smrg &hints, 1257d522f475Smrg &supp) 1258d522f475Smrg && (hints.flags & PMaxSize) != 0) { 1259d522f475Smrg 1260d522f475Smrg TRACE(("QueryMaximize: WM hints max_w %#x max_h %#x\n", 1261d522f475Smrg hints.max_width, 1262d522f475Smrg hints.max_height)); 1263d522f475Smrg 1264d522f475Smrg if ((unsigned) hints.max_width < *width) 1265b7c89284Ssnj *width = (unsigned) hints.max_width; 1266d522f475Smrg if ((unsigned) hints.max_height < *height) 1267b7c89284Ssnj *height = (unsigned) hints.max_height; 1268d522f475Smrg } 1269d522f475Smrg return 1; 1270d522f475Smrg } 1271d522f475Smrg return 0; 1272d522f475Smrg} 1273d522f475Smrg 1274d522f475Smrgvoid 1275c219fbebSmrgRequestMaximize(XtermWidget xw, int maximize) 1276d522f475Smrg{ 1277c219fbebSmrg TScreen *screen = TScreenOf(xw); 1278d522f475Smrg XWindowAttributes wm_attrs, vshell_attrs; 1279d522f475Smrg unsigned root_width, root_height; 1280d522f475Smrg 1281cd3331d0Smrg TRACE(("RequestMaximize %s\n", maximize ? "maximize" : "restore")); 1282cd3331d0Smrg 1283d522f475Smrg if (maximize) { 1284d522f475Smrg 1285c219fbebSmrg if (QueryMaximize(xw, &root_width, &root_height)) { 1286d522f475Smrg 1287d522f475Smrg if (XGetWindowAttributes(screen->display, 1288c219fbebSmrg WMFrameWindow(xw), 1289d522f475Smrg &wm_attrs)) { 1290d522f475Smrg 1291d522f475Smrg if (XGetWindowAttributes(screen->display, 1292c219fbebSmrg VShellWindow(xw), 1293d522f475Smrg &vshell_attrs)) { 1294d522f475Smrg 1295d522f475Smrg if (screen->restore_data != True 1296d522f475Smrg || screen->restore_width != root_width 1297d522f475Smrg || screen->restore_height != root_height) { 1298d522f475Smrg screen->restore_data = True; 1299d522f475Smrg screen->restore_x = wm_attrs.x + wm_attrs.border_width; 1300d522f475Smrg screen->restore_y = wm_attrs.y + wm_attrs.border_width; 1301b7c89284Ssnj screen->restore_width = (unsigned) vshell_attrs.width; 1302b7c89284Ssnj screen->restore_height = (unsigned) vshell_attrs.height; 1303d522f475Smrg TRACE(("HandleMaximize: save window position %d,%d size %d,%d\n", 1304d522f475Smrg screen->restore_x, 1305d522f475Smrg screen->restore_y, 1306d522f475Smrg screen->restore_width, 1307d522f475Smrg screen->restore_height)); 1308d522f475Smrg } 1309d522f475Smrg 1310d522f475Smrg /* subtract wm decoration dimensions */ 1311b7c89284Ssnj root_width -= 1312b7c89284Ssnj (unsigned) ((wm_attrs.width - vshell_attrs.width) 1313b7c89284Ssnj + (wm_attrs.border_width * 2)); 1314b7c89284Ssnj root_height -= 1315b7c89284Ssnj (unsigned) ((wm_attrs.height - vshell_attrs.height) 1316d522f475Smrg + (wm_attrs.border_width * 2)); 1317d522f475Smrg 1318c219fbebSmrg XMoveResizeWindow(screen->display, VShellWindow(xw), 1319d522f475Smrg 0 + wm_attrs.border_width, /* x */ 1320d522f475Smrg 0 + wm_attrs.border_width, /* y */ 1321d522f475Smrg root_width, 1322d522f475Smrg root_height); 1323d522f475Smrg } 1324d522f475Smrg } 1325d522f475Smrg } 1326d522f475Smrg } else { 1327d522f475Smrg if (screen->restore_data) { 1328d522f475Smrg TRACE(("HandleRestoreSize: position %d,%d size %d,%d\n", 1329d522f475Smrg screen->restore_x, 1330d522f475Smrg screen->restore_y, 1331d522f475Smrg screen->restore_width, 1332d522f475Smrg screen->restore_height)); 1333d522f475Smrg screen->restore_data = False; 1334d522f475Smrg 1335d522f475Smrg XMoveResizeWindow(screen->display, 1336c219fbebSmrg VShellWindow(xw), 1337d522f475Smrg screen->restore_x, 1338d522f475Smrg screen->restore_y, 1339d522f475Smrg screen->restore_width, 1340d522f475Smrg screen->restore_height); 1341d522f475Smrg } 1342d522f475Smrg } 1343d522f475Smrg} 1344d522f475Smrg 1345d522f475Smrg/*ARGSUSED*/ 1346d522f475Smrgvoid 1347b7c89284SsnjHandleMaximize(Widget w, 1348d522f475Smrg XEvent * event GCC_UNUSED, 1349d522f475Smrg String * params GCC_UNUSED, 1350d522f475Smrg Cardinal *nparams GCC_UNUSED) 1351d522f475Smrg{ 1352b7c89284Ssnj XtermWidget xw; 1353b7c89284Ssnj 1354b7c89284Ssnj if ((xw = getXtermWidget(w)) != 0) { 1355b7c89284Ssnj RequestMaximize(xw, 1); 1356d522f475Smrg } 1357d522f475Smrg} 1358d522f475Smrg 1359d522f475Smrg/*ARGSUSED*/ 1360d522f475Smrgvoid 1361b7c89284SsnjHandleRestoreSize(Widget w, 1362d522f475Smrg XEvent * event GCC_UNUSED, 1363d522f475Smrg String * params GCC_UNUSED, 1364d522f475Smrg Cardinal *nparams GCC_UNUSED) 1365d522f475Smrg{ 1366b7c89284Ssnj XtermWidget xw; 1367b7c89284Ssnj 1368b7c89284Ssnj if ((xw = getXtermWidget(w)) != 0) { 1369b7c89284Ssnj RequestMaximize(xw, 0); 1370d522f475Smrg } 1371d522f475Smrg} 1372d522f475Smrg#endif /* OPT_MAXIMIZE */ 1373d522f475Smrg 1374d522f475Smrgvoid 1375d522f475SmrgRedraw(void) 1376d522f475Smrg{ 1377d522f475Smrg TScreen *screen = TScreenOf(term); 1378d522f475Smrg XExposeEvent event; 1379d522f475Smrg 1380d522f475Smrg TRACE(("Redraw\n")); 1381d522f475Smrg 1382d522f475Smrg event.type = Expose; 1383d522f475Smrg event.display = screen->display; 1384d522f475Smrg event.x = 0; 1385d522f475Smrg event.y = 0; 1386d522f475Smrg event.count = 0; 1387d522f475Smrg 1388d522f475Smrg if (VWindow(screen)) { 1389d522f475Smrg event.window = VWindow(screen); 1390d522f475Smrg event.width = term->core.width; 1391d522f475Smrg event.height = term->core.height; 1392d522f475Smrg (*term->core.widget_class->core_class.expose) ((Widget) term, 1393d522f475Smrg (XEvent *) & event, 1394d522f475Smrg NULL); 1395d522f475Smrg if (ScrollbarWidth(screen)) { 1396d522f475Smrg (screen->scrollWidget->core.widget_class->core_class.expose) 1397d522f475Smrg (screen->scrollWidget, (XEvent *) & event, NULL); 1398d522f475Smrg } 1399d522f475Smrg } 1400d522f475Smrg#if OPT_TEK4014 1401d522f475Smrg if (TEK4014_SHOWN(term)) { 1402cd3331d0Smrg TekScreen *tekscr = TekScreenOf(tekWidget); 1403d522f475Smrg event.window = TWindow(tekscr); 1404d522f475Smrg event.width = tekWidget->core.width; 1405d522f475Smrg event.height = tekWidget->core.height; 1406d522f475Smrg TekExpose((Widget) tekWidget, (XEvent *) & event, NULL); 1407d522f475Smrg } 1408d522f475Smrg#endif 1409d522f475Smrg} 1410d522f475Smrg 1411d522f475Smrg#ifdef VMS 1412d522f475Smrg#define TIMESTAMP_FMT "%s%d-%02d-%02d-%02d-%02d-%02d" 1413d522f475Smrg#else 1414d522f475Smrg#define TIMESTAMP_FMT "%s%d-%02d-%02d.%02d:%02d:%02d" 1415d522f475Smrg#endif 1416d522f475Smrg 1417d522f475Smrgvoid 1418d522f475Smrgtimestamp_filename(char *dst, const char *src) 1419d522f475Smrg{ 1420d522f475Smrg time_t tstamp; 1421d522f475Smrg struct tm *tstruct; 1422d522f475Smrg 1423d522f475Smrg tstamp = time((time_t *) 0); 1424d522f475Smrg tstruct = localtime(&tstamp); 1425d522f475Smrg sprintf(dst, TIMESTAMP_FMT, 1426d522f475Smrg src, 1427d522f475Smrg tstruct->tm_year + 1900, 1428d522f475Smrg tstruct->tm_mon + 1, 1429d522f475Smrg tstruct->tm_mday, 1430d522f475Smrg tstruct->tm_hour, 1431d522f475Smrg tstruct->tm_min, 1432d522f475Smrg tstruct->tm_sec); 1433d522f475Smrg} 1434d522f475Smrg 1435d522f475Smrgint 1436d522f475Smrgopen_userfile(uid_t uid, gid_t gid, char *path, Bool append) 1437d522f475Smrg{ 1438d522f475Smrg int fd; 1439d522f475Smrg struct stat sb; 1440d522f475Smrg 1441d522f475Smrg#ifdef VMS 1442d522f475Smrg if ((fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644)) < 0) { 1443d522f475Smrg int the_error = errno; 1444d522f475Smrg fprintf(stderr, "%s: cannot open %s: %d:%s\n", 1445c219fbebSmrg ProgramName, 1446d522f475Smrg path, 1447d522f475Smrg the_error, 1448d522f475Smrg SysErrorMsg(the_error)); 1449d522f475Smrg return -1; 1450d522f475Smrg } 1451d522f475Smrg chown(path, uid, gid); 1452d522f475Smrg#else 1453d522f475Smrg if ((access(path, F_OK) != 0 && (errno != ENOENT)) 1454d522f475Smrg || (creat_as(uid, gid, append, path, 0644) <= 0) 1455d522f475Smrg || ((fd = open(path, O_WRONLY | O_APPEND)) < 0)) { 1456d522f475Smrg int the_error = errno; 1457d522f475Smrg fprintf(stderr, "%s: cannot open %s: %d:%s\n", 1458c219fbebSmrg ProgramName, 1459d522f475Smrg path, 1460d522f475Smrg the_error, 1461d522f475Smrg SysErrorMsg(the_error)); 1462d522f475Smrg return -1; 1463d522f475Smrg } 1464d522f475Smrg#endif 1465d522f475Smrg 1466d522f475Smrg /* 1467d522f475Smrg * Doublecheck that the user really owns the file that we've opened before 1468d522f475Smrg * we do any damage, and that it is not world-writable. 1469d522f475Smrg */ 1470d522f475Smrg if (fstat(fd, &sb) < 0 1471d522f475Smrg || sb.st_uid != uid 1472d522f475Smrg || (sb.st_mode & 022) != 0) { 1473c219fbebSmrg fprintf(stderr, "%s: you do not own %s\n", ProgramName, path); 1474d522f475Smrg close(fd); 1475d522f475Smrg return -1; 1476d522f475Smrg } 1477d522f475Smrg return fd; 1478d522f475Smrg} 1479d522f475Smrg 1480d522f475Smrg#ifndef VMS 1481d522f475Smrg/* 1482d522f475Smrg * Create a file only if we could with the permissions of the real user id. 1483d522f475Smrg * We could emulate this with careful use of access() and following 1484d522f475Smrg * symbolic links, but that is messy and has race conditions. 1485d522f475Smrg * Forking is messy, too, but we can't count on setreuid() or saved set-uids 1486d522f475Smrg * being available. 1487d522f475Smrg * 1488d522f475Smrg * Note: When called for user logging, we have ensured that the real and 1489d522f475Smrg * effective user ids are the same, so this remains as a convenience function 1490d522f475Smrg * for the debug logs. 1491d522f475Smrg * 1492d522f475Smrg * Returns 1493d522f475Smrg * 1 if we can proceed to open the file in relative safety, 1494d522f475Smrg * -1 on error, e.g., cannot fork 1495d522f475Smrg * 0 otherwise. 1496d522f475Smrg */ 1497d522f475Smrgint 1498d522f475Smrgcreat_as(uid_t uid, gid_t gid, Bool append, char *pathname, int mode) 1499d522f475Smrg{ 1500d522f475Smrg int fd; 1501d522f475Smrg pid_t pid; 1502d522f475Smrg int retval = 0; 1503d522f475Smrg int childstat = 0; 1504d522f475Smrg#ifndef HAVE_WAITPID 1505d522f475Smrg int waited; 1506d522f475Smrg SIGNAL_T(*chldfunc) (int); 1507d522f475Smrg 1508d522f475Smrg chldfunc = signal(SIGCHLD, SIG_DFL); 1509d522f475Smrg#endif /* HAVE_WAITPID */ 1510d522f475Smrg 1511d522f475Smrg TRACE(("creat_as(uid=%d/%d, gid=%d/%d, append=%d, pathname=%s, mode=%#o)\n", 1512d522f475Smrg (int) uid, (int) geteuid(), 1513d522f475Smrg (int) gid, (int) getegid(), 1514d522f475Smrg append, 1515d522f475Smrg pathname, 1516d522f475Smrg mode)); 1517d522f475Smrg 1518d522f475Smrg if (uid == geteuid() && gid == getegid()) { 1519d522f475Smrg fd = open(pathname, 1520d522f475Smrg O_WRONLY | O_CREAT | (append ? O_APPEND : O_EXCL), 1521d522f475Smrg mode); 1522d522f475Smrg if (fd >= 0) 1523d522f475Smrg close(fd); 1524d522f475Smrg return (fd >= 0); 1525d522f475Smrg } 1526d522f475Smrg 1527d522f475Smrg pid = fork(); 1528d522f475Smrg switch (pid) { 1529d522f475Smrg case 0: /* child */ 1530d522f475Smrg if (setgid(gid) == -1 1531d522f475Smrg || setuid(uid) == -1) { 1532d522f475Smrg /* we cannot report an error here via stderr, just quit */ 1533d522f475Smrg retval = 1; 1534d522f475Smrg } else { 1535d522f475Smrg fd = open(pathname, 1536d522f475Smrg O_WRONLY | O_CREAT | (append ? O_APPEND : O_EXCL), 1537d522f475Smrg mode); 1538d522f475Smrg if (fd >= 0) { 1539d522f475Smrg close(fd); 1540d522f475Smrg retval = 0; 1541d522f475Smrg } else { 1542d522f475Smrg retval = 1; 1543d522f475Smrg } 1544d522f475Smrg } 1545d522f475Smrg _exit(retval); 1546d522f475Smrg /* NOTREACHED */ 1547d522f475Smrg case -1: /* error */ 1548d522f475Smrg return retval; 1549d522f475Smrg default: /* parent */ 1550d522f475Smrg#ifdef HAVE_WAITPID 1551d522f475Smrg while (waitpid(pid, &childstat, 0) < 0) { 1552d522f475Smrg#ifdef EINTR 1553d522f475Smrg if (errno == EINTR) 1554d522f475Smrg continue; 1555d522f475Smrg#endif /* EINTR */ 1556d522f475Smrg#ifdef ERESTARTSYS 1557d522f475Smrg if (errno == ERESTARTSYS) 1558d522f475Smrg continue; 1559d522f475Smrg#endif /* ERESTARTSYS */ 1560d522f475Smrg break; 1561d522f475Smrg } 1562d522f475Smrg#else /* HAVE_WAITPID */ 1563d522f475Smrg waited = wait(&childstat); 1564d522f475Smrg signal(SIGCHLD, chldfunc); 1565d522f475Smrg /* 1566d522f475Smrg Since we had the signal handler uninstalled for a while, 1567d522f475Smrg we might have missed the termination of our screen child. 1568d522f475Smrg If we can check for this possibility without hanging, do so. 1569d522f475Smrg */ 1570d522f475Smrg do 1571cd3331d0Smrg if (waited == TScreenOf(term)->pid) 1572d522f475Smrg Cleanup(0); 1573d522f475Smrg while ((waited = nonblocking_wait()) > 0) ; 1574d522f475Smrg#endif /* HAVE_WAITPID */ 1575d522f475Smrg#ifndef WIFEXITED 1576d522f475Smrg#define WIFEXITED(status) ((status & 0xff) != 0) 1577d522f475Smrg#endif 1578d522f475Smrg if (WIFEXITED(childstat)) 1579d522f475Smrg retval = 1; 1580d522f475Smrg return retval; 1581d522f475Smrg } 1582d522f475Smrg} 1583d522f475Smrg#endif /* !VMS */ 1584d522f475Smrg 1585d522f475Smrgint 1586d522f475SmrgxtermResetIds(TScreen * screen) 1587d522f475Smrg{ 1588d522f475Smrg int result = 0; 1589d522f475Smrg if (setgid(screen->gid) == -1) { 1590d522f475Smrg fprintf(stderr, "%s: unable to reset group-id\n", ProgramName); 1591d522f475Smrg result = -1; 1592d522f475Smrg } 1593d522f475Smrg if (setuid(screen->uid) == -1) { 1594d522f475Smrg fprintf(stderr, "%s: unable to reset user-id\n", ProgramName); 1595d522f475Smrg result = -1; 1596d522f475Smrg } 1597d522f475Smrg return result; 1598d522f475Smrg} 1599d522f475Smrg 1600d522f475Smrg#ifdef ALLOWLOGGING 1601d522f475Smrg 1602d522f475Smrg/* 1603d522f475Smrg * Logging is a security hole, since it allows a setuid program to write 1604d522f475Smrg * arbitrary data to an arbitrary file. So it is disabled by default. 1605d522f475Smrg */ 1606d522f475Smrg 1607d522f475Smrg#ifdef ALLOWLOGFILEEXEC 1608d522f475Smrgstatic SIGNAL_T 1609d522f475Smrglogpipe(int sig GCC_UNUSED) 1610d522f475Smrg{ 1611cd3331d0Smrg XtermWidget xw = term; 1612cd3331d0Smrg TScreen *screen = TScreenOf(xw); 1613d522f475Smrg 1614d522f475Smrg#ifdef SYSV 1615d522f475Smrg (void) signal(SIGPIPE, SIG_IGN); 1616d522f475Smrg#endif /* SYSV */ 1617d522f475Smrg if (screen->logging) 1618cd3331d0Smrg CloseLog(xw); 1619d522f475Smrg} 1620d522f475Smrg#endif /* ALLOWLOGFILEEXEC */ 1621d522f475Smrg 1622d522f475Smrgvoid 1623cd3331d0SmrgStartLog(XtermWidget xw) 1624d522f475Smrg{ 1625d522f475Smrg static char *log_default; 1626d522f475Smrg#ifdef ALLOWLOGFILEEXEC 1627d522f475Smrg char *cp; 1628d522f475Smrg#endif /* ALLOWLOGFILEEXEC */ 1629cd3331d0Smrg TScreen *screen = TScreenOf(xw); 1630d522f475Smrg 1631d522f475Smrg if (screen->logging || (screen->inhibit & I_LOG)) 1632d522f475Smrg return; 1633d522f475Smrg#ifdef VMS /* file name is fixed in VMS variant */ 1634d522f475Smrg screen->logfd = open(XTERM_VMS_LOGFILE, 1635d522f475Smrg O_CREAT | O_TRUNC | O_APPEND | O_RDWR, 1636d522f475Smrg 0640); 1637d522f475Smrg if (screen->logfd < 0) 1638d522f475Smrg return; /* open failed */ 1639d522f475Smrg#else /*VMS */ 1640d522f475Smrg if (screen->logfile == NULL || *screen->logfile == 0) { 1641d522f475Smrg if (screen->logfile) 1642d522f475Smrg free(screen->logfile); 1643d522f475Smrg if (log_default == NULL) { 1644d522f475Smrg#if defined(HAVE_GETHOSTNAME) && defined(HAVE_STRFTIME) 1645d522f475Smrg char log_def_name[512]; /* see sprintf below */ 1646d522f475Smrg char hostname[255 + 1]; /* Internet standard limit (RFC 1035): 1647d522f475Smrg ``To simplify implementations, the 1648d522f475Smrg total length of a domain name (i.e., 1649d522f475Smrg label octets and label length 1650d522f475Smrg octets) is restricted to 255 octets 1651d522f475Smrg or less.'' */ 1652d522f475Smrg char yyyy_mm_dd_hh_mm_ss[4 + 5 * (1 + 2) + 1]; 1653d522f475Smrg time_t now; 1654d522f475Smrg struct tm *ltm; 1655d522f475Smrg 1656d522f475Smrg now = time((time_t *) 0); 1657d522f475Smrg ltm = (struct tm *) localtime(&now); 1658d522f475Smrg if ((gethostname(hostname, sizeof(hostname)) == 0) && 1659d522f475Smrg (strftime(yyyy_mm_dd_hh_mm_ss, 1660d522f475Smrg sizeof(yyyy_mm_dd_hh_mm_ss), 1661d522f475Smrg "%Y.%m.%d.%H.%M.%S", ltm) > 0)) { 1662d522f475Smrg (void) sprintf(log_def_name, "Xterm.log.%.255s.%.20s.%d", 1663d522f475Smrg hostname, yyyy_mm_dd_hh_mm_ss, (int) getpid()); 1664d522f475Smrg } 1665d522f475Smrg if ((log_default = x_strdup(log_def_name)) == NULL) 1666d522f475Smrg return; 1667d522f475Smrg#else 1668d522f475Smrg const char *log_def_name = "XtermLog.XXXXXX"; 1669d522f475Smrg if ((log_default = x_strdup(log_def_name)) == NULL) 1670d522f475Smrg return; 1671d522f475Smrg 1672d522f475Smrg mktemp(log_default); 1673d522f475Smrg#endif 1674d522f475Smrg } 1675d522f475Smrg if ((screen->logfile = x_strdup(log_default)) == 0) 1676d522f475Smrg return; 1677d522f475Smrg } 1678d522f475Smrg if (*screen->logfile == '|') { /* exec command */ 1679d522f475Smrg#ifdef ALLOWLOGFILEEXEC 1680d522f475Smrg /* 1681d522f475Smrg * Warning, enabling this "feature" allows arbitrary programs 1682d522f475Smrg * to be run. If ALLOWLOGFILECHANGES is enabled, this can be 1683d522f475Smrg * done through escape sequences.... You have been warned. 1684d522f475Smrg */ 1685d522f475Smrg int pid; 1686d522f475Smrg int p[2]; 1687d522f475Smrg static char *shell; 1688d522f475Smrg struct passwd *pw; 1689d522f475Smrg 1690d522f475Smrg if (pipe(p) < 0 || (pid = fork()) < 0) 1691d522f475Smrg return; 1692d522f475Smrg if (pid == 0) { /* child */ 1693d522f475Smrg /* 1694d522f475Smrg * Close our output (we won't be talking back to the 1695d522f475Smrg * parent), and redirect our child's output to the 1696d522f475Smrg * original stderr. 1697d522f475Smrg */ 1698d522f475Smrg close(p[1]); 1699d522f475Smrg dup2(p[0], 0); 1700d522f475Smrg close(p[0]); 1701d522f475Smrg dup2(fileno(stderr), 1); 1702d522f475Smrg dup2(fileno(stderr), 2); 1703d522f475Smrg 1704d522f475Smrg close(fileno(stderr)); 1705d522f475Smrg close(ConnectionNumber(screen->display)); 1706d522f475Smrg close(screen->respond); 1707d522f475Smrg 1708d522f475Smrg if ((((cp = x_getenv("SHELL")) == NULL) 1709d522f475Smrg && ((pw = getpwuid(screen->uid)) == NULL 1710d522f475Smrg || *(cp = pw->pw_shell) == 0)) 1711d522f475Smrg || (shell = CastMallocN(char, strlen(cp))) == 0) { 1712cd3331d0Smrg static char dummy[] = "/bin/sh"; 1713cd3331d0Smrg shell = dummy; 1714d522f475Smrg } else { 1715d522f475Smrg strcpy(shell, cp); 1716d522f475Smrg } 1717d522f475Smrg 1718d522f475Smrg signal(SIGHUP, SIG_DFL); 1719d522f475Smrg signal(SIGCHLD, SIG_DFL); 1720d522f475Smrg 1721d522f475Smrg /* (this is redundant) */ 1722d522f475Smrg if (xtermResetIds(screen) < 0) 1723d522f475Smrg exit(ERROR_SETUID); 1724d522f475Smrg 1725d522f475Smrg execl(shell, shell, "-c", &screen->logfile[1], (void *) 0); 1726d522f475Smrg 1727c219fbebSmrg fprintf(stderr, "%s: Can't exec `%s'\n", 1728c219fbebSmrg ProgramName, 1729d522f475Smrg &screen->logfile[1]); 1730d522f475Smrg exit(ERROR_LOGEXEC); 1731d522f475Smrg } 1732d522f475Smrg close(p[0]); 1733d522f475Smrg screen->logfd = p[1]; 1734d522f475Smrg signal(SIGPIPE, logpipe); 1735d522f475Smrg#else 1736cd3331d0Smrg Bell(xw, XkbBI_Info, 0); 1737cd3331d0Smrg Bell(xw, XkbBI_Info, 0); 1738d522f475Smrg return; 1739d522f475Smrg#endif 1740d522f475Smrg } else { 1741d522f475Smrg if ((screen->logfd = open_userfile(screen->uid, 1742d522f475Smrg screen->gid, 1743d522f475Smrg screen->logfile, 1744d522f475Smrg (log_default != 0))) < 0) 1745d522f475Smrg return; 1746d522f475Smrg } 1747d522f475Smrg#endif /*VMS */ 1748d522f475Smrg screen->logstart = VTbuffer->next; 1749d522f475Smrg screen->logging = True; 1750d522f475Smrg update_logging(); 1751d522f475Smrg} 1752d522f475Smrg 1753d522f475Smrgvoid 1754cd3331d0SmrgCloseLog(XtermWidget xw) 1755d522f475Smrg{ 1756cd3331d0Smrg TScreen *screen = TScreenOf(xw); 1757cd3331d0Smrg 1758d522f475Smrg if (!screen->logging || (screen->inhibit & I_LOG)) 1759d522f475Smrg return; 1760cd3331d0Smrg FlushLog(xw); 1761d522f475Smrg close(screen->logfd); 1762d522f475Smrg screen->logging = False; 1763d522f475Smrg update_logging(); 1764d522f475Smrg} 1765d522f475Smrg 1766d522f475Smrgvoid 1767cd3331d0SmrgFlushLog(XtermWidget xw) 1768d522f475Smrg{ 1769cd3331d0Smrg TScreen *screen = TScreenOf(xw); 1770cd3331d0Smrg 1771d522f475Smrg if (screen->logging && !(screen->inhibit & I_LOG)) { 1772d522f475Smrg Char *cp; 1773d522f475Smrg int i; 1774d522f475Smrg 1775d522f475Smrg#ifdef VMS /* avoid logging output loops which otherwise occur sometimes 1776d522f475Smrg when there is no output and cp/screen->logstart are 1 apart */ 1777d522f475Smrg if (!tt_new_output) 1778d522f475Smrg return; 1779d522f475Smrg tt_new_output = False; 1780d522f475Smrg#endif /* VMS */ 1781d522f475Smrg cp = VTbuffer->next; 1782d522f475Smrg if (screen->logstart != 0 1783cd3331d0Smrg && (i = (int) (cp - screen->logstart)) > 0) { 1784cd3331d0Smrg IGNORE_RC(write(screen->logfd, screen->logstart, (size_t) i)); 1785d522f475Smrg } 1786d522f475Smrg screen->logstart = VTbuffer->next; 1787d522f475Smrg } 1788d522f475Smrg} 1789d522f475Smrg 1790d522f475Smrg#endif /* ALLOWLOGGING */ 1791d522f475Smrg 1792d522f475Smrg/***====================================================================***/ 1793d522f475Smrg 1794d522f475Smrg#if OPT_ISO_COLORS 1795d522f475Smrgstatic void 1796d522f475SmrgReportAnsiColorRequest(XtermWidget xw, int colornum, int final) 1797d522f475Smrg{ 1798cd3331d0Smrg if (AllowColorOps(xw, ecGetAnsiColor)) { 1799cd3331d0Smrg XColor color; 1800cd3331d0Smrg Colormap cmap = xw->core.colormap; 1801cd3331d0Smrg char buffer[80]; 1802cd3331d0Smrg 1803cd3331d0Smrg TRACE(("ReportAnsiColorRequest %d\n", colornum)); 1804cd3331d0Smrg color.pixel = GET_COLOR_RES(xw, TScreenOf(xw)->Acolors[colornum]); 1805cd3331d0Smrg XQueryColor(TScreenOf(xw)->display, cmap, &color); 1806cd3331d0Smrg sprintf(buffer, "4;%d;rgb:%04x/%04x/%04x", 1807cd3331d0Smrg colornum, 1808cd3331d0Smrg color.red, 1809cd3331d0Smrg color.green, 1810cd3331d0Smrg color.blue); 1811cd3331d0Smrg unparseputc1(xw, ANSI_OSC); 1812cd3331d0Smrg unparseputs(xw, buffer); 1813cd3331d0Smrg unparseputc1(xw, final); 1814cd3331d0Smrg unparse_end(xw); 1815cd3331d0Smrg } 1816d522f475Smrg} 1817d522f475Smrg 18180d92cbfdSchristosstatic unsigned 1819d522f475SmrggetColormapSize(Display * display) 1820d522f475Smrg{ 18210d92cbfdSchristos unsigned result; 1822d522f475Smrg int numFound; 1823d522f475Smrg XVisualInfo myTemplate, *visInfoPtr; 1824d522f475Smrg 1825d522f475Smrg myTemplate.visualid = XVisualIDFromVisual(DefaultVisual(display, 1826d522f475Smrg XDefaultScreen(display))); 1827d522f475Smrg visInfoPtr = XGetVisualInfo(display, (long) VisualIDMask, 1828d522f475Smrg &myTemplate, &numFound); 18290d92cbfdSchristos result = (numFound >= 1) ? (unsigned) visInfoPtr->colormap_size : 0; 1830d522f475Smrg 1831d522f475Smrg XFree((char *) visInfoPtr); 1832d522f475Smrg return result; 1833d522f475Smrg} 1834d522f475Smrg 1835d522f475Smrg/* 1836d522f475Smrg * Find closest color for "def" in "cmap". 1837d522f475Smrg * Set "def" to the resulting color. 1838d522f475Smrg * 1839d522f475Smrg * Based on Monish Shah's "find_closest_color()" for Vim 6.0, 1840d522f475Smrg * modified with ideas from David Tong's "noflash" library. 1841d522f475Smrg * The code from Vim in turn was derived from FindClosestColor() in Tcl/Tk. 1842d522f475Smrg * 1843d522f475Smrg * These provide some introduction: 1844d522f475Smrg * http://en.wikipedia.org/wiki/YIQ 1845d522f475Smrg * for an introduction to YIQ weights. 1846d522f475Smrg * http://en.wikipedia.org/wiki/Luminance_(video) 1847d522f475Smrg * for a discussion of luma. 1848d522f475Smrg * http://en.wikipedia.org/wiki/YUV 1849d522f475Smrg * 1850d522f475Smrg * Return False if not able to find or allocate a color. 1851d522f475Smrg */ 1852d522f475Smrgstatic Boolean 1853d522f475Smrgfind_closest_color(Display * dpy, Colormap cmap, XColor * def) 1854d522f475Smrg{ 1855d522f475Smrg Boolean result = False; 1856d522f475Smrg XColor *colortable; 1857d522f475Smrg char *tried; 1858d522f475Smrg double diff, thisRGB, bestRGB; 1859d522f475Smrg unsigned attempts; 1860d522f475Smrg unsigned bestInx; 1861d522f475Smrg unsigned cmap_size; 1862d522f475Smrg unsigned i; 1863d522f475Smrg 1864d522f475Smrg cmap_size = getColormapSize(dpy); 1865d522f475Smrg if (cmap_size != 0) { 1866d522f475Smrg 1867b7c89284Ssnj colortable = TypeMallocN(XColor, (size_t) cmap_size); 1868d522f475Smrg if (colortable != 0) { 1869d522f475Smrg 1870b7c89284Ssnj tried = TypeCallocN(char, (size_t) cmap_size); 1871d522f475Smrg if (tried != 0) { 1872d522f475Smrg 1873d522f475Smrg for (i = 0; i < cmap_size; i++) { 1874d522f475Smrg colortable[i].pixel = (unsigned long) i; 1875d522f475Smrg } 1876d522f475Smrg XQueryColors(dpy, cmap, colortable, (int) cmap_size); 1877d522f475Smrg 1878d522f475Smrg /* 1879d522f475Smrg * Try (possibly each entry in the color map) to find the best 1880d522f475Smrg * approximation to the requested color. 1881d522f475Smrg */ 1882d522f475Smrg for (attempts = 0; attempts < cmap_size; attempts++) { 1883d522f475Smrg Boolean first = True; 1884d522f475Smrg 1885d522f475Smrg bestRGB = 0.0; 1886d522f475Smrg bestInx = 0; 1887d522f475Smrg for (i = 0; i < cmap_size; i++) { 1888d522f475Smrg if (!tried[bestInx]) { 1889d522f475Smrg /* 1890d522f475Smrg * Look for the best match based on luminance. 1891d522f475Smrg * Measure this by the least-squares difference of 1892d522f475Smrg * the weighted R/G/B components from the color map 1893d522f475Smrg * versus the requested color. Use the Y (luma) 1894d522f475Smrg * component of the YIQ color space model for 1895d522f475Smrg * weights that correspond to the luminance. 1896d522f475Smrg */ 1897d522f475Smrg#define AddColorWeight(weight, color) \ 1898d522f475Smrg diff = weight * (int) ((def->color) - colortable[i].color); \ 1899d522f475Smrg thisRGB = diff * diff 1900d522f475Smrg 1901d522f475Smrg AddColorWeight(0.30, red); 1902d522f475Smrg AddColorWeight(0.61, green); 1903d522f475Smrg AddColorWeight(0.11, blue); 1904d522f475Smrg 1905d522f475Smrg if (first || (thisRGB < bestRGB)) { 1906d522f475Smrg first = False; 1907d522f475Smrg bestInx = i; 1908d522f475Smrg bestRGB = thisRGB; 1909d522f475Smrg } 1910d522f475Smrg } 1911d522f475Smrg } 1912d522f475Smrg if (XAllocColor(dpy, cmap, &colortable[bestInx]) != 0) { 1913d522f475Smrg *def = colortable[bestInx]; 1914d522f475Smrg result = True; 1915d522f475Smrg break; 1916d522f475Smrg } 1917d522f475Smrg /* 1918d522f475Smrg * It failed - either the color map entry was readonly, or 1919d522f475Smrg * another client has allocated the entry. Mark the entry 1920d522f475Smrg * so we will ignore it 1921d522f475Smrg */ 1922d522f475Smrg tried[bestInx] = True; 1923d522f475Smrg } 1924d522f475Smrg free(tried); 1925d522f475Smrg } 1926d522f475Smrg free(colortable); 1927d522f475Smrg } 1928d522f475Smrg } 1929d522f475Smrg return result; 1930d522f475Smrg} 1931d522f475Smrg 1932d522f475Smrg/* 1933d522f475Smrg * Allocate a color for the "ANSI" colors. That actually includes colors up 1934d522f475Smrg * to 256. 1935d522f475Smrg * 1936d522f475Smrg * Returns 1937d522f475Smrg * -1 on error 1938d522f475Smrg * 0 on no change 1939d522f475Smrg * 1 if a new color was allocated. 1940d522f475Smrg */ 1941d522f475Smrgstatic int 1942d522f475SmrgAllocateAnsiColor(XtermWidget xw, 1943d522f475Smrg ColorRes * res, 1944cd3331d0Smrg const char *spec) 1945d522f475Smrg{ 1946d522f475Smrg int result; 1947d522f475Smrg XColor def; 1948cd3331d0Smrg TScreen *screen = TScreenOf(xw); 1949d522f475Smrg Colormap cmap = xw->core.colormap; 1950d522f475Smrg 1951d522f475Smrg if (XParseColor(screen->display, cmap, spec, &def) 1952d522f475Smrg && (XAllocColor(screen->display, cmap, &def) 1953d522f475Smrg || find_closest_color(screen->display, cmap, &def))) { 1954d522f475Smrg if ( 1955d522f475Smrg#if OPT_COLOR_RES 1956d522f475Smrg res->mode == True && 1957d522f475Smrg#endif 1958d522f475Smrg EQL_COLOR_RES(res, def.pixel)) { 1959d522f475Smrg result = 0; 1960d522f475Smrg } else { 1961d522f475Smrg result = 1; 1962d522f475Smrg SET_COLOR_RES(res, def.pixel); 1963d522f475Smrg TRACE(("AllocateAnsiColor[%d] %s (pixel %#lx)\n", 1964cd3331d0Smrg (int) (res - screen->Acolors), spec, def.pixel)); 1965d522f475Smrg#if OPT_COLOR_RES 1966d522f475Smrg if (!res->mode) 1967d522f475Smrg result = 0; 1968d522f475Smrg res->mode = True; 1969d522f475Smrg#endif 1970d522f475Smrg } 1971d522f475Smrg } else { 1972d522f475Smrg TRACE(("AllocateAnsiColor %s (failed)\n", spec)); 1973d522f475Smrg result = -1; 1974d522f475Smrg } 1975d522f475Smrg return (result); 1976d522f475Smrg} 1977d522f475Smrg 1978d522f475Smrg#if OPT_COLOR_RES 1979d522f475SmrgPixel 1980cd3331d0SmrgxtermGetColorRes(XtermWidget xw, ColorRes * res) 1981d522f475Smrg{ 1982d522f475Smrg Pixel result = 0; 1983d522f475Smrg 1984d522f475Smrg if (res->mode) { 1985d522f475Smrg result = res->value; 1986d522f475Smrg } else { 1987d522f475Smrg TRACE(("xtermGetColorRes for Acolors[%d]\n", 1988cd3331d0Smrg (int) (res - TScreenOf(xw)->Acolors))); 1989d522f475Smrg 1990cd3331d0Smrg if (res >= TScreenOf(xw)->Acolors) { 1991cd3331d0Smrg assert(res - TScreenOf(xw)->Acolors < MAXCOLORS); 1992d522f475Smrg 1993cd3331d0Smrg if (AllocateAnsiColor(xw, res, res->resource) < 0) { 1994cd3331d0Smrg res->value = TScreenOf(xw)->Tcolors[TEXT_FG].value; 1995d522f475Smrg res->mode = -True; 1996d522f475Smrg fprintf(stderr, 1997c952d7faSmrg "%s: Cannot allocate color \"%s\"\n", 1998c219fbebSmrg ProgramName, 1999d522f475Smrg NonNull(res->resource)); 2000d522f475Smrg } 2001d522f475Smrg result = res->value; 2002d522f475Smrg } else { 2003d522f475Smrg result = 0; 2004d522f475Smrg } 2005d522f475Smrg } 2006d522f475Smrg return result; 2007d522f475Smrg} 2008d522f475Smrg#endif 2009d522f475Smrg 2010cd3331d0Smrgstatic int 2011cd3331d0SmrgChangeOneAnsiColor(XtermWidget xw, int color, const char *name) 2012cd3331d0Smrg{ 2013cd3331d0Smrg int code; 2014cd3331d0Smrg 2015cd3331d0Smrg if (color < 0 || color >= MAXCOLORS) { 2016cd3331d0Smrg code = -1; 2017cd3331d0Smrg } else { 2018cd3331d0Smrg ColorRes *res = &(TScreenOf(xw)->Acolors[color]); 2019cd3331d0Smrg 2020cd3331d0Smrg TRACE(("ChangeAnsiColor for Acolors[%d]\n", color)); 2021cd3331d0Smrg code = AllocateAnsiColor(xw, res, name); 2022cd3331d0Smrg } 2023cd3331d0Smrg return code; 2024cd3331d0Smrg} 2025cd3331d0Smrg 2026cd3331d0Smrg/* 2027cd3331d0Smrg * Set or query entries in the Acolors[] array by parsing pairs of color/name 2028cd3331d0Smrg * values from the given buffer. 2029cd3331d0Smrg * 2030cd3331d0Smrg * The color can be any legal index into Acolors[], which consists of the 2031cd3331d0Smrg * 16/88/256 "ANSI" colors, followed by special color values for the various 2032cd3331d0Smrg * colorXX resources. The indices for the special color values are not 2033cd3331d0Smrg * simple to work with, so an alternative is to use the calls which pass in 2034cd3331d0Smrg * 'first' set to the beginning of those indices. 2035cd3331d0Smrg * 2036cd3331d0Smrg * If the name is "?", report to the host the current value for the color. 2037cd3331d0Smrg */ 2038d522f475Smrgstatic Bool 2039d522f475SmrgChangeAnsiColorRequest(XtermWidget xw, 2040d522f475Smrg char *buf, 2041cd3331d0Smrg int first, 2042d522f475Smrg int final) 2043d522f475Smrg{ 2044d522f475Smrg char *name; 2045d522f475Smrg int color; 2046d522f475Smrg int repaint = False; 2047d522f475Smrg int code; 2048cd3331d0Smrg int last = (MAXCOLORS - first); 2049d522f475Smrg 2050d522f475Smrg TRACE(("ChangeAnsiColorRequest string='%s'\n", buf)); 2051d522f475Smrg 2052d522f475Smrg while (buf && *buf) { 2053d522f475Smrg name = strchr(buf, ';'); 2054d522f475Smrg if (name == NULL) 2055d522f475Smrg break; 2056d522f475Smrg *name = '\0'; 2057d522f475Smrg name++; 2058d522f475Smrg color = atoi(buf); 2059cd3331d0Smrg if (color < 0 || color >= last) 2060cd3331d0Smrg break; /* quit on any error */ 2061d522f475Smrg buf = strchr(name, ';'); 2062d522f475Smrg if (buf) { 2063d522f475Smrg *buf = '\0'; 2064d522f475Smrg buf++; 2065d522f475Smrg } 2066cd3331d0Smrg if (!strcmp(name, "?")) { 2067cd3331d0Smrg ReportAnsiColorRequest(xw, color + first, final); 2068cd3331d0Smrg } else { 2069cd3331d0Smrg code = ChangeOneAnsiColor(xw, color + first, name); 2070d522f475Smrg if (code < 0) { 2071d522f475Smrg /* stop on any error */ 2072d522f475Smrg break; 2073d522f475Smrg } else if (code > 0) { 2074d522f475Smrg repaint = True; 2075d522f475Smrg } 2076d522f475Smrg /* FIXME: free old color somehow? We aren't for the other color 2077d522f475Smrg * change style (dynamic colors). 2078d522f475Smrg */ 2079d522f475Smrg } 2080d522f475Smrg } 2081d522f475Smrg 2082d522f475Smrg return (repaint); 2083d522f475Smrg} 2084cd3331d0Smrg 2085cd3331d0Smrgstatic Bool 2086cd3331d0SmrgResetOneAnsiColor(XtermWidget xw, int color, int start) 2087cd3331d0Smrg{ 2088cd3331d0Smrg Bool repaint = False; 2089cd3331d0Smrg int last = MAXCOLORS - start; 2090cd3331d0Smrg 2091cd3331d0Smrg if (color >= 0 && color < last) { 2092cd3331d0Smrg ColorRes *res = &(TScreenOf(xw)->Acolors[color + start]); 2093cd3331d0Smrg 2094cd3331d0Smrg if (res->mode) { 2095cd3331d0Smrg /* a color has been allocated for this slot - test further... */ 2096cd3331d0Smrg if (ChangeOneAnsiColor(xw, color + start, res->resource) > 0) { 2097cd3331d0Smrg repaint = True; 2098cd3331d0Smrg } 2099cd3331d0Smrg } 2100cd3331d0Smrg } 2101cd3331d0Smrg return repaint; 2102cd3331d0Smrg} 2103cd3331d0Smrg 2104cd3331d0Smrgint 2105cd3331d0SmrgResetAnsiColorRequest(XtermWidget xw, char *buf, int start) 2106cd3331d0Smrg{ 2107cd3331d0Smrg int repaint = 0; 2108cd3331d0Smrg int color; 2109cd3331d0Smrg 2110cd3331d0Smrg TRACE(("ResetAnsiColorRequest(%s)\n", buf)); 2111cd3331d0Smrg if (*buf != '\0') { 2112cd3331d0Smrg /* reset specific colors */ 2113cd3331d0Smrg while (!IsEmpty(buf)) { 2114cd3331d0Smrg char *next; 2115cd3331d0Smrg 2116cd3331d0Smrg color = (int) strtol(buf, &next, 10); 2117cd3331d0Smrg if ((next == buf) || (color < 0)) 2118cd3331d0Smrg break; /* no number at all */ 2119cd3331d0Smrg if (next != 0) { 2120cd3331d0Smrg if (strchr(";", *next) == 0) 2121cd3331d0Smrg break; /* unexpected delimiter */ 2122cd3331d0Smrg ++next; 2123cd3331d0Smrg } 2124cd3331d0Smrg 2125cd3331d0Smrg if (ResetOneAnsiColor(xw, color, start)) { 2126cd3331d0Smrg ++repaint; 2127cd3331d0Smrg } 2128cd3331d0Smrg buf = next; 2129cd3331d0Smrg } 2130cd3331d0Smrg } else { 2131cd3331d0Smrg TRACE(("...resetting all %d colors\n", MAXCOLORS)); 2132cd3331d0Smrg for (color = 0; color < MAXCOLORS; ++color) { 2133cd3331d0Smrg if (ResetOneAnsiColor(xw, color, start)) { 2134cd3331d0Smrg ++repaint; 2135cd3331d0Smrg } 2136cd3331d0Smrg } 2137cd3331d0Smrg } 2138cd3331d0Smrg TRACE(("...ResetAnsiColorRequest ->%d\n", repaint)); 2139cd3331d0Smrg return repaint; 2140cd3331d0Smrg} 2141d522f475Smrg#else 2142d522f475Smrg#define find_closest_color(display, cmap, def) 0 2143d522f475Smrg#endif /* OPT_ISO_COLORS */ 2144d522f475Smrg 2145d522f475Smrg#if OPT_PASTE64 2146d522f475Smrgstatic void 2147d522f475SmrgManipulateSelectionData(XtermWidget xw, TScreen * screen, char *buf, int final) 2148d522f475Smrg{ 2149d522f475Smrg#define PDATA(a,b) { a, #b } 2150d522f475Smrg static struct { 2151d522f475Smrg char given; 2152cd3331d0Smrg String result; 2153d522f475Smrg } table[] = { 2154d522f475Smrg PDATA('s', SELECT), 2155d522f475Smrg PDATA('p', PRIMARY), 2156d522f475Smrg PDATA('c', CLIPBOARD), 2157d522f475Smrg PDATA('0', CUT_BUFFER0), 2158d522f475Smrg PDATA('1', CUT_BUFFER1), 2159d522f475Smrg PDATA('2', CUT_BUFFER2), 2160d522f475Smrg PDATA('3', CUT_BUFFER3), 2161d522f475Smrg PDATA('4', CUT_BUFFER4), 2162d522f475Smrg PDATA('5', CUT_BUFFER5), 2163d522f475Smrg PDATA('6', CUT_BUFFER6), 2164d522f475Smrg PDATA('7', CUT_BUFFER7), 2165d522f475Smrg }; 2166d522f475Smrg 2167cd3331d0Smrg const char *base = buf; 2168d522f475Smrg char *used = x_strdup(base); 2169d522f475Smrg Cardinal j, n = 0; 2170cd3331d0Smrg String *select_args = 0; 2171d522f475Smrg 2172d522f475Smrg TRACE(("Manipulate selection data\n")); 2173d522f475Smrg 2174d522f475Smrg while (*buf != ';' && *buf != '\0') { 2175d522f475Smrg ++buf; 2176d522f475Smrg } 2177d522f475Smrg 2178d522f475Smrg if (*buf == ';') { 2179d522f475Smrg *buf++ = '\0'; 2180d522f475Smrg 2181d522f475Smrg if (*base == '\0') 2182d522f475Smrg base = "s0"; 2183d522f475Smrg if ((select_args = TypeCallocN(String, 1 + strlen(base))) == 0) 2184d522f475Smrg return; 2185d522f475Smrg while (*base != '\0') { 2186d522f475Smrg for (j = 0; j < XtNumber(table); ++j) { 2187d522f475Smrg if (*base == table[j].given) { 2188d522f475Smrg used[n] = *base; 2189d522f475Smrg select_args[n++] = table[j].result; 2190d522f475Smrg TRACE(("atom[%d] %s\n", n, table[j].result)); 2191d522f475Smrg break; 2192d522f475Smrg } 2193d522f475Smrg } 2194d522f475Smrg ++base; 2195d522f475Smrg } 2196d522f475Smrg used[n] = 0; 2197d522f475Smrg 2198d522f475Smrg if (!strcmp(buf, "?")) { 2199cd3331d0Smrg if (AllowWindowOps(xw, ewGetSelection)) { 2200cd3331d0Smrg TRACE(("Getting selection\n")); 2201cd3331d0Smrg unparseputc1(xw, ANSI_OSC); 2202cd3331d0Smrg unparseputs(xw, "52"); 2203cd3331d0Smrg unparseputc(xw, ';'); 2204d522f475Smrg 2205cd3331d0Smrg unparseputs(xw, used); 2206cd3331d0Smrg unparseputc(xw, ';'); 2207d522f475Smrg 2208cd3331d0Smrg /* Tell xtermGetSelection data is base64 encoded */ 2209cd3331d0Smrg screen->base64_paste = n; 2210cd3331d0Smrg screen->base64_final = final; 2211d522f475Smrg 2212cd3331d0Smrg /* terminator will be written in this call */ 2213cd3331d0Smrg xtermGetSelection((Widget) xw, (Time) 0, select_args, n, NULL); 2214cd3331d0Smrg } 2215d522f475Smrg } else { 2216cd3331d0Smrg if (AllowWindowOps(xw, ewSetSelection)) { 2217cd3331d0Smrg TRACE(("Setting selection with %s\n", buf)); 2218cd3331d0Smrg ClearSelectionBuffer(screen); 2219cd3331d0Smrg while (*buf != '\0') 2220cd3331d0Smrg AppendToSelectionBuffer(screen, CharOf(*buf++)); 2221cd3331d0Smrg CompleteSelection(xw, select_args, n); 2222cd3331d0Smrg } 2223d522f475Smrg } 2224d522f475Smrg } 2225d522f475Smrg} 2226d522f475Smrg#endif /* OPT_PASTE64 */ 2227d522f475Smrg 2228d522f475Smrg/***====================================================================***/ 2229d522f475Smrg 2230cd3331d0Smrg#define IsSetUtf8Title(xw) (IsTitleMode(xw, tmSetUtf8) || (xw->screen.utf8_title)) 2231cd3331d0Smrg 2232d522f475Smrgstatic Bool 2233cd3331d0SmrgxtermIsPrintable(XtermWidget xw, Char ** bufp, Char * last) 2234d522f475Smrg{ 2235cd3331d0Smrg TScreen *screen = TScreenOf(xw); 2236d522f475Smrg Bool result = False; 2237d522f475Smrg Char *cp = *bufp; 2238d522f475Smrg Char *next = cp; 2239d522f475Smrg 2240d522f475Smrg (void) screen; 2241d522f475Smrg (void) last; 2242d522f475Smrg 2243d522f475Smrg#if OPT_WIDE_CHARS 2244cd3331d0Smrg if (xtermEnvUTF8() && IsSetUtf8Title(xw)) { 2245d522f475Smrg PtyData data; 2246d522f475Smrg 2247d522f475Smrg if (decodeUtf8(fakePtyData(&data, cp, last))) { 2248d522f475Smrg if (data.utf_data != UCS_REPL 2249d522f475Smrg && (data.utf_data >= 128 || 2250d522f475Smrg ansi_table[data.utf_data] == CASE_PRINT)) { 2251d522f475Smrg next += (data.utf_size - 1); 2252d522f475Smrg result = True; 2253d522f475Smrg } else { 2254d522f475Smrg result = False; 2255d522f475Smrg } 2256d522f475Smrg } else { 2257d522f475Smrg result = False; 2258d522f475Smrg } 2259d522f475Smrg } else 2260d522f475Smrg#endif 2261d522f475Smrg#if OPT_C1_PRINT 2262d522f475Smrg if (screen->c1_printable 2263d522f475Smrg && (*cp >= 128 && *cp < 160)) { 2264d522f475Smrg result = True; 2265d522f475Smrg } else 2266d522f475Smrg#endif 2267d522f475Smrg if (ansi_table[*cp] == CASE_PRINT) { 2268d522f475Smrg result = True; 2269d522f475Smrg } 2270d522f475Smrg *bufp = next; 2271d522f475Smrg return result; 2272d522f475Smrg} 2273d522f475Smrg 2274d522f475Smrg/***====================================================================***/ 2275d522f475Smrg 2276d522f475Smrg/* 2277d522f475Smrg * Enum corresponding to the actual OSC codes rather than the internal 2278cd3331d0Smrg * array indices. Compare with TermColors. 2279d522f475Smrg */ 2280d522f475Smrgtypedef enum { 2281d522f475Smrg OSC_TEXT_FG = 10 2282d522f475Smrg ,OSC_TEXT_BG 2283d522f475Smrg ,OSC_TEXT_CURSOR 2284d522f475Smrg ,OSC_MOUSE_FG 2285d522f475Smrg ,OSC_MOUSE_BG 2286d522f475Smrg#if OPT_TEK4014 2287d522f475Smrg ,OSC_TEK_FG = 15 2288d522f475Smrg ,OSC_TEK_BG 2289d522f475Smrg#endif 2290d522f475Smrg#if OPT_HIGHLIGHT_COLOR 2291d522f475Smrg ,OSC_HIGHLIGHT_BG = 17 2292d522f475Smrg#endif 2293d522f475Smrg#if OPT_TEK4014 2294d522f475Smrg ,OSC_TEK_CURSOR = 18 2295d522f475Smrg#endif 2296d522f475Smrg#if OPT_HIGHLIGHT_COLOR 2297d522f475Smrg ,OSC_HIGHLIGHT_FG = 19 2298d522f475Smrg#endif 2299d522f475Smrg ,OSC_NCOLORS 2300d522f475Smrg} OscTextColors; 2301d522f475Smrg 2302cd3331d0Smrg/* 2303cd3331d0Smrg * Map codes to OSC controls that can reset colors. 2304cd3331d0Smrg */ 2305cd3331d0Smrg#define OSC_RESET 100 2306cd3331d0Smrg#define OSC_Reset(code) (code) + OSC_RESET 2307cd3331d0Smrg 2308d522f475Smrgstatic ScrnColors *pOldColors = NULL; 2309d522f475Smrg 2310d522f475Smrgstatic Bool 2311d522f475SmrgGetOldColors(XtermWidget xw) 2312d522f475Smrg{ 2313d522f475Smrg int i; 2314d522f475Smrg if (pOldColors == NULL) { 2315c219fbebSmrg pOldColors = TypeXtMalloc(ScrnColors); 2316d522f475Smrg if (pOldColors == NULL) { 2317d522f475Smrg fprintf(stderr, "allocation failure in GetOldColors\n"); 2318d522f475Smrg return (False); 2319d522f475Smrg } 2320d522f475Smrg pOldColors->which = 0; 2321d522f475Smrg for (i = 0; i < NCOLORS; i++) { 2322d522f475Smrg pOldColors->colors[i] = 0; 2323d522f475Smrg pOldColors->names[i] = NULL; 2324d522f475Smrg } 2325d522f475Smrg GetColors(xw, pOldColors); 2326d522f475Smrg } 2327d522f475Smrg return (True); 2328d522f475Smrg} 2329d522f475Smrg 2330d522f475Smrgstatic int 2331d522f475SmrgoppositeColor(int n) 2332d522f475Smrg{ 2333d522f475Smrg switch (n) { 2334d522f475Smrg case TEXT_FG: 2335d522f475Smrg n = TEXT_BG; 2336d522f475Smrg break; 2337d522f475Smrg case TEXT_BG: 2338d522f475Smrg n = TEXT_FG; 2339d522f475Smrg break; 2340d522f475Smrg case MOUSE_FG: 2341d522f475Smrg n = MOUSE_BG; 2342d522f475Smrg break; 2343d522f475Smrg case MOUSE_BG: 2344d522f475Smrg n = MOUSE_FG; 2345d522f475Smrg break; 2346d522f475Smrg#if OPT_TEK4014 2347d522f475Smrg case TEK_FG: 2348d522f475Smrg n = TEK_BG; 2349d522f475Smrg break; 2350d522f475Smrg case TEK_BG: 2351d522f475Smrg n = TEK_FG; 2352d522f475Smrg break; 2353d522f475Smrg#endif 2354d522f475Smrg#if OPT_HIGHLIGHT_COLOR 2355d522f475Smrg case HIGHLIGHT_FG: 2356d522f475Smrg n = HIGHLIGHT_BG; 2357d522f475Smrg break; 2358d522f475Smrg case HIGHLIGHT_BG: 2359d522f475Smrg n = HIGHLIGHT_FG; 2360d522f475Smrg break; 2361d522f475Smrg#endif 2362d522f475Smrg default: 2363d522f475Smrg break; 2364d522f475Smrg } 2365d522f475Smrg return n; 2366d522f475Smrg} 2367d522f475Smrg 2368d522f475Smrgstatic void 2369d522f475SmrgReportColorRequest(XtermWidget xw, int ndx, int final) 2370d522f475Smrg{ 2371cd3331d0Smrg if (AllowColorOps(xw, ecGetColor)) { 2372cd3331d0Smrg XColor color; 2373cd3331d0Smrg Colormap cmap = xw->core.colormap; 2374cd3331d0Smrg char buffer[80]; 2375d522f475Smrg 2376cd3331d0Smrg /* 2377cd3331d0Smrg * ChangeColorsRequest() has "always" chosen the opposite color when 2378cd3331d0Smrg * reverse-video is set. Report this as the original color index, but 2379cd3331d0Smrg * reporting the opposite color which would be used. 2380cd3331d0Smrg */ 2381cd3331d0Smrg int i = (xw->misc.re_verse) ? oppositeColor(ndx) : ndx; 2382cd3331d0Smrg 2383cd3331d0Smrg GetOldColors(xw); 2384cd3331d0Smrg color.pixel = pOldColors->colors[ndx]; 2385cd3331d0Smrg XQueryColor(TScreenOf(xw)->display, cmap, &color); 2386cd3331d0Smrg sprintf(buffer, "%d;rgb:%04x/%04x/%04x", i + 10, 2387cd3331d0Smrg color.red, 2388cd3331d0Smrg color.green, 2389cd3331d0Smrg color.blue); 2390cd3331d0Smrg TRACE(("ReportColors %d: %#lx as %s\n", 2391cd3331d0Smrg ndx, pOldColors->colors[ndx], buffer)); 2392cd3331d0Smrg unparseputc1(xw, ANSI_OSC); 2393cd3331d0Smrg unparseputs(xw, buffer); 2394cd3331d0Smrg unparseputc1(xw, final); 2395cd3331d0Smrg unparse_end(xw); 2396cd3331d0Smrg } 2397d522f475Smrg} 2398d522f475Smrg 2399d522f475Smrgstatic Bool 2400d522f475SmrgUpdateOldColors(XtermWidget xw GCC_UNUSED, ScrnColors * pNew) 2401d522f475Smrg{ 2402d522f475Smrg int i; 2403d522f475Smrg 2404d522f475Smrg /* if we were going to free old colors, this would be the place to 2405d522f475Smrg * do it. I've decided not to (for now), because it seems likely 2406d522f475Smrg * that we'd have a small set of colors we use over and over, and that 2407d522f475Smrg * we could save some overhead this way. The only case in which this 2408d522f475Smrg * (clearly) fails is if someone is trying a boatload of colors, in 2409d522f475Smrg * which case they can restart xterm 2410d522f475Smrg */ 2411d522f475Smrg for (i = 0; i < NCOLORS; i++) { 2412d522f475Smrg if (COLOR_DEFINED(pNew, i)) { 2413d522f475Smrg if (pOldColors->names[i] != NULL) { 2414d522f475Smrg XtFree(pOldColors->names[i]); 2415d522f475Smrg pOldColors->names[i] = NULL; 2416d522f475Smrg } 2417d522f475Smrg if (pNew->names[i]) { 2418d522f475Smrg pOldColors->names[i] = pNew->names[i]; 2419d522f475Smrg } 2420d522f475Smrg pOldColors->colors[i] = pNew->colors[i]; 2421d522f475Smrg } 2422d522f475Smrg } 2423d522f475Smrg return (True); 2424d522f475Smrg} 2425d522f475Smrg 2426d522f475Smrg/* 2427d522f475Smrg * OSC codes are constant, but the indices for the color arrays depend on how 2428d522f475Smrg * xterm is compiled. 2429d522f475Smrg */ 2430d522f475Smrgstatic int 2431d522f475SmrgOscToColorIndex(OscTextColors mode) 2432d522f475Smrg{ 2433d522f475Smrg int result = 0; 2434d522f475Smrg 2435d522f475Smrg#define CASE(name) case OSC_##name: result = name; break 2436d522f475Smrg switch (mode) { 2437d522f475Smrg CASE(TEXT_FG); 2438d522f475Smrg CASE(TEXT_BG); 2439d522f475Smrg CASE(TEXT_CURSOR); 2440d522f475Smrg CASE(MOUSE_FG); 2441d522f475Smrg CASE(MOUSE_BG); 2442d522f475Smrg#if OPT_TEK4014 2443d522f475Smrg CASE(TEK_FG); 2444d522f475Smrg CASE(TEK_BG); 2445d522f475Smrg#endif 2446d522f475Smrg#if OPT_HIGHLIGHT_COLOR 2447d522f475Smrg CASE(HIGHLIGHT_BG); 2448d522f475Smrg CASE(HIGHLIGHT_FG); 2449d522f475Smrg#endif 2450d522f475Smrg#if OPT_TEK4014 2451d522f475Smrg CASE(TEK_CURSOR); 2452d522f475Smrg#endif 2453d522f475Smrg case OSC_NCOLORS: 2454d522f475Smrg break; 2455d522f475Smrg } 2456d522f475Smrg return result; 2457d522f475Smrg} 2458d522f475Smrg 2459d522f475Smrgstatic Bool 2460d522f475SmrgChangeColorsRequest(XtermWidget xw, 2461d522f475Smrg int start, 2462d522f475Smrg char *names, 2463d522f475Smrg int final) 2464d522f475Smrg{ 2465d522f475Smrg Bool result = False; 2466d522f475Smrg char *thisName; 2467d522f475Smrg ScrnColors newColors; 2468d522f475Smrg int i, ndx; 2469d522f475Smrg 2470d522f475Smrg TRACE(("ChangeColorsRequest start=%d, names='%s'\n", start, names)); 2471d522f475Smrg 2472d522f475Smrg if (GetOldColors(xw)) { 2473d522f475Smrg newColors.which = 0; 2474d522f475Smrg for (i = 0; i < NCOLORS; i++) { 2475d522f475Smrg newColors.names[i] = NULL; 2476d522f475Smrg } 2477d522f475Smrg for (i = start; i < OSC_NCOLORS; i++) { 2478d522f475Smrg ndx = OscToColorIndex((OscTextColors) i); 2479d522f475Smrg if (xw->misc.re_verse) 2480d522f475Smrg ndx = oppositeColor(ndx); 2481d522f475Smrg 2482cd3331d0Smrg if (IsEmpty(names)) { 2483d522f475Smrg newColors.names[ndx] = NULL; 2484d522f475Smrg } else { 2485d522f475Smrg if (names[0] == ';') 2486d522f475Smrg thisName = NULL; 2487d522f475Smrg else 2488d522f475Smrg thisName = names; 2489d522f475Smrg names = strchr(names, ';'); 2490d522f475Smrg if (names != NULL) { 2491d522f475Smrg *names++ = '\0'; 2492d522f475Smrg } 2493d522f475Smrg if (thisName != 0 && !strcmp(thisName, "?")) { 2494d522f475Smrg ReportColorRequest(xw, ndx, final); 2495d522f475Smrg } else if (!pOldColors->names[ndx] 2496d522f475Smrg || (thisName 2497d522f475Smrg && strcmp(thisName, pOldColors->names[ndx]))) { 2498cd3331d0Smrg AllocateTermColor(xw, &newColors, ndx, thisName, False); 2499d522f475Smrg } 2500d522f475Smrg } 2501d522f475Smrg } 2502d522f475Smrg 2503d522f475Smrg if (newColors.which != 0) { 2504d522f475Smrg ChangeColors(xw, &newColors); 2505d522f475Smrg UpdateOldColors(xw, &newColors); 2506d522f475Smrg } 2507d522f475Smrg result = True; 2508d522f475Smrg } 2509d522f475Smrg return result; 2510d522f475Smrg} 2511d522f475Smrg 2512cd3331d0Smrgstatic Bool 2513cd3331d0SmrgResetColorsRequest(XtermWidget xw, 2514cd3331d0Smrg int code) 2515cd3331d0Smrg{ 2516cd3331d0Smrg Bool result = False; 2517cd3331d0Smrg const char *thisName; 2518cd3331d0Smrg ScrnColors newColors; 2519cd3331d0Smrg int ndx; 2520cd3331d0Smrg 2521cd3331d0Smrg TRACE(("ResetColorsRequest code=%d\n", code)); 2522cd3331d0Smrg 2523cd3331d0Smrg#if OPT_COLOR_RES 2524cd3331d0Smrg if (GetOldColors(xw)) { 2525cd3331d0Smrg ndx = OscToColorIndex((OscTextColors) (code - OSC_RESET)); 2526cd3331d0Smrg if (xw->misc.re_verse) 2527cd3331d0Smrg ndx = oppositeColor(ndx); 2528cd3331d0Smrg 2529cd3331d0Smrg thisName = xw->screen.Tcolors[ndx].resource; 2530cd3331d0Smrg 2531cd3331d0Smrg newColors.which = 0; 2532cd3331d0Smrg newColors.names[ndx] = NULL; 2533cd3331d0Smrg 2534cd3331d0Smrg if (thisName != 0 2535cd3331d0Smrg && pOldColors->names[ndx] != 0 2536cd3331d0Smrg && strcmp(thisName, pOldColors->names[ndx])) { 2537cd3331d0Smrg AllocateTermColor(xw, &newColors, ndx, thisName, False); 2538cd3331d0Smrg 2539cd3331d0Smrg if (newColors.which != 0) { 2540cd3331d0Smrg ChangeColors(xw, &newColors); 2541cd3331d0Smrg UpdateOldColors(xw, &newColors); 2542cd3331d0Smrg } 2543cd3331d0Smrg } 2544cd3331d0Smrg result = True; 2545cd3331d0Smrg } 2546cd3331d0Smrg#endif 2547cd3331d0Smrg return result; 2548cd3331d0Smrg} 2549cd3331d0Smrg 2550cd3331d0Smrg#if OPT_SHIFT_FONTS 2551cd3331d0Smrg/* 2552cd3331d0Smrg * Initially, 'source' points to '#' or '?'. 2553cd3331d0Smrg * 2554cd3331d0Smrg * Look for an optional sign and optional number. If those are found, lookup 2555cd3331d0Smrg * the corresponding menu font entry. 2556cd3331d0Smrg */ 2557cd3331d0Smrgstatic int 2558cb4a1343SmrgParseShiftedFont(XtermWidget xw, String source, String * target) 2559cd3331d0Smrg{ 2560cd3331d0Smrg TScreen *screen = TScreenOf(xw); 2561cd3331d0Smrg int num = screen->menu_font_number; 2562cd3331d0Smrg int rel = 0; 2563cd3331d0Smrg 2564cd3331d0Smrg if (*++source == '+') { 2565cd3331d0Smrg rel = 1; 2566cd3331d0Smrg source++; 2567cd3331d0Smrg } else if (*source == '-') { 2568cd3331d0Smrg rel = -1; 2569cd3331d0Smrg source++; 2570cd3331d0Smrg } 2571cd3331d0Smrg 2572cd3331d0Smrg if (isdigit(CharOf(*source))) { 2573cd3331d0Smrg int val = atoi(source); 2574cd3331d0Smrg if (rel > 0) 2575cd3331d0Smrg rel = val; 2576cd3331d0Smrg else if (rel < 0) 2577cd3331d0Smrg rel = -val; 2578cd3331d0Smrg else 2579cd3331d0Smrg num = val; 2580cd3331d0Smrg } 2581cd3331d0Smrg 2582cd3331d0Smrg if (rel != 0) { 2583cd3331d0Smrg num = lookupRelativeFontSize(xw, 2584cd3331d0Smrg screen->menu_font_number, rel); 2585cd3331d0Smrg 2586cd3331d0Smrg } 2587cd3331d0Smrg TRACE(("ParseShiftedFont(%s) ->%d (%s)\n", *target, num, source)); 2588cd3331d0Smrg *target = source; 2589cd3331d0Smrg return num; 2590cd3331d0Smrg} 2591cd3331d0Smrg 2592cd3331d0Smrgstatic void 2593cb4a1343SmrgQueryFontRequest(XtermWidget xw, String buf, int final) 2594cd3331d0Smrg{ 2595cd3331d0Smrg if (AllowFontOps(xw, efGetFont)) { 2596cd3331d0Smrg TScreen *screen = TScreenOf(xw); 2597cd3331d0Smrg Bool success = True; 2598cd3331d0Smrg int num; 2599cb4a1343Smrg String base = buf + 1; 2600cd3331d0Smrg const char *name = 0; 2601cd3331d0Smrg char temp[10]; 2602cd3331d0Smrg 2603cd3331d0Smrg num = ParseShiftedFont(xw, buf, &buf); 2604cd3331d0Smrg if (num < 0 2605cd3331d0Smrg || num > fontMenu_lastBuiltin) { 2606cd3331d0Smrg Bell(xw, XkbBI_MinorError, 0); 2607cd3331d0Smrg success = False; 2608cd3331d0Smrg } else { 2609cd3331d0Smrg#if OPT_RENDERFONT 2610cd3331d0Smrg if (UsingRenderFont(xw)) { 2611cd3331d0Smrg name = getFaceName(xw, False); 2612cd3331d0Smrg } else 2613cd3331d0Smrg#endif 2614cd3331d0Smrg if ((name = screen->MenuFontName(num)) == 0) { 2615cd3331d0Smrg success = False; 2616cd3331d0Smrg } 2617cd3331d0Smrg } 2618cd3331d0Smrg 2619cd3331d0Smrg unparseputc1(xw, ANSI_OSC); 2620cd3331d0Smrg unparseputs(xw, "50"); 2621cd3331d0Smrg 2622cd3331d0Smrg if (success) { 2623cd3331d0Smrg unparseputc(xw, ';'); 2624cd3331d0Smrg if (buf >= base) { 2625cd3331d0Smrg /* identify the font-entry, unless it is the current one */ 2626cd3331d0Smrg if (*buf != '\0') { 2627cd3331d0Smrg unparseputc(xw, '#'); 2628cd3331d0Smrg sprintf(temp, "%d", num); 2629cd3331d0Smrg unparseputs(xw, temp); 2630cd3331d0Smrg if (*name != '\0') 2631cd3331d0Smrg unparseputc(xw, ' '); 2632cd3331d0Smrg } 2633cd3331d0Smrg } 2634cd3331d0Smrg unparseputs(xw, name); 2635cd3331d0Smrg } 2636cd3331d0Smrg 2637cd3331d0Smrg unparseputc1(xw, final); 2638cd3331d0Smrg unparse_end(xw); 2639cd3331d0Smrg } 2640cd3331d0Smrg} 2641cd3331d0Smrg 2642cd3331d0Smrgstatic void 2643cb4a1343SmrgChangeFontRequest(XtermWidget xw, String buf) 2644cd3331d0Smrg{ 2645cd3331d0Smrg if (AllowFontOps(xw, efSetFont)) { 2646cd3331d0Smrg TScreen *screen = TScreenOf(xw); 2647cd3331d0Smrg Bool success = True; 2648cd3331d0Smrg int num; 2649cd3331d0Smrg VTFontNames fonts; 2650cd3331d0Smrg char *name; 2651cd3331d0Smrg 2652cd3331d0Smrg /* 2653cd3331d0Smrg * If the font specification is a "#", followed by an optional sign and 2654cd3331d0Smrg * optional number, lookup the corresponding menu font entry. 2655cd3331d0Smrg * 2656cd3331d0Smrg * Further, if the "#", etc., is followed by a font name, use that 2657cd3331d0Smrg * to load the font entry. 2658cd3331d0Smrg */ 2659cd3331d0Smrg if (*buf == '#') { 2660cd3331d0Smrg num = ParseShiftedFont(xw, buf, &buf); 2661cd3331d0Smrg 2662cd3331d0Smrg if (num < 0 2663cd3331d0Smrg || num > fontMenu_lastBuiltin) { 2664cd3331d0Smrg Bell(xw, XkbBI_MinorError, 0); 2665cd3331d0Smrg success = False; 2666cd3331d0Smrg } else { 2667cd3331d0Smrg /* 2668cd3331d0Smrg * Skip past the optional number, and any whitespace to look 2669cd3331d0Smrg * for a font specification within the control. 2670cd3331d0Smrg */ 2671cd3331d0Smrg while (isdigit(CharOf(*buf))) { 2672cd3331d0Smrg ++buf; 2673cd3331d0Smrg } 2674cd3331d0Smrg while (isspace(CharOf(*buf))) { 2675cd3331d0Smrg ++buf; 2676cd3331d0Smrg } 2677cd3331d0Smrg#if OPT_RENDERFONT 2678cd3331d0Smrg if (UsingRenderFont(xw)) { 2679c219fbebSmrg /* EMPTY */ 2680c219fbebSmrg /* there is only one font entry to load */ 2681c219fbebSmrg ; 2682cd3331d0Smrg } else 2683cd3331d0Smrg#endif 2684cd3331d0Smrg { 2685cd3331d0Smrg /* 2686cd3331d0Smrg * Normally there is no font specified in the control. 2687cd3331d0Smrg * But if there is, simply overwrite the font entry. 2688cd3331d0Smrg */ 2689cd3331d0Smrg if (*buf == '\0') { 2690cd3331d0Smrg if ((buf = screen->MenuFontName(num)) == 0) { 2691cd3331d0Smrg success = False; 2692cd3331d0Smrg } 2693cd3331d0Smrg } 2694cd3331d0Smrg } 2695cd3331d0Smrg } 2696cd3331d0Smrg } else { 2697cd3331d0Smrg num = screen->menu_font_number; 2698cd3331d0Smrg } 2699cd3331d0Smrg name = x_strtrim(buf); 2700cd3331d0Smrg if (success && !IsEmpty(name)) { 2701cd3331d0Smrg#if OPT_RENDERFONT 2702cd3331d0Smrg if (UsingRenderFont(xw)) { 2703cd3331d0Smrg setFaceName(xw, name); 2704cd3331d0Smrg xtermUpdateFontInfo(xw, True); 2705cd3331d0Smrg } else 2706cd3331d0Smrg#endif 2707cd3331d0Smrg { 2708cd3331d0Smrg memset(&fonts, 0, sizeof(fonts)); 2709cd3331d0Smrg fonts.f_n = name; 2710cd3331d0Smrg SetVTFont(xw, num, True, &fonts); 2711cd3331d0Smrg } 2712cd3331d0Smrg } else { 2713cd3331d0Smrg Bell(xw, XkbBI_MinorError, 0); 2714cd3331d0Smrg } 2715cd3331d0Smrg free(name); 2716cd3331d0Smrg } 2717cd3331d0Smrg} 2718cd3331d0Smrg#endif /* OPT_SHIFT_FONTS */ 2719cd3331d0Smrg 2720d522f475Smrg/***====================================================================***/ 2721d522f475Smrg 2722d522f475Smrgvoid 2723cd3331d0Smrgdo_osc(XtermWidget xw, Char * oscbuf, size_t len, int final) 2724d522f475Smrg{ 2725cd3331d0Smrg TScreen *screen = TScreenOf(xw); 2726d522f475Smrg int mode; 2727d522f475Smrg Char *cp; 2728d522f475Smrg int state = 0; 2729d522f475Smrg char *buf = 0; 2730cd3331d0Smrg char temp[2]; 2731cd3331d0Smrg#if OPT_ISO_COLORS 2732cd3331d0Smrg int ansi_colors = 0; 2733cd3331d0Smrg#endif 2734cd3331d0Smrg Bool need_data = True; 2735d522f475Smrg 2736d522f475Smrg TRACE(("do_osc %s\n", oscbuf)); 2737d522f475Smrg 2738d522f475Smrg /* 2739d522f475Smrg * Lines should be of the form <OSC> number ; string <ST>, however 2740d522f475Smrg * older xterms can accept <BEL> as a final character. We will respond 2741d522f475Smrg * with the same final character as the application sends to make this 2742d522f475Smrg * work better with shell scripts, which may have trouble reading an 2743d522f475Smrg * <ESC><backslash>, which is the 7-bit equivalent to <ST>. 2744d522f475Smrg */ 2745d522f475Smrg mode = 0; 2746d522f475Smrg for (cp = oscbuf; *cp != '\0'; cp++) { 2747d522f475Smrg switch (state) { 2748d522f475Smrg case 0: 2749d522f475Smrg if (isdigit(*cp)) { 2750d522f475Smrg mode = 10 * mode + (*cp - '0'); 2751d522f475Smrg if (mode > 65535) { 2752d522f475Smrg TRACE(("do_osc found unknown mode %d\n", mode)); 2753d522f475Smrg return; 2754d522f475Smrg } 2755d522f475Smrg break; 2756d522f475Smrg } 2757d522f475Smrg /* FALLTHRU */ 2758d522f475Smrg case 1: 2759d522f475Smrg if (*cp != ';') { 2760cd3331d0Smrg TRACE(("do_osc did not find semicolon offset %d\n", 2761cd3331d0Smrg (int) (cp - oscbuf))); 2762d522f475Smrg return; 2763d522f475Smrg } 2764d522f475Smrg state = 2; 2765d522f475Smrg break; 2766d522f475Smrg case 2: 2767d522f475Smrg buf = (char *) cp; 2768d522f475Smrg state = 3; 2769d522f475Smrg /* FALLTHRU */ 2770d522f475Smrg default: 2771cd3331d0Smrg if (!xtermIsPrintable(xw, &cp, oscbuf + len)) { 2772d522f475Smrg switch (mode) { 2773d522f475Smrg case 0: 2774d522f475Smrg case 1: 2775d522f475Smrg case 2: 2776d522f475Smrg break; 2777d522f475Smrg default: 2778d522f475Smrg TRACE(("do_osc found nonprinting char %02X offset %d\n", 2779d522f475Smrg CharOf(*cp), 2780cd3331d0Smrg (int) (cp - oscbuf))); 2781d522f475Smrg return; 2782d522f475Smrg } 2783d522f475Smrg } 2784d522f475Smrg } 2785d522f475Smrg } 2786cd3331d0Smrg 2787cd3331d0Smrg /* 2788cd3331d0Smrg * Most OSC controls other than resets require data. Handle the others as 2789cd3331d0Smrg * a special case. 2790cd3331d0Smrg */ 2791cd3331d0Smrg switch (mode) { 2792cd3331d0Smrg#if OPT_ISO_COLORS 2793cd3331d0Smrg case OSC_Reset(4): 2794cd3331d0Smrg case OSC_Reset(5): 2795cd3331d0Smrg case OSC_Reset(OSC_TEXT_FG): 2796cd3331d0Smrg case OSC_Reset(OSC_TEXT_BG): 2797cd3331d0Smrg case OSC_Reset(OSC_TEXT_CURSOR): 2798cd3331d0Smrg case OSC_Reset(OSC_MOUSE_FG): 2799cd3331d0Smrg case OSC_Reset(OSC_MOUSE_BG): 2800cd3331d0Smrg#if OPT_HIGHLIGHT_COLOR 2801cd3331d0Smrg case OSC_Reset(OSC_HIGHLIGHT_BG): 2802cd3331d0Smrg case OSC_Reset(OSC_HIGHLIGHT_FG): 2803cd3331d0Smrg#endif 2804cd3331d0Smrg#if OPT_TEK4014 2805cd3331d0Smrg case OSC_Reset(OSC_TEK_FG): 2806cd3331d0Smrg case OSC_Reset(OSC_TEK_BG): 2807cd3331d0Smrg case OSC_Reset(OSC_TEK_CURSOR): 2808cd3331d0Smrg#endif 2809cd3331d0Smrg need_data = False; 2810cd3331d0Smrg break; 2811cd3331d0Smrg#endif 2812cd3331d0Smrg default: 2813cd3331d0Smrg break; 2814cd3331d0Smrg } 2815cd3331d0Smrg 2816cd3331d0Smrg /* 2817cd3331d0Smrg * Check if we have data when we want, and not when we do not want it. 2818cd3331d0Smrg * Either way, that is a malformed control sequence, and will be ignored. 2819cd3331d0Smrg */ 2820cd3331d0Smrg if (IsEmpty(buf)) { 2821cd3331d0Smrg if (need_data) { 2822cd3331d0Smrg TRACE(("do_osc found no data\n")); 2823cd3331d0Smrg return; 2824cd3331d0Smrg } 2825cd3331d0Smrg temp[0] = '\0'; 2826cd3331d0Smrg buf = temp; 2827cd3331d0Smrg } else if (!need_data) { 2828cd3331d0Smrg TRACE(("do_osc found found unwanted data\n")); 2829d522f475Smrg return; 28300d92cbfdSchristos } 2831d522f475Smrg 2832d522f475Smrg switch (mode) { 2833d522f475Smrg case 0: /* new icon name and title */ 2834b7c89284Ssnj ChangeIconName(xw, buf); 2835b7c89284Ssnj ChangeTitle(xw, buf); 2836d522f475Smrg break; 2837d522f475Smrg 2838d522f475Smrg case 1: /* new icon name only */ 2839b7c89284Ssnj ChangeIconName(xw, buf); 2840d522f475Smrg break; 2841d522f475Smrg 2842d522f475Smrg case 2: /* new title only */ 2843b7c89284Ssnj ChangeTitle(xw, buf); 2844d522f475Smrg break; 2845d522f475Smrg 284622d8e007Schristos#ifdef notdef 2847d522f475Smrg case 3: /* change X property */ 2848cd3331d0Smrg if (AllowWindowOps(xw, ewSetXprop)) 28490d92cbfdSchristos ChangeXprop(buf); 2850d522f475Smrg break; 285122d8e007Schristos#endif 2852d522f475Smrg#if OPT_ISO_COLORS 2853cd3331d0Smrg case 5: 2854cd3331d0Smrg ansi_colors = NUM_ANSI_COLORS; 2855cd3331d0Smrg /* FALLTHRU */ 2856d522f475Smrg case 4: 2857cd3331d0Smrg if (ChangeAnsiColorRequest(xw, buf, ansi_colors, final)) 2858cd3331d0Smrg xtermRepaint(xw); 2859cd3331d0Smrg break; 2860cd3331d0Smrg case OSC_Reset(5): 2861cd3331d0Smrg ansi_colors = NUM_ANSI_COLORS; 2862cd3331d0Smrg /* FALLTHRU */ 2863cd3331d0Smrg case OSC_Reset(4): 2864cd3331d0Smrg if (ResetAnsiColorRequest(xw, buf, ansi_colors)) 2865cd3331d0Smrg xtermRepaint(xw); 2866d522f475Smrg break; 2867d522f475Smrg#endif 2868d522f475Smrg case OSC_TEXT_FG: 2869d522f475Smrg case OSC_TEXT_BG: 2870d522f475Smrg case OSC_TEXT_CURSOR: 2871d522f475Smrg case OSC_MOUSE_FG: 2872d522f475Smrg case OSC_MOUSE_BG: 2873d522f475Smrg#if OPT_HIGHLIGHT_COLOR 2874d522f475Smrg case OSC_HIGHLIGHT_BG: 2875cd3331d0Smrg case OSC_HIGHLIGHT_FG: 2876d522f475Smrg#endif 2877d522f475Smrg#if OPT_TEK4014 2878d522f475Smrg case OSC_TEK_FG: 2879d522f475Smrg case OSC_TEK_BG: 2880d522f475Smrg case OSC_TEK_CURSOR: 2881d522f475Smrg#endif 2882cd3331d0Smrg if (xw->misc.dynamicColors) { 2883d522f475Smrg ChangeColorsRequest(xw, mode, buf, final); 2884cd3331d0Smrg } 2885cd3331d0Smrg break; 2886cd3331d0Smrg case OSC_Reset(OSC_TEXT_FG): 2887cd3331d0Smrg case OSC_Reset(OSC_TEXT_BG): 2888cd3331d0Smrg case OSC_Reset(OSC_TEXT_CURSOR): 2889cd3331d0Smrg case OSC_Reset(OSC_MOUSE_FG): 2890cd3331d0Smrg case OSC_Reset(OSC_MOUSE_BG): 2891cd3331d0Smrg#if OPT_HIGHLIGHT_COLOR 2892cd3331d0Smrg case OSC_Reset(OSC_HIGHLIGHT_BG): 2893cd3331d0Smrg case OSC_Reset(OSC_HIGHLIGHT_FG): 2894cd3331d0Smrg#endif 2895cd3331d0Smrg#if OPT_TEK4014 2896cd3331d0Smrg case OSC_Reset(OSC_TEK_FG): 2897cd3331d0Smrg case OSC_Reset(OSC_TEK_BG): 2898cd3331d0Smrg case OSC_Reset(OSC_TEK_CURSOR): 2899cd3331d0Smrg#endif 2900cd3331d0Smrg if (xw->misc.dynamicColors) { 2901cd3331d0Smrg ResetColorsRequest(xw, mode); 2902cd3331d0Smrg } 2903d522f475Smrg break; 2904d522f475Smrg 2905d522f475Smrg case 30: 2906d522f475Smrg case 31: 2907d522f475Smrg /* reserved for Konsole (Stephan Binner <Stephan.Binner@gmx.de>) */ 2908d522f475Smrg break; 2909d522f475Smrg 2910d522f475Smrg#ifdef ALLOWLOGGING 2911d522f475Smrg case 46: /* new log file */ 2912d522f475Smrg#ifdef ALLOWLOGFILECHANGES 2913d522f475Smrg /* 2914d522f475Smrg * Warning, enabling this feature allows people to overwrite 2915d522f475Smrg * arbitrary files accessible to the person running xterm. 2916d522f475Smrg */ 2917cd3331d0Smrg if (strcmp(buf, "?") 2918d522f475Smrg && (cp = CastMallocN(char, strlen(buf)) != NULL)) { 2919d522f475Smrg strcpy(cp, buf); 2920d522f475Smrg if (screen->logfile) 2921d522f475Smrg free(screen->logfile); 2922d522f475Smrg screen->logfile = cp; 2923d522f475Smrg break; 2924d522f475Smrg } 2925d522f475Smrg#endif 2926cd3331d0Smrg Bell(xw, XkbBI_Info, 0); 2927cd3331d0Smrg Bell(xw, XkbBI_Info, 0); 2928d522f475Smrg break; 2929d522f475Smrg#endif /* ALLOWLOGGING */ 2930d522f475Smrg 2931d522f475Smrg case 50: 2932d522f475Smrg#if OPT_SHIFT_FONTS 2933cd3331d0Smrg if (*buf == '?') { 2934cd3331d0Smrg QueryFontRequest(xw, buf, final); 2935cd3331d0Smrg } else if (xw->misc.shift_fonts) { 2936cd3331d0Smrg ChangeFontRequest(xw, buf); 2937d522f475Smrg } 2938d522f475Smrg#endif /* OPT_SHIFT_FONTS */ 2939d522f475Smrg break; 2940d522f475Smrg case 51: 2941d522f475Smrg /* reserved for Emacs shell (Rob Mayoff <mayoff@dqd.com>) */ 2942d522f475Smrg break; 2943d522f475Smrg 2944d522f475Smrg#if OPT_PASTE64 2945d522f475Smrg case 52: 2946cd3331d0Smrg ManipulateSelectionData(xw, screen, buf, final); 2947d522f475Smrg break; 2948d522f475Smrg#endif 2949d522f475Smrg /* 2950d522f475Smrg * One could write code to send back the display and host names, 2951d522f475Smrg * but that could potentially open a fairly nasty security hole. 2952d522f475Smrg */ 2953cd3331d0Smrg default: 2954cd3331d0Smrg TRACE(("do_osc - unrecognized code\n")); 2955cd3331d0Smrg break; 2956d522f475Smrg } 2957d522f475Smrg unparse_end(xw); 2958d522f475Smrg} 2959d522f475Smrg 2960d522f475Smrg#ifdef SunXK_F36 2961d522f475Smrg#define MAX_UDK 37 2962d522f475Smrg#else 2963d522f475Smrg#define MAX_UDK 35 2964d522f475Smrg#endif 2965d522f475Smrgstatic struct { 2966d522f475Smrg char *str; 2967d522f475Smrg int len; 2968d522f475Smrg} user_keys[MAX_UDK]; 2969d522f475Smrg 2970d522f475Smrg/* 2971d522f475Smrg * Parse one nibble of a hex byte from the OSC string. We have removed the 2972d522f475Smrg * string-terminator (replacing it with a null), so the only other delimiter 2973d522f475Smrg * that is expected is semicolon. Ignore other characters (Ray Neuman says 2974d522f475Smrg * "real" terminals accept commas in the string definitions). 2975d522f475Smrg */ 2976d522f475Smrgstatic int 2977cd3331d0Smrgudk_value(const char **cp) 2978d522f475Smrg{ 2979cd3331d0Smrg int result = -1; 2980d522f475Smrg int c; 2981d522f475Smrg 2982d522f475Smrg for (;;) { 2983d522f475Smrg if ((c = **cp) != '\0') 2984d522f475Smrg *cp = *cp + 1; 2985d522f475Smrg if (c == ';' || c == '\0') 2986cd3331d0Smrg break; 2987cd3331d0Smrg if ((result = x_hex2int(c)) >= 0) 2988cd3331d0Smrg break; 2989d522f475Smrg } 2990cd3331d0Smrg 2991cd3331d0Smrg return result; 2992d522f475Smrg} 2993d522f475Smrg 2994d522f475Smrgvoid 2995d522f475Smrgreset_decudk(void) 2996d522f475Smrg{ 2997d522f475Smrg int n; 2998d522f475Smrg for (n = 0; n < MAX_UDK; n++) { 2999d522f475Smrg if (user_keys[n].str != 0) { 3000d522f475Smrg free(user_keys[n].str); 3001d522f475Smrg user_keys[n].str = 0; 3002d522f475Smrg user_keys[n].len = 0; 3003d522f475Smrg } 3004d522f475Smrg } 3005d522f475Smrg} 3006d522f475Smrg 3007d522f475Smrg/* 3008d522f475Smrg * Parse the data for DECUDK (user-defined keys). 3009d522f475Smrg */ 3010d522f475Smrgstatic void 3011cd3331d0Smrgparse_decudk(const char *cp) 3012d522f475Smrg{ 3013d522f475Smrg while (*cp) { 3014cd3331d0Smrg const char *base = cp; 3015d522f475Smrg char *str = CastMallocN(char, strlen(cp) + 1); 3016d522f475Smrg unsigned key = 0; 3017d522f475Smrg int lo, hi; 3018d522f475Smrg int len = 0; 3019d522f475Smrg 3020d522f475Smrg while (isdigit(CharOf(*cp))) 30210d92cbfdSchristos key = (key * 10) + (unsigned) (*cp++ - '0'); 3022d522f475Smrg if (*cp == '/') { 3023d522f475Smrg cp++; 3024d522f475Smrg while ((hi = udk_value(&cp)) >= 0 3025d522f475Smrg && (lo = udk_value(&cp)) >= 0) { 30260d92cbfdSchristos str[len++] = (char) ((hi << 4) | lo); 3027d522f475Smrg } 3028d522f475Smrg } 3029d522f475Smrg if (len > 0 && key < MAX_UDK) { 3030d522f475Smrg if (user_keys[key].str != 0) 3031d522f475Smrg free(user_keys[key].str); 3032d522f475Smrg user_keys[key].str = str; 3033d522f475Smrg user_keys[key].len = len; 3034d522f475Smrg } else { 3035d522f475Smrg free(str); 3036d522f475Smrg } 3037d522f475Smrg if (*cp == ';') 3038d522f475Smrg cp++; 3039d522f475Smrg if (cp == base) /* badly-formed sequence - bail out */ 3040d522f475Smrg break; 3041d522f475Smrg } 3042d522f475Smrg} 3043d522f475Smrg 3044d522f475Smrg#if OPT_TRACE 3045d522f475Smrg#define SOFT_WIDE 10 3046d522f475Smrg#define SOFT_HIGH 20 3047d522f475Smrg 3048d522f475Smrgstatic void 3049cd3331d0Smrgparse_decdld(ANSI * params, const char *string) 3050d522f475Smrg{ 3051d522f475Smrg char DscsName[8]; 3052d522f475Smrg int len; 3053d522f475Smrg int Pfn = params->a_param[0]; 3054d522f475Smrg int Pcn = params->a_param[1]; 3055d522f475Smrg int Pe = params->a_param[2]; 3056d522f475Smrg int Pcmw = params->a_param[3]; 3057d522f475Smrg int Pw = params->a_param[4]; 3058d522f475Smrg int Pt = params->a_param[5]; 3059d522f475Smrg int Pcmh = params->a_param[6]; 3060d522f475Smrg int Pcss = params->a_param[7]; 3061d522f475Smrg 3062d522f475Smrg int start_char = Pcn + 0x20; 3063d522f475Smrg int char_wide = ((Pcmw == 0) 3064d522f475Smrg ? (Pcss ? 6 : 10) 3065d522f475Smrg : (Pcmw > 4 3066d522f475Smrg ? Pcmw 3067d522f475Smrg : (Pcmw + 3))); 3068d522f475Smrg int char_high = ((Pcmh == 0) 3069d522f475Smrg ? ((Pcmw >= 2 || Pcmw <= 4) 3070d522f475Smrg ? 10 3071d522f475Smrg : 20) 3072d522f475Smrg : Pcmh); 3073d522f475Smrg Char ch; 3074d522f475Smrg Char bits[SOFT_HIGH][SOFT_WIDE]; 3075d522f475Smrg Bool first = True; 3076d522f475Smrg Bool prior = False; 3077d522f475Smrg int row = 0, col = 0; 3078d522f475Smrg 3079d522f475Smrg TRACE(("Parsing DECDLD\n")); 3080d522f475Smrg TRACE((" font number %d\n", Pfn)); 3081d522f475Smrg TRACE((" starting char %d\n", Pcn)); 3082d522f475Smrg TRACE((" erase control %d\n", Pe)); 3083d522f475Smrg TRACE((" char-width %d\n", Pcmw)); 3084d522f475Smrg TRACE((" font-width %d\n", Pw)); 3085d522f475Smrg TRACE((" text/full %d\n", Pt)); 3086d522f475Smrg TRACE((" char-height %d\n", Pcmh)); 3087d522f475Smrg TRACE((" charset-size %d\n", Pcss)); 3088d522f475Smrg 3089d522f475Smrg if (Pfn > 1 3090d522f475Smrg || Pcn > 95 3091d522f475Smrg || Pe > 2 3092d522f475Smrg || Pcmw > 10 3093d522f475Smrg || Pcmw == 1 3094d522f475Smrg || Pt > 2 3095d522f475Smrg || Pcmh > 20 3096d522f475Smrg || Pcss > 1 3097d522f475Smrg || char_wide > SOFT_WIDE 3098d522f475Smrg || char_high > SOFT_HIGH) { 3099d522f475Smrg TRACE(("DECDLD illegal parameter\n")); 3100d522f475Smrg return; 3101d522f475Smrg } 3102d522f475Smrg 3103d522f475Smrg len = 0; 3104d522f475Smrg while (*string != '\0') { 3105d522f475Smrg ch = CharOf(*string++); 3106d522f475Smrg if (ch >= ANSI_SPA && ch <= 0x2f) { 3107d522f475Smrg if (len < 2) 3108b7c89284Ssnj DscsName[len++] = (char) ch; 3109d522f475Smrg } else if (ch >= 0x30 && ch <= 0x7e) { 3110b7c89284Ssnj DscsName[len++] = (char) ch; 3111d522f475Smrg break; 3112d522f475Smrg } 3113d522f475Smrg } 3114d522f475Smrg DscsName[len] = 0; 3115d522f475Smrg TRACE((" Dscs name '%s'\n", DscsName)); 3116d522f475Smrg 3117d522f475Smrg TRACE((" character matrix %dx%d\n", char_high, char_wide)); 3118d522f475Smrg while (*string != '\0') { 3119d522f475Smrg if (first) { 3120d522f475Smrg TRACE(("Char %d:\n", start_char)); 3121d522f475Smrg if (prior) { 3122d522f475Smrg for (row = 0; row < char_high; ++row) { 3123d522f475Smrg TRACE(("%.*s\n", char_wide, bits[row])); 3124d522f475Smrg } 3125d522f475Smrg } 3126d522f475Smrg prior = False; 3127d522f475Smrg first = False; 3128d522f475Smrg for (row = 0; row < char_high; ++row) { 3129d522f475Smrg for (col = 0; col < char_wide; ++col) { 3130d522f475Smrg bits[row][col] = '.'; 3131d522f475Smrg } 3132d522f475Smrg } 3133d522f475Smrg row = col = 0; 3134d522f475Smrg } 3135d522f475Smrg ch = CharOf(*string++); 3136d522f475Smrg if (ch >= 0x3f && ch <= 0x7e) { 3137d522f475Smrg int n; 3138d522f475Smrg 3139b7c89284Ssnj ch = CharOf(ch - 0x3f); 3140d522f475Smrg for (n = 0; n < 6; ++n) { 3141b7c89284Ssnj bits[row + n][col] = CharOf((ch & (1 << n)) ? '*' : '.'); 3142d522f475Smrg } 3143d522f475Smrg col += 1; 3144d522f475Smrg prior = True; 3145d522f475Smrg } else if (ch == '/') { 3146d522f475Smrg row += 6; 3147d522f475Smrg col = 0; 3148d522f475Smrg } else if (ch == ';') { 3149d522f475Smrg first = True; 3150d522f475Smrg ++start_char; 3151d522f475Smrg } 3152d522f475Smrg } 3153d522f475Smrg} 3154d522f475Smrg#else 3155d522f475Smrg#define parse_decdld(p,q) /* nothing */ 3156d522f475Smrg#endif 3157d522f475Smrg 3158d522f475Smrg/* 3159d522f475Smrg * Parse numeric parameters. Normally we use a state machine to simplify 3160d522f475Smrg * interspersing with control characters, but have the string already. 3161d522f475Smrg */ 3162d522f475Smrgstatic void 3163cd3331d0Smrgparse_ansi_params(ANSI * params, const char **string) 3164d522f475Smrg{ 3165cd3331d0Smrg const char *cp = *string; 3166b7c89284Ssnj ParmType nparam = 0; 3167d522f475Smrg 3168d522f475Smrg memset(params, 0, sizeof(*params)); 3169d522f475Smrg while (*cp != '\0') { 3170d522f475Smrg Char ch = CharOf(*cp++); 3171d522f475Smrg 3172d522f475Smrg if (isdigit(ch)) { 3173d522f475Smrg if (nparam < NPARAM) { 3174b7c89284Ssnj params->a_param[nparam] = 3175b7c89284Ssnj (ParmType) ((params->a_param[nparam] * 10) 3176b7c89284Ssnj + (ch - '0')); 3177d522f475Smrg } 3178d522f475Smrg } else if (ch == ';') { 3179d522f475Smrg if (++nparam < NPARAM) 3180d522f475Smrg params->a_nparam = nparam; 3181d522f475Smrg } else if (ch < 32) { 3182c219fbebSmrg /* EMPTY */ ; 3183d522f475Smrg } else { 3184d522f475Smrg /* should be 0x30 to 0x7e */ 3185d522f475Smrg params->a_final = ch; 3186d522f475Smrg break; 3187d522f475Smrg } 3188d522f475Smrg } 3189d522f475Smrg *string = cp; 3190d522f475Smrg} 3191d522f475Smrg 3192d522f475Smrgvoid 3193d522f475Smrgdo_dcs(XtermWidget xw, Char * dcsbuf, size_t dcslen) 3194d522f475Smrg{ 3195cd3331d0Smrg TScreen *screen = TScreenOf(xw); 3196d522f475Smrg char reply[BUFSIZ]; 3197cd3331d0Smrg const char *cp = (const char *) dcsbuf; 3198d522f475Smrg Bool okay; 3199d522f475Smrg ANSI params; 3200d522f475Smrg 3201cd3331d0Smrg TRACE(("do_dcs(%s:%lu)\n", (char *) dcsbuf, (unsigned long) dcslen)); 3202d522f475Smrg 3203d522f475Smrg if (dcslen != strlen(cp)) 3204d522f475Smrg /* shouldn't have nulls in the string */ 3205d522f475Smrg return; 3206d522f475Smrg 3207d522f475Smrg switch (*cp) { /* intermediate character, or parameter */ 3208d522f475Smrg case '$': /* DECRQSS */ 3209d522f475Smrg okay = True; 3210d522f475Smrg 3211d522f475Smrg cp++; 3212d522f475Smrg if (*cp++ == 'q') { 3213d522f475Smrg if (!strcmp(cp, "\"q")) { /* DECSCA */ 3214d522f475Smrg sprintf(reply, "%d%s", 3215d522f475Smrg (screen->protected_mode == DEC_PROTECT) 3216d522f475Smrg && (xw->flags & PROTECTED) ? 1 : 0, 3217d522f475Smrg cp); 3218d522f475Smrg } else if (!strcmp(cp, "\"p")) { /* DECSCL */ 3219d522f475Smrg sprintf(reply, "%d%s%s", 3220d522f475Smrg (screen->vtXX_level ? 3221d522f475Smrg screen->vtXX_level : 1) + 60, 3222d522f475Smrg (screen->vtXX_level >= 2) 3223d522f475Smrg ? (screen->control_eight_bits 3224d522f475Smrg ? ";0" : ";1") 3225d522f475Smrg : "", 3226d522f475Smrg cp); 3227d522f475Smrg } else if (!strcmp(cp, "r")) { /* DECSTBM */ 3228d522f475Smrg sprintf(reply, "%d;%dr", 3229d522f475Smrg screen->top_marg + 1, 3230d522f475Smrg screen->bot_marg + 1); 3231d522f475Smrg } else if (!strcmp(cp, "m")) { /* SGR */ 3232d522f475Smrg strcpy(reply, "0"); 3233d522f475Smrg if (xw->flags & BOLD) 3234d522f475Smrg strcat(reply, ";1"); 3235d522f475Smrg if (xw->flags & UNDERLINE) 3236d522f475Smrg strcat(reply, ";4"); 3237d522f475Smrg if (xw->flags & BLINK) 3238d522f475Smrg strcat(reply, ";5"); 3239d522f475Smrg if (xw->flags & INVERSE) 3240d522f475Smrg strcat(reply, ";7"); 3241d522f475Smrg if (xw->flags & INVISIBLE) 3242d522f475Smrg strcat(reply, ";8"); 3243b7c89284Ssnj#if OPT_256_COLORS || OPT_88_COLORS 3244b7c89284Ssnj if_OPT_ISO_COLORS(screen, { 3245d522f475Smrg if (xw->flags & FG_COLOR) { 3246d522f475Smrg if (xw->cur_foreground >= 16) 3247d522f475Smrg sprintf(reply + strlen(reply), 3248d522f475Smrg ";38;5;%d", xw->cur_foreground); 3249d522f475Smrg else 3250d522f475Smrg sprintf(reply + strlen(reply), 3251d522f475Smrg ";%d%d", 3252d522f475Smrg xw->cur_foreground >= 8 ? 9 : 3, 3253d522f475Smrg xw->cur_foreground >= 8 ? 3254d522f475Smrg xw->cur_foreground - 8 : 3255d522f475Smrg xw->cur_foreground); 3256d522f475Smrg } 3257d522f475Smrg if (xw->flags & BG_COLOR) { 3258d522f475Smrg if (xw->cur_background >= 16) 3259d522f475Smrg sprintf(reply + strlen(reply), 3260d522f475Smrg ";48;5;%d", xw->cur_foreground); 3261d522f475Smrg else 3262d522f475Smrg sprintf(reply + strlen(reply), 3263d522f475Smrg ";%d%d", 3264d522f475Smrg xw->cur_background >= 8 ? 10 : 4, 3265d522f475Smrg xw->cur_background >= 8 ? 3266d522f475Smrg xw->cur_background - 8 : 3267d522f475Smrg xw->cur_background); 3268d522f475Smrg } 3269d522f475Smrg }); 3270b7c89284Ssnj#elif OPT_ISO_COLORS 3271b7c89284Ssnj if_OPT_ISO_COLORS(screen, { 3272d522f475Smrg if (xw->flags & FG_COLOR) 3273d522f475Smrg sprintf(reply + strlen(reply), 3274d522f475Smrg ";%d%d", 3275d522f475Smrg xw->cur_foreground >= 8 ? 9 : 3, 3276d522f475Smrg xw->cur_foreground >= 8 ? 3277d522f475Smrg xw->cur_foreground - 8 : 3278d522f475Smrg xw->cur_foreground); 3279d522f475Smrg if (xw->flags & BG_COLOR) 3280d522f475Smrg sprintf(reply + strlen(reply), 3281d522f475Smrg ";%d%d", 3282d522f475Smrg xw->cur_background >= 8 ? 10 : 4, 3283d522f475Smrg xw->cur_background >= 8 ? 3284d522f475Smrg xw->cur_background - 8 : 3285d522f475Smrg xw->cur_background); 3286d522f475Smrg }); 3287b7c89284Ssnj#endif 3288d522f475Smrg strcat(reply, "m"); 3289d522f475Smrg } else 3290d522f475Smrg okay = False; 3291d522f475Smrg 329222d8e007Schristos if (okay) { 32930d92cbfdSchristos unparseputc1(xw, ANSI_DCS); 32940d92cbfdSchristos unparseputc(xw, okay ? '1' : '0'); 32950d92cbfdSchristos unparseputc(xw, '$'); 32960d92cbfdSchristos unparseputc(xw, 'r'); 3297d522f475Smrg cp = reply; 329822d8e007Schristos unparseputs(xw, cp); 32990d92cbfdSchristos unparseputc1(xw, ANSI_ST); 33000d92cbfdSchristos } else { 33010d92cbfdSchristos unparseputc(xw, ANSI_CAN); 330222d8e007Schristos } 3303d522f475Smrg } else { 3304d522f475Smrg unparseputc(xw, ANSI_CAN); 3305d522f475Smrg } 3306d522f475Smrg break; 3307d522f475Smrg#if OPT_TCAP_QUERY 3308d522f475Smrg case '+': 3309d522f475Smrg cp++; 3310cd3331d0Smrg switch (*cp) { 3311cd3331d0Smrg case 'p': 3312cd3331d0Smrg if (AllowTcapOps(xw, etSetTcap)) { 3313cd3331d0Smrg set_termcap(xw, cp + 1); 3314cd3331d0Smrg } 3315cd3331d0Smrg break; 3316cd3331d0Smrg case 'q': 3317cd3331d0Smrg if (AllowTcapOps(xw, etGetTcap)) { 3318cd3331d0Smrg Bool fkey; 3319cd3331d0Smrg unsigned state; 3320cd3331d0Smrg int code; 3321cd3331d0Smrg const char *tmp; 3322cd3331d0Smrg const char *parsed = ++cp; 3323d522f475Smrg 3324cd3331d0Smrg code = xtermcapKeycode(xw, &parsed, &state, &fkey); 3325d522f475Smrg 3326cd3331d0Smrg unparseputc1(xw, ANSI_DCS); 3327b7c89284Ssnj 3328cd3331d0Smrg unparseputc(xw, code >= 0 ? '1' : '0'); 3329d522f475Smrg 3330cd3331d0Smrg unparseputc(xw, '+'); 3331cd3331d0Smrg unparseputc(xw, 'r'); 3332d522f475Smrg 3333cd3331d0Smrg while (*cp != 0 && (code >= -1)) { 3334cd3331d0Smrg if (cp == parsed) 3335cd3331d0Smrg break; /* no data found, error */ 3336d522f475Smrg 3337cd3331d0Smrg for (tmp = cp; tmp != parsed; ++tmp) 3338cd3331d0Smrg unparseputc(xw, *tmp); 3339d522f475Smrg 3340cd3331d0Smrg if (code >= 0) { 3341cd3331d0Smrg unparseputc(xw, '='); 3342cd3331d0Smrg screen->tc_query_code = code; 3343cd3331d0Smrg screen->tc_query_fkey = fkey; 3344d522f475Smrg#if OPT_ISO_COLORS 3345cd3331d0Smrg /* XK_COLORS is a fake code for the "Co" entry (maximum 3346cd3331d0Smrg * number of colors) */ 3347cd3331d0Smrg if (code == XK_COLORS) { 3348cd3331d0Smrg unparseputn(xw, NUM_ANSI_COLORS); 3349cd3331d0Smrg } else 3350cd3331d0Smrg#endif 3351cd3331d0Smrg if (code == XK_TCAPNAME) { 3352c219fbebSmrg unparseputs(xw, resource.term_name); 3353cd3331d0Smrg } else { 3354cd3331d0Smrg XKeyEvent event; 3355cd3331d0Smrg event.state = state; 3356cd3331d0Smrg Input(xw, &event, False); 3357cd3331d0Smrg } 3358cd3331d0Smrg screen->tc_query_code = -1; 3359cd3331d0Smrg } else { 3360cd3331d0Smrg break; /* no match found, error */ 3361d522f475Smrg } 3362d522f475Smrg 3363d522f475Smrg cp = parsed; 3364cd3331d0Smrg if (*parsed == ';') { 3365cd3331d0Smrg unparseputc(xw, *parsed++); 3366cd3331d0Smrg cp = parsed; 3367cd3331d0Smrg code = xtermcapKeycode(xw, &parsed, &state, &fkey); 3368cd3331d0Smrg } 3369d522f475Smrg } 3370cd3331d0Smrg unparseputc1(xw, ANSI_ST); 3371d522f475Smrg } 3372cd3331d0Smrg break; 3373d522f475Smrg } 3374d522f475Smrg break; 3375d522f475Smrg#endif 3376d522f475Smrg default: 33770d92cbfdSchristos if (screen->terminal_id >= 200) { /* VT220 */ 33780d92cbfdSchristos parse_ansi_params(¶ms, &cp); 33790d92cbfdSchristos switch (params.a_final) { 33800d92cbfdSchristos case '|': /* DECUDK */ 33810d92cbfdSchristos if (params.a_param[0] == 0) 33820d92cbfdSchristos reset_decudk(); 33830d92cbfdSchristos parse_decudk(cp); 33840d92cbfdSchristos break; 33850d92cbfdSchristos case '{': /* DECDLD (no '}' case though) */ 33860d92cbfdSchristos parse_decdld(¶ms, cp); 33870d92cbfdSchristos break; 33880d92cbfdSchristos } 3389d522f475Smrg } 3390d522f475Smrg break; 3391d522f475Smrg } 3392d522f475Smrg unparse_end(xw); 3393d522f475Smrg} 3394d522f475Smrg 3395cb4a1343Smrg#if OPT_DEC_RECTOPS 3396cb4a1343Smrgenum { 3397cb4a1343Smrg mdUnknown = 0, 3398cb4a1343Smrg mdMaybeSet = 1, 3399cb4a1343Smrg mdMaybeReset = 2, 3400cb4a1343Smrg mdAlwaysSet = 3, 3401cb4a1343Smrg mdAlwaysReset = 4 3402cb4a1343Smrg}; 3403cb4a1343Smrg 3404cb4a1343Smrg#define MdBool(bool) ((bool) ? mdMaybeSet : mdMaybeReset) 3405cb4a1343Smrg#define MdFlag(mode,flag) MdBool(xw->keyboard.flags & MODE_KAM) 3406cb4a1343Smrg 3407cb4a1343Smrg/* 3408cb4a1343Smrg * Reply is the same format as the query, with pair of mode/value: 3409cb4a1343Smrg * 0 - not recognized 3410cb4a1343Smrg * 1 - set 3411cb4a1343Smrg * 2 - reset 3412cb4a1343Smrg * 3 - permanently set 3413cb4a1343Smrg * 4 - permanently reset 3414cb4a1343Smrg * Only one mode can be reported at a time. 3415cb4a1343Smrg */ 3416cb4a1343Smrgvoid 3417cb4a1343Smrgdo_rpm(XtermWidget xw, int nparams, int *params) 3418cb4a1343Smrg{ 3419cb4a1343Smrg ANSI reply; 3420cb4a1343Smrg int result = 0; 3421cb4a1343Smrg int count = 0; 3422cb4a1343Smrg 3423cb4a1343Smrg TRACE(("do_rpm %d:%d\n", nparams, params[0])); 3424cb4a1343Smrg memset(&reply, 0, sizeof(reply)); 3425cb4a1343Smrg if (nparams >= 1) { 3426cb4a1343Smrg switch (params[0]) { 3427cb4a1343Smrg case 1: /* GATM */ 3428cb4a1343Smrg result = mdAlwaysReset; 3429cb4a1343Smrg break; 3430cb4a1343Smrg case 2: 3431cb4a1343Smrg result = MdFlag(xw->keyboard.flags, MODE_KAM); 3432cb4a1343Smrg break; 3433cb4a1343Smrg case 3: /* CRM */ 3434cb4a1343Smrg result = mdMaybeReset; 3435cb4a1343Smrg break; 3436cb4a1343Smrg case 4: 3437cb4a1343Smrg result = MdFlag(xw->flags, INSERT); 3438cb4a1343Smrg break; 3439cb4a1343Smrg case 5: /* SRTM */ 3440cb4a1343Smrg case 7: /* VEM */ 3441cb4a1343Smrg case 10: /* HEM */ 3442cb4a1343Smrg case 11: /* PUM */ 3443cb4a1343Smrg result = mdAlwaysReset; 3444cb4a1343Smrg break; 3445cb4a1343Smrg case 12: 3446cb4a1343Smrg result = MdFlag(xw->keyboard.flags, MODE_SRM); 3447cb4a1343Smrg break; 3448cb4a1343Smrg case 13: /* FEAM */ 3449cb4a1343Smrg case 14: /* FETM */ 3450cb4a1343Smrg case 15: /* MATM */ 3451cb4a1343Smrg case 16: /* TTM */ 3452cb4a1343Smrg case 17: /* SATM */ 3453cb4a1343Smrg case 18: /* TSM */ 3454cb4a1343Smrg case 19: /* EBM */ 3455cb4a1343Smrg result = mdAlwaysReset; 3456cb4a1343Smrg break; 3457cb4a1343Smrg case 20: 3458cb4a1343Smrg result = MdFlag(xw->flags, LINEFEED); 3459cb4a1343Smrg break; 3460cb4a1343Smrg } 3461cb4a1343Smrg reply.a_param[count++] = (ParmType) params[0]; 3462cb4a1343Smrg reply.a_param[count++] = (ParmType) result; 3463cb4a1343Smrg } 3464cb4a1343Smrg reply.a_type = ANSI_CSI; 3465cb4a1343Smrg reply.a_nparam = (ParmType) count; 3466cb4a1343Smrg reply.a_inters = '$'; 3467cb4a1343Smrg reply.a_final = 'y'; 3468cb4a1343Smrg unparseseq(xw, &reply); 3469cb4a1343Smrg} 3470cb4a1343Smrg 3471cb4a1343Smrgvoid 3472cb4a1343Smrgdo_decrpm(XtermWidget xw, int nparams, int *params) 3473cb4a1343Smrg{ 3474cb4a1343Smrg ANSI reply; 3475cb4a1343Smrg int result = 0; 3476cb4a1343Smrg int count = 0; 3477cb4a1343Smrg 3478cb4a1343Smrg TRACE(("do_decrpm %d:%d\n", nparams, params[0])); 3479cb4a1343Smrg memset(&reply, 0, sizeof(reply)); 3480cb4a1343Smrg if (nparams >= 1) { 3481cb4a1343Smrg TScreen *screen = TScreenOf(xw); 3482cb4a1343Smrg 3483cb4a1343Smrg switch (params[0]) { 3484cb4a1343Smrg case 1: /* DECCKM */ 3485cb4a1343Smrg result = MdFlag(xw->keyboard.flags, MODE_DECCKM); 3486cb4a1343Smrg break; 3487cb4a1343Smrg case 2: /* DECANM - ANSI/VT52 mode */ 3488cb4a1343Smrg#if OPT_VT52_MODE 3489cb4a1343Smrg result = MdBool(screen->terminal_id >= 100); 3490cb4a1343Smrg#else 3491cb4a1343Smrg result = mdMaybeSet; 3492cb4a1343Smrg#endif 3493cb4a1343Smrg break; 3494cb4a1343Smrg case 3: /* DECCOLM */ 3495cb4a1343Smrg result = MdFlag(xw->flags, IN132COLUMNS); 3496cb4a1343Smrg break; 3497cb4a1343Smrg case 4: /* DECSCLM (slow scroll) */ 3498cb4a1343Smrg result = MdFlag(xw->flags, SMOOTHSCROLL); 3499cb4a1343Smrg break; 3500cb4a1343Smrg case 5: /* DECSCNM */ 3501cb4a1343Smrg result = MdFlag(xw->flags, REVERSE_VIDEO); 3502cb4a1343Smrg break; 3503cb4a1343Smrg case 6: /* DECOM */ 3504cb4a1343Smrg result = MdFlag(xw->flags, ORIGIN); 3505cb4a1343Smrg break; 3506cb4a1343Smrg case 7: /* DECAWM */ 3507cb4a1343Smrg result = MdFlag(xw->flags, WRAPAROUND); 3508cb4a1343Smrg break; 3509cb4a1343Smrg case 8: /* DECARM */ 3510cb4a1343Smrg result = mdAlwaysReset; 3511cb4a1343Smrg break; 3512cb4a1343Smrg case SET_X10_MOUSE: /* X10 mouse */ 3513cb4a1343Smrg result = MdBool(screen->send_mouse_pos == X10_MOUSE); 3514cb4a1343Smrg break; 3515cb4a1343Smrg#if OPT_TOOLBAR 3516cb4a1343Smrg case 10: /* rxvt */ 3517cb4a1343Smrg result = MdBool(resource.toolBar); 3518cb4a1343Smrg break; 3519cb4a1343Smrg#endif 3520cb4a1343Smrg#if OPT_BLINK_CURS 3521cb4a1343Smrg case 12: /* att610: Start/stop blinking cursor */ 3522cb4a1343Smrg result = MdBool(screen->cursor_blink_res); 3523cb4a1343Smrg break; 3524cb4a1343Smrg#endif 3525cb4a1343Smrg case 18: /* DECPFF: print form feed */ 3526cb4a1343Smrg result = MdBool(screen->printer_formfeed); 3527cb4a1343Smrg break; 3528cb4a1343Smrg case 19: /* DECPEX: print extent */ 3529cb4a1343Smrg result = MdBool(screen->printer_extent); 3530cb4a1343Smrg break; 3531cb4a1343Smrg case 25: /* DECTCEM: Show/hide cursor (VT200) */ 3532cb4a1343Smrg result = MdBool(screen->cursor_set); 3533cb4a1343Smrg break; 3534cb4a1343Smrg case 30: /* rxvt */ 3535cb4a1343Smrg result = MdBool(screen->fullVwin.sb_info.width != OFF); 3536cb4a1343Smrg break; 3537cb4a1343Smrg#if OPT_SHIFT_FONTS 3538cb4a1343Smrg case 35: /* rxvt */ 3539cb4a1343Smrg result = MdBool(xw->misc.shift_fonts); 3540cb4a1343Smrg break; 3541cb4a1343Smrg#endif 3542cb4a1343Smrg#if OPT_TEK4014 3543cb4a1343Smrg case 38: /* DECTEK */ 3544cb4a1343Smrg result = MdBool(TEK4014_ACTIVE(xw)); 3545cb4a1343Smrg break; 3546cb4a1343Smrg#endif 3547cb4a1343Smrg case 40: /* 132 column mode */ 3548cb4a1343Smrg result = MdBool(screen->c132); 3549cb4a1343Smrg break; 3550cb4a1343Smrg case 41: /* curses hack */ 3551cb4a1343Smrg result = MdBool(screen->curses); 3552cb4a1343Smrg break; 3553cb4a1343Smrg case 42: /* DECNRCM national charset (VT220) */ 3554cb4a1343Smrg result = MdFlag(xw->flags, NATIONAL); 3555cb4a1343Smrg break; 3556cb4a1343Smrg case 44: /* margin bell */ 3557cb4a1343Smrg result = MdBool(screen->marginbell); 3558cb4a1343Smrg break; 3559cb4a1343Smrg case 45: /* reverse wraparound */ 3560cb4a1343Smrg result = MdFlag(xw->flags, REVERSEWRAP); 3561cb4a1343Smrg break; 3562cb4a1343Smrg#ifdef ALLOWLOGGING 3563cb4a1343Smrg case 46: /* logging */ 3564cb4a1343Smrg#ifdef ALLOWLOGFILEONOFF 3565cb4a1343Smrg result = MdBool(screen->logging); 3566cb4a1343Smrg#endif /* ALLOWLOGFILEONOFF */ 3567cb4a1343Smrg break; 3568cb4a1343Smrg#endif 3569cb4a1343Smrg case 1049: /* alternate buffer & cursor */ 3570cb4a1343Smrg /* FALLTHRU */ 3571cb4a1343Smrg case 1047: 3572cb4a1343Smrg /* FALLTHRU */ 3573cb4a1343Smrg case 47: /* alternate buffer */ 3574cb4a1343Smrg result = MdBool(screen->whichBuf); 3575cb4a1343Smrg break; 3576cb4a1343Smrg case 66: /* DECNKM */ 3577cb4a1343Smrg result = MdFlag(xw->keyboard.flags, MODE_DECKPAM); 3578cb4a1343Smrg break; 3579cb4a1343Smrg case 67: /* DECBKM */ 3580cb4a1343Smrg result = MdFlag(xw->keyboard.flags, MODE_DECBKM); 3581cb4a1343Smrg break; 3582cb4a1343Smrg case SET_VT200_MOUSE: /* xterm bogus sequence */ 3583cb4a1343Smrg result = MdBool(screen->send_mouse_pos == VT200_MOUSE); 3584cb4a1343Smrg break; 3585cb4a1343Smrg case SET_VT200_HIGHLIGHT_MOUSE: /* xterm sequence w/hilite tracking */ 3586cb4a1343Smrg result = MdBool(screen->send_mouse_pos == VT200_HIGHLIGHT_MOUSE); 3587cb4a1343Smrg break; 3588cb4a1343Smrg case SET_BTN_EVENT_MOUSE: 3589cb4a1343Smrg result = MdBool(screen->send_mouse_pos == BTN_EVENT_MOUSE); 3590cb4a1343Smrg break; 3591cb4a1343Smrg case SET_ANY_EVENT_MOUSE: 3592cb4a1343Smrg result = MdBool(screen->send_mouse_pos == ANY_EVENT_MOUSE); 3593cb4a1343Smrg break; 3594cb4a1343Smrg#if OPT_FOCUS_EVENT 3595cb4a1343Smrg case SET_FOCUS_EVENT_MOUSE: 3596cb4a1343Smrg result = MdBool(screen->send_focus_pos); 3597cb4a1343Smrg break; 3598cb4a1343Smrg#endif 3599cb4a1343Smrg case SET_EXT_MODE_MOUSE: 3600cb4a1343Smrg result = MdBool(screen->ext_mode_mouse); 3601cb4a1343Smrg break; 3602cb4a1343Smrg case 1010: /* rxvt */ 3603cb4a1343Smrg result = MdBool(screen->scrollttyoutput); 3604cb4a1343Smrg break; 3605cb4a1343Smrg case 1011: /* rxvt */ 3606cb4a1343Smrg result = MdBool(screen->scrollkey); 3607cb4a1343Smrg break; 3608cb4a1343Smrg case 1034: 3609cb4a1343Smrg result = MdBool(screen->input_eight_bits); 3610cb4a1343Smrg break; 3611cb4a1343Smrg#if OPT_NUM_LOCK 3612cb4a1343Smrg case 1035: 3613cb4a1343Smrg result = MdBool(xw->misc.real_NumLock); 3614cb4a1343Smrg break; 3615cb4a1343Smrg case 1036: 3616cb4a1343Smrg result = MdBool(screen->meta_sends_esc); 3617cb4a1343Smrg break; 3618cb4a1343Smrg#endif 3619cb4a1343Smrg case 1037: 3620cb4a1343Smrg result = MdBool(screen->delete_is_del); 3621cb4a1343Smrg break; 3622cb4a1343Smrg#if OPT_NUM_LOCK 3623cb4a1343Smrg case 1039: 3624cb4a1343Smrg result = MdBool(screen->alt_sends_esc); 3625cb4a1343Smrg break; 3626cb4a1343Smrg#endif 3627cb4a1343Smrg case 1040: 3628cb4a1343Smrg result = MdBool(screen->keepSelection); 3629cb4a1343Smrg break; 3630cb4a1343Smrg case 1041: 3631cb4a1343Smrg result = MdBool(screen->selectToClipboard); 3632cb4a1343Smrg break; 3633cb4a1343Smrg case 1042: 3634cb4a1343Smrg result = MdBool(screen->bellIsUrgent); 3635cb4a1343Smrg break; 3636cb4a1343Smrg case 1043: 3637cb4a1343Smrg result = MdBool(screen->poponbell); 3638cb4a1343Smrg break; 3639cb4a1343Smrg case 1048: 3640cb4a1343Smrg result = MdBool(screen->sc[screen->whichBuf].saved); 3641cb4a1343Smrg break; 3642cb4a1343Smrg#if OPT_TCAP_FKEYS 3643cb4a1343Smrg case 1050: 3644cb4a1343Smrg result = MdBool(xw->keyboard.type == keyboardIsTermcap); 3645cb4a1343Smrg break; 3646cb4a1343Smrg#endif 3647cb4a1343Smrg#if OPT_SUN_FUNC_KEYS 3648cb4a1343Smrg case 1051: 3649cb4a1343Smrg result = MdBool(xw->keyboard.type == keyboardIsSun); 3650cb4a1343Smrg break; 3651cb4a1343Smrg#endif 3652cb4a1343Smrg#if OPT_HP_FUNC_KEYS 3653cb4a1343Smrg case 1052: 3654cb4a1343Smrg result = MdBool(xw->keyboard.type == keyboardIsHP); 3655cb4a1343Smrg break; 3656cb4a1343Smrg#endif 3657cb4a1343Smrg#if OPT_SCO_FUNC_KEYS 3658cb4a1343Smrg case 1053: 3659cb4a1343Smrg result = MdBool(xw->keyboard.type == keyboardIsSCO); 3660cb4a1343Smrg break; 3661cb4a1343Smrg#endif 3662cb4a1343Smrg case 1060: 3663cb4a1343Smrg result = MdBool(xw->keyboard.type == keyboardIsLegacy); 3664cb4a1343Smrg break; 3665cb4a1343Smrg#if OPT_SUNPC_KBD 3666cb4a1343Smrg case 1061: 3667cb4a1343Smrg result = MdBool(xw->keyboard.type == keyboardIsVT220); 3668cb4a1343Smrg break; 3669cb4a1343Smrg#endif 3670cb4a1343Smrg#if OPT_READLINE 3671cb4a1343Smrg case SET_BUTTON1_MOVE_POINT: 3672cb4a1343Smrg result = MdBool(screen->click1_moves); 3673cb4a1343Smrg break; 3674cb4a1343Smrg case SET_BUTTON2_MOVE_POINT: 3675cb4a1343Smrg result = MdBool(screen->paste_moves); 3676cb4a1343Smrg break; 3677cb4a1343Smrg case SET_DBUTTON3_DELETE: 3678cb4a1343Smrg result = MdBool(screen->dclick3_deletes); 3679cb4a1343Smrg break; 3680cb4a1343Smrg case SET_PASTE_IN_BRACKET: 3681cb4a1343Smrg result = MdBool(screen->paste_brackets); 3682cb4a1343Smrg break; 3683cb4a1343Smrg case SET_PASTE_QUOTE: 3684cb4a1343Smrg result = MdBool(screen->paste_quotes); 3685cb4a1343Smrg break; 3686cb4a1343Smrg case SET_PASTE_LITERAL_NL: 3687cb4a1343Smrg result = MdBool(screen->paste_literal_nl); 3688cb4a1343Smrg break; 3689cb4a1343Smrg#endif /* OPT_READLINE */ 3690cb4a1343Smrg } 3691cb4a1343Smrg reply.a_param[count++] = (ParmType) params[0]; 3692cb4a1343Smrg reply.a_param[count++] = (ParmType) result; 3693cb4a1343Smrg } 3694cb4a1343Smrg reply.a_type = ANSI_CSI; 3695cb4a1343Smrg reply.a_pintro = '?'; 3696cb4a1343Smrg reply.a_nparam = (ParmType) count; 3697cb4a1343Smrg reply.a_inters = '$'; 3698cb4a1343Smrg reply.a_final = 'y'; 3699cb4a1343Smrg unparseseq(xw, &reply); 3700cb4a1343Smrg} 3701cb4a1343Smrg#endif /* OPT_DEC_RECTOPS */ 3702cb4a1343Smrg 3703d522f475Smrgchar * 3704d522f475Smrgudk_lookup(int keycode, int *len) 3705d522f475Smrg{ 3706d522f475Smrg if (keycode >= 0 && keycode < MAX_UDK) { 3707d522f475Smrg *len = user_keys[keycode].len; 3708d522f475Smrg return user_keys[keycode].str; 3709d522f475Smrg } 3710d522f475Smrg return 0; 3711d522f475Smrg} 3712d522f475Smrg 3713d522f475Smrgstatic void 3714cd3331d0SmrgChangeGroup(XtermWidget xw, const char *attribute, char *value) 3715d522f475Smrg{ 3716d522f475Smrg#if OPT_WIDE_CHARS 3717d522f475Smrg static Char *converted; /* NO_LEAKS */ 3718d522f475Smrg#endif 3719d522f475Smrg static char empty[1]; 3720d522f475Smrg 3721d522f475Smrg Arg args[1]; 3722cd3331d0Smrg Boolean changed = True; 3723d522f475Smrg Widget w = CURRENT_EMU(); 3724d522f475Smrg Widget top = SHELL_OF(w); 3725d522f475Smrg 3726cd3331d0Smrg char *my_attr; 3727cd3331d0Smrg char *name; 3728cd3331d0Smrg size_t limit; 3729cd3331d0Smrg Char *c1; 3730cd3331d0Smrg Char *cp; 3731d522f475Smrg 3732b7c89284Ssnj if (!AllowTitleOps(xw)) 3733d522f475Smrg return; 3734d522f475Smrg 3735cd3331d0Smrg if (value == 0) 3736cd3331d0Smrg value = empty; 3737cd3331d0Smrg if (IsTitleMode(xw, tmSetBase16)) { 3738cd3331d0Smrg const char *temp; 3739cd3331d0Smrg char *test; 3740cd3331d0Smrg 3741cd3331d0Smrg value = x_decode_hex(value, &temp); 3742cd3331d0Smrg if (*temp != '\0') 3743cd3331d0Smrg return; 3744cd3331d0Smrg for (test = value; *test != '\0'; ++test) { 3745cd3331d0Smrg if (CharOf(*test) < 32) { 3746cd3331d0Smrg *test = '\0'; 3747cd3331d0Smrg break; 3748cd3331d0Smrg } 3749cd3331d0Smrg } 3750cd3331d0Smrg } 3751cd3331d0Smrg 3752cd3331d0Smrg c1 = (Char *) value; 3753cd3331d0Smrg name = value; 3754cd3331d0Smrg limit = strlen(name); 3755cd3331d0Smrg my_attr = x_strdup(attribute); 3756cd3331d0Smrg 3757cd3331d0Smrg TRACE(("ChangeGroup(attribute=%s, value=%s)\n", my_attr, name)); 3758cd3331d0Smrg 3759d522f475Smrg /* 3760d522f475Smrg * Ignore titles that are too long to be plausible requests. 3761d522f475Smrg */ 3762cd3331d0Smrg if (limit > 0 && limit < 1024) { 3763d522f475Smrg 3764cd3331d0Smrg /* 3765cd3331d0Smrg * After all decoding, overwrite nonprintable characters with '?'. 3766cd3331d0Smrg */ 3767cd3331d0Smrg for (cp = c1; *cp != 0; ++cp) { 3768cd3331d0Smrg Char *c2 = cp; 3769cd3331d0Smrg if (!xtermIsPrintable(xw, &cp, c1 + limit)) { 3770cd3331d0Smrg memset(c2, '?', (size_t) (cp + 1 - c2)); 3771cd3331d0Smrg } 3772d522f475Smrg } 3773d522f475Smrg 3774d522f475Smrg#if OPT_WIDE_CHARS 3775cd3331d0Smrg /* 3776cd3331d0Smrg * If we're running in UTF-8 mode, and have not been told that the 3777cd3331d0Smrg * title string is in UTF-8, it is likely that non-ASCII text in the 3778cd3331d0Smrg * string will be rejected because it is not printable in the current 3779cd3331d0Smrg * locale. So we convert it to UTF-8, allowing the X library to 3780cd3331d0Smrg * convert it back. 3781cd3331d0Smrg */ 3782cd3331d0Smrg if (xtermEnvUTF8() && !IsSetUtf8Title(xw)) { 3783cd3331d0Smrg int n; 3784cd3331d0Smrg 3785cd3331d0Smrg for (n = 0; name[n] != '\0'; ++n) { 3786cd3331d0Smrg if (CharOf(name[n]) > 127) { 3787cd3331d0Smrg if (converted != 0) 3788cd3331d0Smrg free(converted); 3789cd3331d0Smrg if ((converted = TypeMallocN(Char, 1 + (6 * limit))) != 0) { 3790cd3331d0Smrg Char *temp = converted; 3791cd3331d0Smrg while (*name != 0) { 3792cd3331d0Smrg temp = convertToUTF8(temp, CharOf(*name)); 3793cd3331d0Smrg ++name; 3794cd3331d0Smrg } 3795cd3331d0Smrg *temp = 0; 3796cd3331d0Smrg name = (char *) converted; 3797cd3331d0Smrg TRACE(("...converted{%s}\n", name)); 3798d522f475Smrg } 3799cd3331d0Smrg break; 3800d522f475Smrg } 3801d522f475Smrg } 3802d522f475Smrg } 3803d522f475Smrg#endif 3804d522f475Smrg 3805d522f475Smrg#if OPT_SAME_NAME 3806cd3331d0Smrg /* If the attribute isn't going to change, then don't bother... */ 3807cd3331d0Smrg 3808cd3331d0Smrg if (resource.sameName) { 3809cd3331d0Smrg char *buf = 0; 3810cd3331d0Smrg XtSetArg(args[0], my_attr, &buf); 3811cd3331d0Smrg XtGetValues(top, args, 1); 3812cd3331d0Smrg TRACE(("...comparing{%s}\n", buf)); 3813cd3331d0Smrg if (buf != 0 && strcmp(name, buf) == 0) 3814cd3331d0Smrg changed = False; 3815cd3331d0Smrg } 3816d522f475Smrg#endif /* OPT_SAME_NAME */ 3817d522f475Smrg 3818cd3331d0Smrg if (changed) { 3819cd3331d0Smrg TRACE(("...updating %s\n", my_attr)); 3820cd3331d0Smrg TRACE(("...value is %s\n", name)); 3821cd3331d0Smrg XtSetArg(args[0], my_attr, name); 3822cd3331d0Smrg XtSetValues(top, args, 1); 3823d522f475Smrg 3824d522f475Smrg#if OPT_WIDE_CHARS 3825cd3331d0Smrg if (xtermEnvUTF8()) { 3826cd3331d0Smrg Display *dpy = XtDisplay(xw); 3827cd3331d0Smrg Atom my_atom; 3828cd3331d0Smrg 3829cd3331d0Smrg const char *propname = (!strcmp(my_attr, XtNtitle) 3830cd3331d0Smrg ? "_NET_WM_NAME" 3831cd3331d0Smrg : "_NET_WM_ICON_NAME"); 3832cd3331d0Smrg if ((my_atom = XInternAtom(dpy, propname, False)) != None) { 3833cd3331d0Smrg if (IsSetUtf8Title(xw)) { 3834cd3331d0Smrg TRACE(("...updating %s\n", propname)); 3835cd3331d0Smrg TRACE(("...value is %s\n", value)); 3836c219fbebSmrg XChangeProperty(dpy, VShellWindow(xw), my_atom, 3837cd3331d0Smrg XA_UTF8_STRING(dpy), 8, 3838cd3331d0Smrg PropModeReplace, 3839cd3331d0Smrg (Char *) value, 3840cd3331d0Smrg (int) strlen(value)); 3841cd3331d0Smrg } else { 3842cd3331d0Smrg TRACE(("...deleting %s\n", propname)); 3843c219fbebSmrg XDeleteProperty(dpy, VShellWindow(xw), my_atom); 3844cd3331d0Smrg } 3845cd3331d0Smrg } 3846d522f475Smrg } 3847cd3331d0Smrg#endif 3848d522f475Smrg } 3849cd3331d0Smrg 3850cd3331d0Smrg free(my_attr); 3851cd3331d0Smrg 3852cd3331d0Smrg if (IsTitleMode(xw, tmSetBase16)) 3853cd3331d0Smrg free(value); 3854cd3331d0Smrg 3855d522f475Smrg } 3856cd3331d0Smrg return; 3857d522f475Smrg} 3858d522f475Smrg 3859d522f475Smrgvoid 3860b7c89284SsnjChangeIconName(XtermWidget xw, char *name) 3861d522f475Smrg{ 3862cd3331d0Smrg if (name == 0) { 3863cd3331d0Smrg static char dummy[] = ""; 3864cd3331d0Smrg name = dummy; 3865cd3331d0Smrg } 3866d522f475Smrg#if OPT_ZICONBEEP /* If warning should be given then give it */ 3867cd3331d0Smrg if (resource.zIconBeep && TScreenOf(xw)->zIconBeep_flagged) { 3868d522f475Smrg char *newname = CastMallocN(char, strlen(name) + 4); 3869d522f475Smrg if (!newname) { 3870d522f475Smrg fprintf(stderr, "malloc failed in ChangeIconName\n"); 3871d522f475Smrg return; 3872d522f475Smrg } 3873d522f475Smrg strcpy(newname, "*** "); 3874d522f475Smrg strcat(newname, name); 3875b7c89284Ssnj ChangeGroup(xw, XtNiconName, newname); 3876d522f475Smrg free(newname); 3877d522f475Smrg } else 3878d522f475Smrg#endif /* OPT_ZICONBEEP */ 3879b7c89284Ssnj ChangeGroup(xw, XtNiconName, name); 3880d522f475Smrg} 3881d522f475Smrg 3882d522f475Smrgvoid 3883b7c89284SsnjChangeTitle(XtermWidget xw, char *name) 3884d522f475Smrg{ 3885b7c89284Ssnj ChangeGroup(xw, XtNtitle, name); 3886d522f475Smrg} 3887d522f475Smrg 3888d522f475Smrg#define Strlen(s) strlen((char *)(s)) 3889d522f475Smrg 3890d522f475Smrgvoid 3891d522f475SmrgChangeXprop(char *buf) 3892d522f475Smrg{ 3893d522f475Smrg Display *dpy = XtDisplay(toplevel); 3894d522f475Smrg Window w = XtWindow(toplevel); 3895d522f475Smrg XTextProperty text_prop; 3896d522f475Smrg Atom aprop; 3897d522f475Smrg Char *pchEndPropName = (Char *) strchr(buf, '='); 3898d522f475Smrg 3899d522f475Smrg if (pchEndPropName) 3900d522f475Smrg *pchEndPropName = '\0'; 3901d522f475Smrg aprop = XInternAtom(dpy, buf, False); 3902d522f475Smrg if (pchEndPropName == NULL) { 3903d522f475Smrg /* no "=value" given, so delete the property */ 3904d522f475Smrg XDeleteProperty(dpy, w, aprop); 3905d522f475Smrg } else { 3906d522f475Smrg text_prop.value = pchEndPropName + 1; 3907d522f475Smrg text_prop.encoding = XA_STRING; 3908d522f475Smrg text_prop.format = 8; 3909d522f475Smrg text_prop.nitems = Strlen(text_prop.value); 3910d522f475Smrg XSetTextProperty(dpy, w, &text_prop, aprop); 3911d522f475Smrg } 3912d522f475Smrg} 3913d522f475Smrg 3914d522f475Smrg/***====================================================================***/ 3915d522f475Smrg 3916d522f475Smrg/* 3917d522f475Smrg * This is part of ReverseVideo(). It reverses the data stored for the old 3918d522f475Smrg * "dynamic" colors that might have been retrieved using OSC 10-18. 3919d522f475Smrg */ 3920d522f475Smrgvoid 3921d522f475SmrgReverseOldColors(void) 3922d522f475Smrg{ 3923d522f475Smrg ScrnColors *pOld = pOldColors; 3924d522f475Smrg Pixel tmpPix; 3925d522f475Smrg char *tmpName; 3926d522f475Smrg 3927d522f475Smrg if (pOld) { 3928d522f475Smrg /* change text cursor, if necesary */ 3929d522f475Smrg if (pOld->colors[TEXT_CURSOR] == pOld->colors[TEXT_FG]) { 3930d522f475Smrg pOld->colors[TEXT_CURSOR] = pOld->colors[TEXT_BG]; 3931d522f475Smrg if (pOld->names[TEXT_CURSOR]) { 3932d522f475Smrg XtFree(pOldColors->names[TEXT_CURSOR]); 3933d522f475Smrg pOld->names[TEXT_CURSOR] = NULL; 3934d522f475Smrg } 3935d522f475Smrg if (pOld->names[TEXT_BG]) { 3936d522f475Smrg if ((tmpName = x_strdup(pOld->names[TEXT_BG])) != 0) { 3937d522f475Smrg pOld->names[TEXT_CURSOR] = tmpName; 3938d522f475Smrg } 3939d522f475Smrg } 3940d522f475Smrg } 3941d522f475Smrg 3942d522f475Smrg EXCHANGE(pOld->colors[TEXT_FG], pOld->colors[TEXT_BG], tmpPix); 3943d522f475Smrg EXCHANGE(pOld->names[TEXT_FG], pOld->names[TEXT_BG], tmpName); 3944d522f475Smrg 3945d522f475Smrg EXCHANGE(pOld->colors[MOUSE_FG], pOld->colors[MOUSE_BG], tmpPix); 3946d522f475Smrg EXCHANGE(pOld->names[MOUSE_FG], pOld->names[MOUSE_BG], tmpName); 3947d522f475Smrg 3948d522f475Smrg#if OPT_TEK4014 3949d522f475Smrg EXCHANGE(pOld->colors[TEK_FG], pOld->colors[TEK_BG], tmpPix); 3950d522f475Smrg EXCHANGE(pOld->names[TEK_FG], pOld->names[TEK_BG], tmpName); 3951d522f475Smrg#endif 3952d522f475Smrg } 3953d522f475Smrg return; 3954d522f475Smrg} 3955d522f475Smrg 3956d522f475SmrgBool 3957d522f475SmrgAllocateTermColor(XtermWidget xw, 3958d522f475Smrg ScrnColors * pNew, 3959d522f475Smrg int ndx, 3960cd3331d0Smrg const char *name, 3961cd3331d0Smrg Bool always) 3962d522f475Smrg{ 3963cd3331d0Smrg Bool result = False; 3964d522f475Smrg 3965cd3331d0Smrg if (always || AllowColorOps(xw, ecSetColor)) { 3966cd3331d0Smrg XColor def; 3967cd3331d0Smrg TScreen *screen = TScreenOf(xw); 3968cd3331d0Smrg Colormap cmap = xw->core.colormap; 3969cd3331d0Smrg char *newName; 3970cd3331d0Smrg 3971cd3331d0Smrg if (XParseColor(screen->display, cmap, name, &def) 3972cd3331d0Smrg && (XAllocColor(screen->display, cmap, &def) 3973cd3331d0Smrg || find_closest_color(screen->display, cmap, &def)) 3974cd3331d0Smrg && (newName = x_strdup(name)) != 0) { 3975cd3331d0Smrg if (COLOR_DEFINED(pNew, ndx)) 3976cd3331d0Smrg free(pNew->names[ndx]); 3977cd3331d0Smrg SET_COLOR_VALUE(pNew, ndx, def.pixel); 3978cd3331d0Smrg SET_COLOR_NAME(pNew, ndx, newName); 3979cd3331d0Smrg TRACE(("AllocateTermColor #%d: %s (pixel %#lx)\n", ndx, newName, def.pixel)); 3980cd3331d0Smrg result = True; 3981cd3331d0Smrg } else { 3982cd3331d0Smrg TRACE(("AllocateTermColor #%d: %s (failed)\n", ndx, name)); 3983cd3331d0Smrg } 3984cd3331d0Smrg } 3985cd3331d0Smrg return result; 3986d522f475Smrg} 3987d522f475Smrg/***====================================================================***/ 3988d522f475Smrg 3989d522f475Smrg/* ARGSUSED */ 3990d522f475Smrgvoid 3991cd3331d0SmrgPanic(const char *s GCC_UNUSED, int a GCC_UNUSED) 3992d522f475Smrg{ 3993d522f475Smrg#ifdef DEBUG 3994d522f475Smrg if (debug) { 3995c219fbebSmrg fprintf(stderr, "%s: PANIC!\t", ProgramName); 3996d522f475Smrg fprintf(stderr, s, a); 3997d522f475Smrg fputs("\r\n", stderr); 3998d522f475Smrg fflush(stderr); 3999d522f475Smrg } 4000d522f475Smrg#endif /* DEBUG */ 4001d522f475Smrg} 4002d522f475Smrg 4003d522f475Smrgconst char * 4004d522f475SmrgSysErrorMsg(int code) 4005d522f475Smrg{ 4006d522f475Smrg static char unknown[] = "unknown error"; 4007d522f475Smrg char *s = strerror(code); 4008d522f475Smrg return s ? s : unknown; 4009d522f475Smrg} 4010d522f475Smrg 4011d522f475Smrgconst char * 4012d522f475SmrgSysReasonMsg(int code) 4013d522f475Smrg{ 4014d522f475Smrg /* *INDENT-OFF* */ 4015d522f475Smrg static const struct { 4016d522f475Smrg int code; 4017d522f475Smrg const char *name; 4018d522f475Smrg } table[] = { 4019d522f475Smrg { ERROR_FIONBIO, "main: ioctl() failed on FIONBIO" }, 4020d522f475Smrg { ERROR_F_GETFL, "main: ioctl() failed on F_GETFL" }, 4021d522f475Smrg { ERROR_F_SETFL, "main: ioctl() failed on F_SETFL", }, 4022d522f475Smrg { ERROR_OPDEVTTY, "spawn: open() failed on /dev/tty", }, 4023d522f475Smrg { ERROR_TIOCGETP, "spawn: ioctl() failed on TIOCGETP", }, 4024d522f475Smrg { ERROR_PTSNAME, "spawn: ptsname() failed", }, 4025d522f475Smrg { ERROR_OPPTSNAME, "spawn: open() failed on ptsname", }, 4026d522f475Smrg { ERROR_PTEM, "spawn: ioctl() failed on I_PUSH/\"ptem\"" }, 4027d522f475Smrg { ERROR_CONSEM, "spawn: ioctl() failed on I_PUSH/\"consem\"" }, 4028d522f475Smrg { ERROR_LDTERM, "spawn: ioctl() failed on I_PUSH/\"ldterm\"" }, 4029d522f475Smrg { ERROR_TTCOMPAT, "spawn: ioctl() failed on I_PUSH/\"ttcompat\"" }, 4030d522f475Smrg { ERROR_TIOCSETP, "spawn: ioctl() failed on TIOCSETP" }, 4031d522f475Smrg { ERROR_TIOCSETC, "spawn: ioctl() failed on TIOCSETC" }, 4032d522f475Smrg { ERROR_TIOCSETD, "spawn: ioctl() failed on TIOCSETD" }, 4033d522f475Smrg { ERROR_TIOCSLTC, "spawn: ioctl() failed on TIOCSLTC" }, 4034d522f475Smrg { ERROR_TIOCLSET, "spawn: ioctl() failed on TIOCLSET" }, 4035d522f475Smrg { ERROR_INIGROUPS, "spawn: initgroups() failed" }, 4036d522f475Smrg { ERROR_FORK, "spawn: fork() failed" }, 4037d522f475Smrg { ERROR_EXEC, "spawn: exec() failed" }, 4038d522f475Smrg { ERROR_PTYS, "get_pty: not enough ptys" }, 4039d522f475Smrg { ERROR_PTY_EXEC, "waiting for initial map" }, 4040d522f475Smrg { ERROR_SETUID, "spawn: setuid() failed" }, 4041d522f475Smrg { ERROR_INIT, "spawn: can't initialize window" }, 4042d522f475Smrg { ERROR_TIOCKSET, "spawn: ioctl() failed on TIOCKSET" }, 4043d522f475Smrg { ERROR_TIOCKSETC, "spawn: ioctl() failed on TIOCKSETC" }, 4044d522f475Smrg { ERROR_LUMALLOC, "luit: command-line malloc failed" }, 4045d522f475Smrg { ERROR_SELECT, "in_put: select() failed" }, 4046d522f475Smrg { ERROR_VINIT, "VTInit: can't initialize window" }, 4047d522f475Smrg { ERROR_KMMALLOC1, "HandleKeymapChange: malloc failed" }, 4048d522f475Smrg { ERROR_TSELECT, "Tinput: select() failed" }, 4049d522f475Smrg { ERROR_TINIT, "TekInit: can't initialize window" }, 4050d522f475Smrg { ERROR_BMALLOC2, "SaltTextAway: malloc() failed" }, 4051d522f475Smrg { ERROR_LOGEXEC, "StartLog: exec() failed" }, 4052d522f475Smrg { ERROR_XERROR, "xerror: XError event" }, 4053d522f475Smrg { ERROR_XIOERROR, "xioerror: X I/O error" }, 4054d522f475Smrg { ERROR_SCALLOC, "Alloc: calloc() failed on base" }, 4055d522f475Smrg { ERROR_SCALLOC2, "Alloc: calloc() failed on rows" }, 4056d522f475Smrg { ERROR_SAVE_PTR, "ScrnPointers: malloc/realloc() failed" }, 4057d522f475Smrg { ERROR_MMALLOC, "my_memmove: malloc/realloc failed" }, 4058d522f475Smrg }; 4059d522f475Smrg /* *INDENT-ON* */ 4060d522f475Smrg 4061d522f475Smrg Cardinal n; 4062d522f475Smrg const char *result = "?"; 4063d522f475Smrg 4064d522f475Smrg for (n = 0; n < XtNumber(table); ++n) { 4065d522f475Smrg if (code == table[n].code) { 4066d522f475Smrg result = table[n].name; 4067d522f475Smrg break; 4068d522f475Smrg } 4069d522f475Smrg } 4070d522f475Smrg return result; 4071d522f475Smrg} 4072d522f475Smrg 4073d522f475Smrgvoid 4074d522f475SmrgSysError(int code) 4075d522f475Smrg{ 4076d522f475Smrg int oerrno = errno; 4077d522f475Smrg 4078c219fbebSmrg fprintf(stderr, "%s: Error %d, errno %d: ", ProgramName, code, oerrno); 4079d522f475Smrg fprintf(stderr, "%s\n", SysErrorMsg(oerrno)); 4080d522f475Smrg fprintf(stderr, "Reason: %s\n", SysReasonMsg(code)); 4081d522f475Smrg 4082d522f475Smrg Cleanup(code); 4083d522f475Smrg} 4084d522f475Smrg 4085d522f475Smrg/* 4086d522f475Smrg * cleanup by sending SIGHUP to client processes 4087d522f475Smrg */ 4088d522f475Smrgvoid 4089d522f475SmrgCleanup(int code) 4090d522f475Smrg{ 4091d522f475Smrg static Bool cleaning; 4092d522f475Smrg TScreen *screen = TScreenOf(term); 4093d522f475Smrg 4094d522f475Smrg /* 4095d522f475Smrg * Process "-hold" and session cleanup only for a normal exit. 4096d522f475Smrg */ 4097d522f475Smrg if (code == 0) { 4098d522f475Smrg if (cleaning) { 4099d522f475Smrg hold_screen = 0; 4100d522f475Smrg return; 4101d522f475Smrg } 4102d522f475Smrg 4103d522f475Smrg cleaning = True; 4104d522f475Smrg need_cleanup = False; 4105d522f475Smrg 4106d522f475Smrg TRACE(("Cleanup %d\n", code)); 4107d522f475Smrg 4108d522f475Smrg if (hold_screen) { 4109d522f475Smrg hold_screen = 2; 4110d522f475Smrg while (hold_screen) { 4111d522f475Smrg xevents(); 4112d522f475Smrg Sleep(10); 4113d522f475Smrg } 4114d522f475Smrg } 4115d522f475Smrg#if OPT_SESSION_MGT 4116d522f475Smrg if (resource.sessionMgt) { 4117d522f475Smrg XtVaSetValues(toplevel, 4118d522f475Smrg XtNjoinSession, False, 4119cd3331d0Smrg NULL); 4120d522f475Smrg } 4121d522f475Smrg#endif 4122d522f475Smrg } 4123d522f475Smrg 4124d522f475Smrg if (screen->pid > 1) { 4125d522f475Smrg (void) kill_process_group(screen->pid, SIGHUP); 4126d522f475Smrg } 4127d522f475Smrg Exit(code); 4128d522f475Smrg} 4129d522f475Smrg 4130d522f475Smrg#ifndef VMS 4131d522f475Smrgchar * 4132d522f475SmrgxtermFindShell(char *leaf, Bool warning) 4133d522f475Smrg{ 4134d522f475Smrg char *s; 4135d522f475Smrg char *d; 4136d522f475Smrg char *tmp; 4137d522f475Smrg char *result = leaf; 4138d522f475Smrg 4139d522f475Smrg TRACE(("xtermFindShell(%s)\n", leaf)); 4140d522f475Smrg if (*result != '\0' && strchr("+/-", *result) == 0) { 4141d522f475Smrg /* find it in $PATH */ 4142d522f475Smrg if ((s = x_getenv("PATH")) != 0) { 41430d92cbfdSchristos if ((tmp = TypeMallocN(char, strlen(leaf) + strlen(s) + 2)) != 0) { 4144d522f475Smrg Bool found = False; 4145d522f475Smrg while (*s != '\0') { 4146d522f475Smrg strcpy(tmp, s); 4147d522f475Smrg for (d = tmp;; ++d) { 4148d522f475Smrg if (*d == ':' || *d == '\0') { 4149d522f475Smrg int skip = (*d != '\0'); 4150d522f475Smrg *d = '/'; 4151d522f475Smrg strcpy(d + 1, leaf); 4152d522f475Smrg if (skip) 4153d522f475Smrg ++d; 4154d522f475Smrg s += (d - tmp); 4155d522f475Smrg if (*tmp == '/' 4156d522f475Smrg && strstr(tmp, "..") == 0 4157d522f475Smrg && access(tmp, X_OK) == 0) { 4158d522f475Smrg result = x_strdup(tmp); 4159d522f475Smrg found = True; 4160d522f475Smrg } 4161d522f475Smrg break; 4162d522f475Smrg } 4163d522f475Smrg if (found) 4164d522f475Smrg break; 4165d522f475Smrg } 4166d522f475Smrg if (found) 4167d522f475Smrg break; 4168d522f475Smrg } 4169d522f475Smrg free(tmp); 4170d522f475Smrg } 4171d522f475Smrg } 4172d522f475Smrg } 4173d522f475Smrg TRACE(("...xtermFindShell(%s)\n", result)); 4174d522f475Smrg if (*result != '/' 4175d522f475Smrg || strstr(result, "..") != 0 4176d522f475Smrg || access(result, X_OK) != 0) { 4177d522f475Smrg if (warning) 4178d522f475Smrg fprintf(stderr, "No absolute path found for shell: %s\n", result); 4179d522f475Smrg result = 0; 4180d522f475Smrg } 4181d522f475Smrg return result; 4182d522f475Smrg} 4183d522f475Smrg#endif /* VMS */ 4184d522f475Smrg 41850d92cbfdSchristos#define ENV_HUNK(n) (unsigned) ((((n) + 1) | 31) + 1) 4186d522f475Smrg 4187d522f475Smrg/* 4188d522f475Smrg * copy the environment before Setenv'ing. 4189d522f475Smrg */ 4190d522f475Smrgvoid 4191d522f475SmrgxtermCopyEnv(char **oldenv) 4192d522f475Smrg{ 4193d522f475Smrg unsigned size; 4194d522f475Smrg char **newenv; 4195d522f475Smrg 4196d522f475Smrg for (size = 0; oldenv[size] != NULL; size++) { 4197d522f475Smrg ; 4198d522f475Smrg } 4199d522f475Smrg 4200d522f475Smrg newenv = TypeCallocN(char *, ENV_HUNK(size)); 4201d522f475Smrg memmove(newenv, oldenv, size * sizeof(char *)); 4202d522f475Smrg environ = newenv; 4203d522f475Smrg} 4204d522f475Smrg 4205d522f475Smrg/* 4206d522f475Smrg * sets the value of var to be arg in the Unix 4.2 BSD environment env. 4207d522f475Smrg * Var should end with '=' (bindings are of the form "var=value"). 4208d522f475Smrg * This procedure assumes the memory for the first level of environ 4209d522f475Smrg * was allocated using calloc, with enough extra room at the end so not 4210d522f475Smrg * to have to do a realloc(). 4211d522f475Smrg */ 4212d522f475Smrgvoid 4213cd3331d0SmrgxtermSetenv(const char *var, const char *value) 4214d522f475Smrg{ 4215d522f475Smrg if (value != 0) { 4216d522f475Smrg char *test; 4217d522f475Smrg int envindex = 0; 4218d522f475Smrg size_t len = strlen(var); 4219d522f475Smrg int found = -1; 4220d522f475Smrg 4221d522f475Smrg TRACE(("xtermSetenv(%s=%s)\n", var, value)); 4222d522f475Smrg 4223d522f475Smrg while ((test = environ[envindex]) != NULL) { 4224d522f475Smrg if (strncmp(test, var, len) == 0 && test[len] == '=') { 4225d522f475Smrg found = envindex; 4226d522f475Smrg break; 4227d522f475Smrg } 4228d522f475Smrg envindex++; 4229d522f475Smrg } 4230d522f475Smrg 4231d522f475Smrg if (found < 0) { 4232d522f475Smrg unsigned need = ENV_HUNK(envindex + 1); 4233d522f475Smrg unsigned have = ENV_HUNK(envindex); 4234d522f475Smrg 4235d522f475Smrg if (need > have) { 4236d522f475Smrg char **newenv; 4237d522f475Smrg newenv = TypeMallocN(char *, need); 4238d522f475Smrg if (newenv == 0) { 4239d522f475Smrg fprintf(stderr, "Cannot increase environment\n"); 4240d522f475Smrg return; 4241d522f475Smrg } 4242d522f475Smrg memmove(newenv, environ, have * sizeof(*newenv)); 4243d522f475Smrg free(environ); 4244d522f475Smrg environ = newenv; 4245d522f475Smrg } 4246d522f475Smrg 4247d522f475Smrg found = envindex; 4248d522f475Smrg environ[found + 1] = NULL; 4249d522f475Smrg environ = environ; 4250d522f475Smrg } 4251d522f475Smrg 4252d522f475Smrg environ[found] = CastMallocN(char, 1 + len + strlen(value)); 4253d522f475Smrg if (environ[found] == 0) { 4254d522f475Smrg fprintf(stderr, "Cannot allocate environment %s\n", var); 4255d522f475Smrg return; 4256d522f475Smrg } 4257d522f475Smrg sprintf(environ[found], "%s=%s", var, value); 4258d522f475Smrg } 4259d522f475Smrg} 4260d522f475Smrg 4261d522f475Smrg/*ARGSUSED*/ 4262d522f475Smrgint 4263d522f475Smrgxerror(Display * d, XErrorEvent * ev) 4264d522f475Smrg{ 4265c219fbebSmrg fprintf(stderr, "%s: warning, error event received:\n", ProgramName); 4266d522f475Smrg (void) XmuPrintDefaultErrorMessage(d, ev, stderr); 4267d522f475Smrg Exit(ERROR_XERROR); 4268d522f475Smrg return 0; /* appease the compiler */ 4269d522f475Smrg} 4270d522f475Smrg 4271d522f475Smrg/*ARGSUSED*/ 4272d522f475Smrgint 4273d522f475Smrgxioerror(Display * dpy) 4274d522f475Smrg{ 4275d522f475Smrg int the_error = errno; 4276d522f475Smrg 4277d522f475Smrg (void) fprintf(stderr, 4278d522f475Smrg "%s: fatal IO error %d (%s) or KillClient on X server \"%s\"\r\n", 4279c219fbebSmrg ProgramName, the_error, SysErrorMsg(the_error), 4280d522f475Smrg DisplayString(dpy)); 4281d522f475Smrg 4282d522f475Smrg Exit(ERROR_XIOERROR); 4283d522f475Smrg return 0; /* appease the compiler */ 4284d522f475Smrg} 4285d522f475Smrg 4286d522f475Smrgvoid 4287d522f475Smrgxt_error(String message) 4288d522f475Smrg{ 4289d522f475Smrg (void) fprintf(stderr, "%s Xt error: %s\n", ProgramName, message); 4290d522f475Smrg 4291d522f475Smrg /* 4292d522f475Smrg * Check for the obvious - Xt does a poor job of reporting this. 4293d522f475Smrg */ 4294d522f475Smrg if (x_getenv("DISPLAY") == 0) { 4295d522f475Smrg fprintf(stderr, "%s: DISPLAY is not set\n", ProgramName); 4296d522f475Smrg } 4297d522f475Smrg exit(1); 4298d522f475Smrg} 4299d522f475Smrg 4300d522f475Smrgint 4301d522f475SmrgXStrCmp(char *s1, char *s2) 4302d522f475Smrg{ 4303d522f475Smrg if (s1 && s2) 4304d522f475Smrg return (strcmp(s1, s2)); 4305d522f475Smrg if (s1 && *s1) 4306d522f475Smrg return (1); 4307d522f475Smrg if (s2 && *s2) 4308d522f475Smrg return (-1); 4309d522f475Smrg return (0); 4310d522f475Smrg} 4311d522f475Smrg 4312d522f475Smrg#if OPT_TEK4014 4313d522f475Smrgstatic void 4314d522f475Smrgwithdraw_window(Display * dpy, Window w, int scr) 4315d522f475Smrg{ 4316d522f475Smrg TRACE(("withdraw_window %#lx\n", (long) w)); 4317d522f475Smrg (void) XmuUpdateMapHints(dpy, w, NULL); 4318d522f475Smrg XWithdrawWindow(dpy, w, scr); 4319d522f475Smrg return; 4320d522f475Smrg} 4321d522f475Smrg#endif 4322d522f475Smrg 4323d522f475Smrgvoid 4324d522f475Smrgset_vt_visibility(Bool on) 4325d522f475Smrg{ 4326c219fbebSmrg XtermWidget xw = term; 4327c219fbebSmrg TScreen *screen = TScreenOf(xw); 4328d522f475Smrg 4329d522f475Smrg TRACE(("set_vt_visibility(%d)\n", on)); 4330d522f475Smrg if (on) { 4331c219fbebSmrg if (!screen->Vshow && xw) { 4332c219fbebSmrg VTInit(xw); 4333c219fbebSmrg XtMapWidget(XtParent(xw)); 4334d522f475Smrg#if OPT_TOOLBAR 4335d522f475Smrg /* we need both of these during initialization */ 4336c219fbebSmrg XtMapWidget(SHELL_OF(xw)); 4337d522f475Smrg ShowToolbar(resource.toolBar); 4338d522f475Smrg#endif 4339d522f475Smrg screen->Vshow = True; 4340d522f475Smrg } 4341d522f475Smrg } 4342d522f475Smrg#if OPT_TEK4014 4343d522f475Smrg else { 4344c219fbebSmrg if (screen->Vshow && xw) { 4345c219fbebSmrg withdraw_window(XtDisplay(xw), 4346c219fbebSmrg VShellWindow(xw), 4347c219fbebSmrg XScreenNumberOfScreen(XtScreen(xw))); 4348d522f475Smrg screen->Vshow = False; 4349d522f475Smrg } 4350d522f475Smrg } 4351d522f475Smrg set_vthide_sensitivity(); 4352d522f475Smrg set_tekhide_sensitivity(); 4353d522f475Smrg update_vttekmode(); 4354d522f475Smrg update_tekshow(); 4355d522f475Smrg update_vtshow(); 4356d522f475Smrg#endif 4357d522f475Smrg return; 4358d522f475Smrg} 4359d522f475Smrg 4360d522f475Smrg#if OPT_TEK4014 4361d522f475Smrgvoid 4362d522f475Smrgset_tek_visibility(Bool on) 4363d522f475Smrg{ 4364d522f475Smrg TRACE(("set_tek_visibility(%d)\n", on)); 4365d522f475Smrg 4366d522f475Smrg if (on) { 4367cd3331d0Smrg if (!TEK4014_SHOWN(term)) { 4368cd3331d0Smrg if (tekWidget == 0) { 4369cd3331d0Smrg TekInit(); /* will exit on failure */ 4370cd3331d0Smrg } 4371cd3331d0Smrg if (tekWidget != 0) { 4372cd3331d0Smrg Widget tekParent = SHELL_OF(tekWidget); 4373cd3331d0Smrg XtRealizeWidget(tekParent); 4374cd3331d0Smrg XtMapWidget(XtParent(tekWidget)); 4375d522f475Smrg#if OPT_TOOLBAR 4376cd3331d0Smrg /* we need both of these during initialization */ 4377cd3331d0Smrg XtMapWidget(tekParent); 4378cd3331d0Smrg XtMapWidget(tekWidget); 4379d522f475Smrg#endif 4380cd3331d0Smrg XtOverrideTranslations(tekParent, 4381cd3331d0Smrg XtParseTranslationTable 4382cd3331d0Smrg ("<Message>WM_PROTOCOLS: DeleteWindow()")); 4383cd3331d0Smrg (void) XSetWMProtocols(XtDisplay(tekParent), 4384cd3331d0Smrg XtWindow(tekParent), 4385cd3331d0Smrg &wm_delete_window, 1); 4386cd3331d0Smrg TEK4014_SHOWN(term) = True; 4387cd3331d0Smrg } 4388d522f475Smrg } 4389d522f475Smrg } else { 4390d522f475Smrg if (TEK4014_SHOWN(term) && tekWidget) { 4391d522f475Smrg withdraw_window(XtDisplay(tekWidget), 4392d522f475Smrg TShellWindow, 4393d522f475Smrg XScreenNumberOfScreen(XtScreen(tekWidget))); 4394d522f475Smrg TEK4014_SHOWN(term) = False; 4395d522f475Smrg } 4396d522f475Smrg } 4397d522f475Smrg set_tekhide_sensitivity(); 4398d522f475Smrg set_vthide_sensitivity(); 4399d522f475Smrg update_vtshow(); 4400d522f475Smrg update_tekshow(); 4401d522f475Smrg update_vttekmode(); 4402d522f475Smrg return; 4403d522f475Smrg} 4404d522f475Smrg 4405d522f475Smrgvoid 4406d522f475Smrgend_tek_mode(void) 4407d522f475Smrg{ 4408cd3331d0Smrg XtermWidget xw = term; 4409cd3331d0Smrg 4410cd3331d0Smrg if (TEK4014_ACTIVE(xw)) { 4411cd3331d0Smrg FlushLog(xw); 4412d522f475Smrg longjmp(Tekend, 1); 4413d522f475Smrg } 4414d522f475Smrg return; 4415d522f475Smrg} 4416d522f475Smrg 4417d522f475Smrgvoid 4418d522f475Smrgend_vt_mode(void) 4419d522f475Smrg{ 4420cd3331d0Smrg XtermWidget xw = term; 4421cd3331d0Smrg 4422cd3331d0Smrg if (!TEK4014_ACTIVE(xw)) { 4423cd3331d0Smrg FlushLog(xw); 4424cd3331d0Smrg TEK4014_ACTIVE(xw) = True; 4425d522f475Smrg longjmp(VTend, 1); 4426d522f475Smrg } 4427d522f475Smrg return; 4428d522f475Smrg} 4429d522f475Smrg 4430d522f475Smrgvoid 4431d522f475Smrgswitch_modes(Bool tovt) /* if true, then become vt mode */ 4432d522f475Smrg{ 4433d522f475Smrg if (tovt) { 4434d522f475Smrg if (tekRefreshList) 4435d522f475Smrg TekRefresh(tekWidget); 4436d522f475Smrg end_tek_mode(); /* WARNING: this does a longjmp... */ 4437d522f475Smrg } else { 4438d522f475Smrg end_vt_mode(); /* WARNING: this does a longjmp... */ 4439d522f475Smrg } 4440d522f475Smrg} 4441d522f475Smrg 4442d522f475Smrgvoid 4443d522f475Smrghide_vt_window(void) 4444d522f475Smrg{ 4445d522f475Smrg set_vt_visibility(False); 4446d522f475Smrg if (!TEK4014_ACTIVE(term)) 4447d522f475Smrg switch_modes(False); /* switch to tek mode */ 4448d522f475Smrg} 4449d522f475Smrg 4450d522f475Smrgvoid 4451d522f475Smrghide_tek_window(void) 4452d522f475Smrg{ 4453d522f475Smrg set_tek_visibility(False); 4454d522f475Smrg tekRefreshList = (TekLink *) 0; 4455d522f475Smrg if (TEK4014_ACTIVE(term)) 4456d522f475Smrg switch_modes(True); /* does longjmp to vt mode */ 4457d522f475Smrg} 4458d522f475Smrg#endif /* OPT_TEK4014 */ 4459d522f475Smrg 4460d522f475Smrgstatic const char * 4461d522f475Smrgskip_punct(const char *s) 4462d522f475Smrg{ 4463d522f475Smrg while (*s == '-' || *s == '/' || *s == '+' || *s == '#' || *s == '%') { 4464d522f475Smrg ++s; 4465d522f475Smrg } 4466d522f475Smrg return s; 4467d522f475Smrg} 4468d522f475Smrg 4469d522f475Smrgstatic int 4470d522f475Smrgcmp_options(const void *a, const void *b) 4471d522f475Smrg{ 4472d522f475Smrg const char *s1 = skip_punct(((const OptionHelp *) a)->opt); 4473d522f475Smrg const char *s2 = skip_punct(((const OptionHelp *) b)->opt); 4474d522f475Smrg return strcmp(s1, s2); 4475d522f475Smrg} 4476d522f475Smrg 4477d522f475Smrgstatic int 4478d522f475Smrgcmp_resources(const void *a, const void *b) 4479d522f475Smrg{ 4480d522f475Smrg return strcmp(((const XrmOptionDescRec *) a)->option, 4481d522f475Smrg ((const XrmOptionDescRec *) b)->option); 4482d522f475Smrg} 4483d522f475Smrg 4484d522f475SmrgXrmOptionDescRec * 4485d522f475SmrgsortedOptDescs(XrmOptionDescRec * descs, Cardinal res_count) 4486d522f475Smrg{ 4487d522f475Smrg static XrmOptionDescRec *res_array = 0; 4488d522f475Smrg 4489d522f475Smrg#ifdef NO_LEAKS 4490cd3331d0Smrg if (descs == 0) { 4491cd3331d0Smrg if (res_array != 0) { 4492cd3331d0Smrg free(res_array); 4493cd3331d0Smrg res_array = 0; 4494cd3331d0Smrg } 4495d522f475Smrg } else 4496d522f475Smrg#endif 4497d522f475Smrg if (res_array == 0) { 4498d522f475Smrg Cardinal j; 4499d522f475Smrg 4500d522f475Smrg /* make a sorted index to 'resources' */ 4501d522f475Smrg res_array = TypeCallocN(XrmOptionDescRec, res_count); 4502cd3331d0Smrg if (res_array != 0) { 4503cd3331d0Smrg for (j = 0; j < res_count; j++) 4504cd3331d0Smrg res_array[j] = descs[j]; 4505cd3331d0Smrg qsort(res_array, (size_t) res_count, sizeof(*res_array), cmp_resources); 4506cd3331d0Smrg } 4507d522f475Smrg } 4508d522f475Smrg return res_array; 4509d522f475Smrg} 4510d522f475Smrg 4511d522f475Smrg/* 4512d522f475Smrg * The first time this is called, construct sorted index to the main program's 4513d522f475Smrg * list of options, taking into account the on/off options which will be 4514d522f475Smrg * compressed into one token. It's a lot simpler to do it this way than 4515d522f475Smrg * maintain the list in sorted form with lots of ifdef's. 4516d522f475Smrg */ 4517d522f475SmrgOptionHelp * 4518d522f475SmrgsortedOpts(OptionHelp * options, XrmOptionDescRec * descs, Cardinal numDescs) 4519d522f475Smrg{ 4520d522f475Smrg static OptionHelp *opt_array = 0; 4521d522f475Smrg 4522d522f475Smrg#ifdef NO_LEAKS 4523d522f475Smrg if (descs == 0 && opt_array != 0) { 4524d522f475Smrg sortedOptDescs(descs, numDescs); 4525d522f475Smrg free(opt_array); 4526d522f475Smrg opt_array = 0; 4527d522f475Smrg return 0; 4528d522f475Smrg } else if (options == 0 || descs == 0) { 4529d522f475Smrg return 0; 4530d522f475Smrg } 4531d522f475Smrg#endif 4532d522f475Smrg 4533d522f475Smrg if (opt_array == 0) { 4534cd3331d0Smrg size_t opt_count, j; 4535d522f475Smrg#if OPT_TRACE 4536d522f475Smrg Cardinal k; 4537d522f475Smrg XrmOptionDescRec *res_array = sortedOptDescs(descs, numDescs); 4538d522f475Smrg int code; 4539cd3331d0Smrg const char *mesg; 4540d522f475Smrg#else 4541d522f475Smrg (void) descs; 4542d522f475Smrg (void) numDescs; 4543d522f475Smrg#endif 4544d522f475Smrg 4545d522f475Smrg /* count 'options' and make a sorted index to it */ 4546d522f475Smrg for (opt_count = 0; options[opt_count].opt != 0; ++opt_count) { 4547d522f475Smrg ; 4548d522f475Smrg } 4549d522f475Smrg opt_array = TypeCallocN(OptionHelp, opt_count + 1); 4550d522f475Smrg for (j = 0; j < opt_count; j++) 4551d522f475Smrg opt_array[j] = options[j]; 4552d522f475Smrg qsort(opt_array, opt_count, sizeof(OptionHelp), cmp_options); 4553d522f475Smrg 4554d522f475Smrg /* supply the "turn on/off" strings if needed */ 4555d522f475Smrg#if OPT_TRACE 4556d522f475Smrg for (j = 0; j < opt_count; j++) { 4557d522f475Smrg if (!strncmp(opt_array[j].opt, "-/+", 3)) { 4558c219fbebSmrg char temp[80]; 4559cd3331d0Smrg const char *name = opt_array[j].opt + 3; 4560d522f475Smrg for (k = 0; k < numDescs; ++k) { 4561cd3331d0Smrg const char *value = res_array[k].value; 4562d522f475Smrg if (res_array[k].option[0] == '-') { 4563d522f475Smrg code = -1; 4564d522f475Smrg } else if (res_array[k].option[0] == '+') { 4565d522f475Smrg code = 1; 4566d522f475Smrg } else { 4567d522f475Smrg code = 0; 4568d522f475Smrg } 4569c219fbebSmrg strcpy(temp, opt_array[j].desc); 4570c219fbebSmrg if (x_strindex(temp, "inhibit") != 0) 4571d522f475Smrg code = -code; 4572d522f475Smrg if (code != 0 4573d522f475Smrg && res_array[k].value != 0 4574d522f475Smrg && !strcmp(name, res_array[k].option + 1)) { 4575d522f475Smrg if (((code < 0) && !strcmp(value, "on")) 4576d522f475Smrg || ((code > 0) && !strcmp(value, "off")) 4577d522f475Smrg || ((code > 0) && !strcmp(value, "0"))) { 4578d522f475Smrg mesg = "turn on/off"; 4579d522f475Smrg } else { 4580d522f475Smrg mesg = "turn off/on"; 4581d522f475Smrg } 4582d522f475Smrg if (strncmp(mesg, opt_array[j].desc, strlen(mesg))) { 4583d522f475Smrg if (strncmp(opt_array[j].desc, "turn ", 5)) { 4584d522f475Smrg char *s = CastMallocN(char, 4585d522f475Smrg strlen(mesg) 4586d522f475Smrg + 1 4587d522f475Smrg + strlen(opt_array[j].desc)); 4588d522f475Smrg if (s != 0) { 4589d522f475Smrg sprintf(s, "%s %s", mesg, opt_array[j].desc); 4590d522f475Smrg opt_array[j].desc = s; 4591d522f475Smrg } 4592d522f475Smrg } else { 4593d522f475Smrg TRACE(("OOPS ")); 4594d522f475Smrg } 4595d522f475Smrg } 4596d522f475Smrg TRACE(("%s: %s %s: %s (%s)\n", 4597d522f475Smrg mesg, 4598d522f475Smrg res_array[k].option, 4599d522f475Smrg res_array[k].value, 4600d522f475Smrg opt_array[j].opt, 4601d522f475Smrg opt_array[j].desc)); 4602d522f475Smrg break; 4603d522f475Smrg } 4604d522f475Smrg } 4605d522f475Smrg } 4606d522f475Smrg } 4607d522f475Smrg#endif 4608d522f475Smrg } 4609d522f475Smrg return opt_array; 4610d522f475Smrg} 4611d522f475Smrg 4612d522f475Smrg/* 4613d522f475Smrg * Report the character-type locale that xterm was started in. 4614d522f475Smrg */ 4615d522f475Smrgchar * 4616d522f475SmrgxtermEnvLocale(void) 4617d522f475Smrg{ 4618d522f475Smrg static char *result; 4619d522f475Smrg 4620d522f475Smrg if (result == 0) { 4621d522f475Smrg if ((result = x_nonempty(setlocale(LC_CTYPE, 0))) == 0) { 4622cd3331d0Smrg result = x_strdup("C"); 4623cd3331d0Smrg } else { 4624cd3331d0Smrg result = x_strdup(result); 4625d522f475Smrg } 4626d522f475Smrg TRACE(("xtermEnvLocale ->%s\n", result)); 4627d522f475Smrg } 4628d522f475Smrg return result; 4629d522f475Smrg} 4630d522f475Smrg 4631d522f475Smrgchar * 4632d522f475SmrgxtermEnvEncoding(void) 4633d522f475Smrg{ 4634d522f475Smrg static char *result; 4635d522f475Smrg 4636d522f475Smrg if (result == 0) { 4637d522f475Smrg#ifdef HAVE_LANGINFO_CODESET 4638d522f475Smrg result = nl_langinfo(CODESET); 4639d522f475Smrg#else 4640d522f475Smrg char *locale = xtermEnvLocale(); 4641d522f475Smrg if (!strcmp(locale, "C") || !strcmp(locale, "POSIX")) { 4642d522f475Smrg result = "ASCII"; 4643d522f475Smrg } else { 4644d522f475Smrg result = "ISO-8859-1"; 4645d522f475Smrg } 4646d522f475Smrg#endif 4647d522f475Smrg TRACE(("xtermEnvEncoding ->%s\n", result)); 4648d522f475Smrg } 4649d522f475Smrg return result; 4650d522f475Smrg} 4651d522f475Smrg 4652d522f475Smrg#if OPT_WIDE_CHARS 4653d522f475Smrg/* 4654d522f475Smrg * Tell whether xterm was started in a locale that uses UTF-8 encoding for 4655d522f475Smrg * characters. That environment is inherited by subprocesses and used in 4656d522f475Smrg * various library calls. 4657d522f475Smrg */ 4658d522f475SmrgBool 4659d522f475SmrgxtermEnvUTF8(void) 4660d522f475Smrg{ 4661d522f475Smrg static Bool init = False; 4662d522f475Smrg static Bool result = False; 4663d522f475Smrg 4664d522f475Smrg if (!init) { 4665d522f475Smrg init = True; 4666d522f475Smrg#ifdef HAVE_LANGINFO_CODESET 4667d522f475Smrg result = (strcmp(xtermEnvEncoding(), "UTF-8") == 0); 4668d522f475Smrg#else 4669d522f475Smrg result = (strstr(xtermEnvLocale(), "UTF-8") != NULL); 4670d522f475Smrg#endif 4671d522f475Smrg TRACE(("xtermEnvUTF8 ->%s\n", BtoS(result))); 4672d522f475Smrg } 4673d522f475Smrg return result; 4674d522f475Smrg} 4675d522f475Smrg#endif /* OPT_WIDE_CHARS */ 4676d522f475Smrg 4677d522f475Smrg/* 4678d522f475Smrg * Returns the version-string used in the "-v' message as well as a few other 4679d522f475Smrg * places. It is derived (when possible) from the __vendorversion__ symbol 4680d522f475Smrg * that some newer imake configurations define. 4681d522f475Smrg */ 4682d522f475Smrgchar * 4683d522f475SmrgxtermVersion(void) 4684d522f475Smrg{ 4685cd3331d0Smrg static char vendor_version[] = __vendorversion__; 4686d522f475Smrg static char *result; 4687cd3331d0Smrg 4688d522f475Smrg if (result == 0) { 4689cd3331d0Smrg char *vendor = vendor_version; 4690d522f475Smrg char first[BUFSIZ]; 4691d522f475Smrg char second[BUFSIZ]; 4692d522f475Smrg 4693d522f475Smrg result = CastMallocN(char, strlen(vendor) + 9); 4694d522f475Smrg if (result == 0) 4695d522f475Smrg result = vendor; 4696d522f475Smrg else { 4697d522f475Smrg /* some vendors leave trash in this string */ 4698d522f475Smrg for (;;) { 4699cd3331d0Smrg if (!strncmp(vendor, "Version ", (size_t) 8)) 4700d522f475Smrg vendor += 8; 4701d522f475Smrg else if (isspace(CharOf(*vendor))) 4702d522f475Smrg ++vendor; 4703d522f475Smrg else 4704d522f475Smrg break; 4705d522f475Smrg } 4706d522f475Smrg if (strlen(vendor) < BUFSIZ && 4707d522f475Smrg sscanf(vendor, "%[0-9.] %[A-Za-z_0-9.]", first, second) == 2) 4708d522f475Smrg sprintf(result, "%s %s(%d)", second, first, XTERM_PATCH); 4709d522f475Smrg else 4710d522f475Smrg sprintf(result, "%s(%d)", vendor, XTERM_PATCH); 4711d522f475Smrg } 4712d522f475Smrg } 4713d522f475Smrg return result; 4714d522f475Smrg} 4715b7c89284Ssnj 4716b7c89284Ssnj/* 4717b7c89284Ssnj * Check if the current widget, or any parent, is the VT100 "xterm" widget. 4718b7c89284Ssnj */ 4719b7c89284SsnjXtermWidget 4720b7c89284SsnjgetXtermWidget(Widget w) 4721b7c89284Ssnj{ 4722b7c89284Ssnj XtermWidget xw; 4723b7c89284Ssnj 4724b7c89284Ssnj if (w == 0) { 4725b7c89284Ssnj xw = (XtermWidget) CURRENT_EMU(); 4726b7c89284Ssnj if (!IsXtermWidget(xw)) { 4727b7c89284Ssnj xw = 0; 4728b7c89284Ssnj } 4729b7c89284Ssnj } else if (IsXtermWidget(w)) { 4730b7c89284Ssnj xw = (XtermWidget) w; 4731b7c89284Ssnj } else { 4732b7c89284Ssnj xw = getXtermWidget(XtParent(w)); 4733b7c89284Ssnj } 4734b7c89284Ssnj TRACE2(("getXtermWidget %p -> %p\n", w, xw)); 4735b7c89284Ssnj return xw; 4736b7c89284Ssnj} 4737