15dfecf96Smrg/* 25dfecf96Smrg * Copyright (c) 2002 by The XFree86 Project, Inc. 35dfecf96Smrg * 45dfecf96Smrg * Permission is hereby granted, free of charge, to any person obtaining a 55dfecf96Smrg * copy of this software and associated documentation files (the "Software"), 65dfecf96Smrg * to deal in the Software without restriction, including without limitation 75dfecf96Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 85dfecf96Smrg * and/or sell copies of the Software, and to permit persons to whom the 95dfecf96Smrg * Software is furnished to do so, subject to the following conditions: 105dfecf96Smrg * 115dfecf96Smrg * The above copyright notice and this permission notice shall be included in 125dfecf96Smrg * all copies or substantial portions of the Software. 135dfecf96Smrg * 145dfecf96Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 155dfecf96Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 165dfecf96Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 175dfecf96Smrg * THE XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 185dfecf96Smrg * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF 195dfecf96Smrg * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 205dfecf96Smrg * SOFTWARE. 215dfecf96Smrg * 225dfecf96Smrg * Except as contained in this notice, the name of the XFree86 Project shall 235dfecf96Smrg * not be used in advertising or otherwise to promote the sale, use or other 245dfecf96Smrg * dealings in this Software without prior written authorization from the 255dfecf96Smrg * XFree86 Project. 265dfecf96Smrg * 275dfecf96Smrg * Author: Paulo César Pereira de Andrade 285dfecf96Smrg */ 295dfecf96Smrg 305dfecf96Smrg/* $XFree86: xc/programs/xedit/lisp/xedit.c,v 1.25 2003/04/27 18:17:35 tsi Exp $ */ 315dfecf96Smrg 325dfecf96Smrg#include "../xedit.h" 335dfecf96Smrg#include <X11/Xaw/TextSrcP.h> /* Needs some private definitions */ 345dfecf96Smrg#include <X11/Xaw/TextSinkP.h> /* Also needs private definitions... */ 355dfecf96Smrg#include <X11/Xmu/Xmu.h> 365dfecf96Smrg#define XEDIT_LISP_PRIVATE 375dfecf96Smrg#include "xedit.h" 385dfecf96Smrg#include <signal.h> 395dfecf96Smrg 405dfecf96Smrg/* Initialize to enter lisp */ 415dfecf96Smrg#define LISP_SETUP() \ 425dfecf96Smrg int lisp__running = lisp__data.running 435dfecf96Smrg 445dfecf96Smrg/* XXX Maybe should use ualarm or better, setitimer, but one 455dfecf96Smrg * second seens good enough to check for interrupts */ 465dfecf96Smrg 475dfecf96Smrg#define ENABLE_SIGALRM() \ 485dfecf96Smrg old_sigalrm = signal(SIGALRM, SigalrmHandler); \ 495dfecf96Smrg alarm(1) 505dfecf96Smrg 515dfecf96Smrg#define DISABLE_SIGALRM() \ 525dfecf96Smrg alarm(0); \ 535dfecf96Smrg signal(SIGALRM, old_sigalrm) 545dfecf96Smrg 555dfecf96Smrg/* Enter lisp */ 565dfecf96Smrg#define LISP_ENTER() \ 575dfecf96Smrg if (!lisp__running) { \ 585dfecf96Smrg lisp__data.running = 1; \ 595dfecf96Smrg XFlush(XtDisplay(textwindow)); \ 605dfecf96Smrg ENABLE_SIGALRM(); \ 615dfecf96Smrg if (sigsetjmp(lisp__data.jmp, 1) != 0) { \ 625dfecf96Smrg DISABLE_SIGALRM(); \ 635dfecf96Smrg lisp__data.running = 0; \ 645dfecf96Smrg return; \ 655dfecf96Smrg } \ 665dfecf96Smrg } 675dfecf96Smrg 685dfecf96Smrg/* Leave lisp */ 695dfecf96Smrg#define LISP_LEAVE() \ 705dfecf96Smrg if (!lisp__running) { \ 715dfecf96Smrg DISABLE_SIGALRM(); \ 725dfecf96Smrg LispTopLevel(); \ 735dfecf96Smrg lisp__data.running = 0; \ 745dfecf96Smrg } 755dfecf96Smrg 765dfecf96Smrg/* 775dfecf96Smrg * Types 785dfecf96Smrg */ 795dfecf96Smrgtypedef struct { 805dfecf96Smrg XawTextPosition left, right; 815dfecf96Smrg XrmQuark property; 825dfecf96Smrg} EntityInfo; 835dfecf96Smrg 845dfecf96Smrg/* 855dfecf96Smrg * Prototypes 865dfecf96Smrg */ 875dfecf96Smrgstatic Bool ControlGPredicate(Display*, XEvent*, XPointer); 885dfecf96Smrgstatic ssize_t WriteToStdout(int, const void*, size_t); 895dfecf96Smrgstatic ssize_t WriteToStderr(int, const void*, size_t); 905dfecf96Smrgstatic ssize_t WrapWrite(Widget, const void*, size_t); 915dfecf96Smrgstatic void XeditUpdateModeInfos(void); 925dfecf96Smrgstatic void XeditPrint(Widget, LispObj*, int); 935dfecf96Smrgstatic void XeditInteractiveCallback(Widget, XtPointer, XtPointer); 945dfecf96Smrgstatic void XeditIndentationCallback(Widget, XtPointer, XtPointer); 955dfecf96Smrgstatic LispObj *XeditCharAt(LispBuiltin*, int); 965dfecf96Smrgstatic LispObj *XeditSearch(LispBuiltin*, XawTextScanDirection); 975dfecf96Smrg 985dfecf96Smrg/* 995dfecf96Smrg * Initialization 1005dfecf96Smrg */ 1015dfecf96Smrgstatic void (*old_sigalrm)(int); 1025dfecf96Smrg 1035dfecf96SmrgEditModeInfo *mode_infos; 1045dfecf96SmrgCardinal num_mode_infos; 1055dfecf96Smrg 1065dfecf96Smrgstatic LispObj *Oauto_modes, *Oauto_mode, *Osyntax_highlight, *Osyntable_indent; 1075dfecf96Smrg 1085dfecf96Smrg/* Just to make calling interactive reparse easier */ 1095dfecf96Smrgstatic LispObj interactive_arguments[4]; 1105dfecf96Smrg 1115dfecf96Smrgstatic LispObj *justify_modes[4]; 1125dfecf96Smrgstatic LispObj *wrap_modes[3]; 1135dfecf96Smrgstatic LispObj *scan_types[6]; 1145dfecf96Smrgstatic LispObj *scan_directions[2]; 1155dfecf96Smrgstatic LispObj execute_stream; 1165dfecf96Smrgstatic LispString execute_string; 1175dfecf96Smrgstatic LispObj result_stream; 1185dfecf96Smrgstatic LispString result_string; 1195dfecf96Smrgstatic XawTextPropertyList **property_lists; 1205dfecf96Smrgstatic Cardinal num_property_lists; 1215dfecf96Smrg 1225dfecf96Smrg/* Some hacks to (at lest try to) avoid problems reentering Xlib while 1235dfecf96Smrg * testing for user interrupts */ 1245dfecf96Smrgstatic volatile int disable_timeout, request_timeout; 1255dfecf96Smrg 1265dfecf96Smrgextern int pagesize; 1275dfecf96Smrg 1285dfecf96Smrgstatic LispBuiltin xeditbuiltins[] = { 1295dfecf96Smrg {LispFunction, Xedit_AddEntity, "add-entity offset length identifier"}, 1305dfecf96Smrg {LispFunction, Xedit_AutoFill, "auto-fill &optional value"}, 1315dfecf96Smrg {LispFunction, Xedit_Background, "background &optional color"}, 1325dfecf96Smrg {LispFunction, Xedit_CharAfter, "char-after &optional offset"}, 1335dfecf96Smrg {LispFunction, Xedit_CharBefore, "char-before &optional offset"}, 1345dfecf96Smrg {LispFunction, Xedit_ClearEntities, "clear-entities left right"}, 1355dfecf96Smrg {LispFunction, Xedit_ConvertPropertyList, "convert-property-list name definition"}, 1365dfecf96Smrg {LispFunction, Xedit_Font, "font &optional font"}, 1375dfecf96Smrg {LispFunction, Xedit_Foreground, "foreground &optional color"}, 1385dfecf96Smrg {LispFunction, Xedit_GotoChar, "goto-char offset"}, 1395dfecf96Smrg {LispFunction, Xedit_HorizontalScrollbar, "horizontal-scrollbar &optional state"}, 1405dfecf96Smrg {LispFunction, Xedit_Insert, "insert text"}, 1415dfecf96Smrg {LispFunction, Xedit_Justification, "justification &optional value"}, 1425dfecf96Smrg {LispFunction, Xedit_LeftColumn, "left-column &optional left"}, 1435dfecf96Smrg {LispFunction, Xedit_Point, "point"}, 1445dfecf96Smrg {LispFunction, Xedit_PointMax, "point-max"}, 1455dfecf96Smrg {LispFunction, Xedit_PointMin, "point-min"}, 1465dfecf96Smrg {LispFunction, Xedit_PropertyList, "property-list &optional value"}, 1475dfecf96Smrg {LispFunction, Xedit_ReadText, "read-text offset length"}, 1485dfecf96Smrg {LispFunction, Xedit_ReplaceText, "replace-text left right text"}, 1495dfecf96Smrg {LispFunction, Xedit_RightColumn, "right-column &optional right"}, 1505dfecf96Smrg {LispFunction, Xedit_Scan, "scan offset type direction &key count include"}, 1515dfecf96Smrg {LispFunction, Xedit_SearchBackward, "search-backward string &optional offset ignore-case"}, 1525dfecf96Smrg {LispFunction, Xedit_SearchForward, "search-forward string &optional offset ignore-case"}, 1535dfecf96Smrg {LispFunction, Xedit_VerticalScrollbar, "vertical-scrollbar &optional state"}, 1545dfecf96Smrg {LispFunction, Xedit_WrapMode, "wrap-mode &optional value"}, 1555dfecf96Smrg 1565dfecf96Smrg /* This should be available from elsewhere at some time... */ 1575dfecf96Smrg {LispFunction, Xedit_XrmStringToQuark, "xrm-string-to-quark string"}, 1585dfecf96Smrg}; 1595dfecf96Smrg 1605dfecf96Smrg/* 1615dfecf96Smrg * Implementation 1625dfecf96Smrg */ 1635dfecf96Smrg/*ARGUSED*/ 1645dfecf96Smrgstatic Bool 1655dfecf96SmrgControlGPredicate(Display *display, XEvent *event, XPointer arguments) 1665dfecf96Smrg{ 1675dfecf96Smrg char buffer[2]; 1685dfecf96Smrg 1695dfecf96Smrg return ((event->type == KeyPress || event->type == KeyRelease) && 1705dfecf96Smrg (event->xkey.state & ControlMask) && 1715dfecf96Smrg XLookupString(&(event->xkey), buffer, sizeof(buffer), NULL, NULL) && 1725dfecf96Smrg buffer[0] == '\a'); 1735dfecf96Smrg} 1745dfecf96Smrg 1755dfecf96Smrg/*ARGSUSED*/ 176f765521fSmrgstatic void 1775dfecf96SmrgSigalrmHandler(int signum) 1785dfecf96Smrg{ 1795dfecf96Smrg XEvent event; 1805dfecf96Smrg 1815dfecf96Smrg if (disable_timeout) { 1825dfecf96Smrg request_timeout = 1; 1835dfecf96Smrg return; 1845dfecf96Smrg } 1855dfecf96Smrg 1865dfecf96Smrg /* Check if user pressed C-g */ 1875dfecf96Smrg if (XCheckIfEvent(XtDisplay(textwindow), &event, ControlGPredicate, NULL)) { 1885dfecf96Smrg XPutBackEvent(XtDisplay(textwindow), &event); 1895dfecf96Smrg alarm(0); 1905dfecf96Smrg /* Tell a signal was received, print message for SIGINT */ 1915dfecf96Smrg LispSignal(SIGINT); 1925dfecf96Smrg } 1935dfecf96Smrg else 1945dfecf96Smrg alarm(1); 1955dfecf96Smrg} 1965dfecf96Smrg 1975dfecf96Smrgstatic ssize_t 1985dfecf96SmrgWrapWrite(Widget output, const void *buffer, size_t nbytes) 1995dfecf96Smrg{ 2005dfecf96Smrg XawTextBlock block; 2015dfecf96Smrg XawTextPosition position; 2025dfecf96Smrg 2035dfecf96Smrg disable_timeout = 1; 2045dfecf96Smrg position = XawTextGetInsertionPoint(output); 2055dfecf96Smrg block.firstPos = 0; 2065dfecf96Smrg block.format = FMT8BIT; 2075dfecf96Smrg block.length = nbytes; 2085dfecf96Smrg block.ptr = (String)buffer; 2095dfecf96Smrg XawTextReplace(output, position, position, &block); 2105dfecf96Smrg XawTextSetInsertionPoint(output, position + block.length); 2115dfecf96Smrg disable_timeout = 0; 2125dfecf96Smrg 2135dfecf96Smrg if (request_timeout) { 2145dfecf96Smrg XFlush(XtDisplay(output)); 2155dfecf96Smrg request_timeout = 0; 2165dfecf96Smrg SigalrmHandler(SIGALRM); 2175dfecf96Smrg } 2185dfecf96Smrg 2195dfecf96Smrg return ((ssize_t)nbytes); 2205dfecf96Smrg} 2215dfecf96Smrg 2225dfecf96Smrgstatic ssize_t 2235dfecf96SmrgWriteToStdout(int fd, const void *buffer, size_t nbytes) 2245dfecf96Smrg{ 2255dfecf96Smrg return (WrapWrite(textwindow, buffer, nbytes)); 2265dfecf96Smrg} 2275dfecf96Smrg 2285dfecf96Smrgstatic ssize_t 2295dfecf96SmrgWriteToStderr(int fd, const void *buffer, size_t nbytes) 2305dfecf96Smrg{ 2315dfecf96Smrg return (WrapWrite(messwidget, buffer, nbytes)); 2325dfecf96Smrg} 2335dfecf96Smrg 2345dfecf96Smrgvoid 2355dfecf96SmrgLispXeditInitialize(void) 2365dfecf96Smrg{ 2375dfecf96Smrg int i; 2385dfecf96Smrg char *string; 2395dfecf96Smrg LispObj *xedit, *list, *savepackage; 2405dfecf96Smrg 2415dfecf96Smrg LispSetFileWrite(Stdout, WriteToStdout); 2425dfecf96Smrg LispSetFileWrite(Stderr, WriteToStderr); 2435dfecf96Smrg 2445dfecf96Smrg justify_modes[0] = KEYWORD("LEFT"); 2455dfecf96Smrg justify_modes[1] = KEYWORD("RIGHT"); 2465dfecf96Smrg justify_modes[2] = KEYWORD("CENTER"); 2475dfecf96Smrg justify_modes[3] = KEYWORD("FULL"); 2485dfecf96Smrg 2495dfecf96Smrg wrap_modes[0] = KEYWORD("NEVER"); 2505dfecf96Smrg wrap_modes[1] = KEYWORD("LINE"); 2515dfecf96Smrg wrap_modes[2] = KEYWORD("WORD"); 2525dfecf96Smrg 2535dfecf96Smrg scan_types[0] = KEYWORD("POSITIONS"); 2545dfecf96Smrg scan_types[1] = KEYWORD("WHITE-SPACE"); 2555dfecf96Smrg scan_types[2] = KEYWORD("EOL"); 2565dfecf96Smrg scan_types[3] = KEYWORD("PARAGRAPH"); 2575dfecf96Smrg scan_types[4] = KEYWORD("ALL"); 2585dfecf96Smrg scan_types[5] = KEYWORD("ALPHA-NUMERIC"); 2595dfecf96Smrg 2605dfecf96Smrg scan_directions[0] = justify_modes[0]; 2615dfecf96Smrg scan_directions[1] = justify_modes[1]; 2625dfecf96Smrg 2635dfecf96Smrg /* Remember value of current package */ 2645dfecf96Smrg savepackage = PACKAGE; 2655dfecf96Smrg 2665dfecf96Smrg /* Create the XEDIT package */ 2675dfecf96Smrg xedit = LispNewPackage(STRING("XEDIT"), NIL); 2685dfecf96Smrg 2695dfecf96Smrg /* Update list of packages */ 2705dfecf96Smrg PACK = CONS(xedit, PACK); 2715dfecf96Smrg 2725dfecf96Smrg /* Temporarily switch to the XEDIT package */ 2735dfecf96Smrg lisp__data.pack = lisp__data.savepack = xedit->data.package.package; 2745dfecf96Smrg PACKAGE = xedit; 2755dfecf96Smrg 2765dfecf96Smrg /* Add XEDIT builtin functions */ 2775dfecf96Smrg for (i = 0; i < sizeof(xeditbuiltins) / sizeof(xeditbuiltins[0]); i++) 2785dfecf96Smrg LispAddBuiltinFunction(&xeditbuiltins[i]); 2795dfecf96Smrg 2805dfecf96Smrg /* Create these objects in the xedit package */ 2815dfecf96Smrg Oauto_modes = STATIC_ATOM("*AUTO-MODES*"); 2825dfecf96Smrg Oauto_mode = STATIC_ATOM("AUTO-MODE"); 2835dfecf96Smrg Osyntax_highlight = STATIC_ATOM("SYNTAX-HIGHLIGHT"); 2845dfecf96Smrg Osyntable_indent = STATIC_ATOM("SYNTABLE-INDENT"); 2855dfecf96Smrg 2865dfecf96Smrg /* Import symbols from the LISP and EXT packages */ 2875dfecf96Smrg for (list = PACK; CONSP(list); list = CDR(list)) { 2885dfecf96Smrg string = THESTR(CAR(list)->data.package.name); 2895dfecf96Smrg if (strcmp(string, "LISP") == 0 || strcmp(string, "EXT") == 0) 2905dfecf96Smrg LispUsePackage(CAR(list)); 2915dfecf96Smrg } 2925dfecf96Smrg 2935dfecf96Smrg /* Restore previous package */ 2945dfecf96Smrg lisp__data.pack = savepackage->data.package.package; 2955dfecf96Smrg PACKAGE = savepackage; 2965dfecf96Smrg 2975dfecf96Smrg /* Initialize helper static objects used when executing expressions */ 2985dfecf96Smrg execute_stream.type = LispStream_t; 2995dfecf96Smrg execute_stream.data.stream.source.string = &execute_string; 3005dfecf96Smrg execute_stream.data.stream.pathname = NIL; 3015dfecf96Smrg execute_stream.data.stream.type = LispStreamString; 3025dfecf96Smrg execute_stream.data.stream.readable = 1; 3035dfecf96Smrg execute_stream.data.stream.writable = 0; 3045dfecf96Smrg execute_string.output = 0; 3055dfecf96Smrg result_stream.type = LispStream_t; 3065dfecf96Smrg result_stream.data.stream.source.string = &result_string; 3075dfecf96Smrg result_stream.data.stream.pathname = NIL; 3085dfecf96Smrg result_stream.data.stream.type = LispStreamString; 3095dfecf96Smrg result_stream.data.stream.readable = 0; 3105dfecf96Smrg result_stream.data.stream.writable = 1; 3115dfecf96Smrg result_string.string = XtMalloc(pagesize); 3125dfecf96Smrg result_string.space = pagesize; 3135dfecf96Smrg 3145dfecf96Smrg /* Initialize interactive edition function arguments */ 3155dfecf96Smrg /* first argument is syntax table */ 3165dfecf96Smrg interactive_arguments[0].type = LispCons_t; 3175dfecf96Smrg interactive_arguments[0].data.cons.cdr = &interactive_arguments[1]; 3185dfecf96Smrg /* second argument is where to start reparsing */ 3195dfecf96Smrg interactive_arguments[1].type = LispCons_t; 3205dfecf96Smrg interactive_arguments[1].data.cons.cdr = &interactive_arguments[2]; 3215dfecf96Smrg /* third argument is where to stop reparsing */ 3225dfecf96Smrg interactive_arguments[2].type = LispCons_t; 3235dfecf96Smrg interactive_arguments[2].data.cons.cdr = &interactive_arguments[3]; 3245dfecf96Smrg /* fourth argument is interactive flag */ 3255dfecf96Smrg interactive_arguments[3].type = LispCons_t; 3265dfecf96Smrg interactive_arguments[3].data.cons.car = T; 3275dfecf96Smrg interactive_arguments[3].data.cons.cdr = NIL; 3285dfecf96Smrg 3295dfecf96Smrg /* Load extra functions and data type definitions */ 3305dfecf96Smrg EXECUTE("(require \"xedit\")"); 3315dfecf96Smrg 3325dfecf96Smrg 3335dfecf96Smrg /* 3345dfecf96Smrg * This assumes that the *auto-modes* variable is a list where every 3355dfecf96Smrg * item has the format: 3365dfecf96Smrg * (regexp string-desc load-file-desc . symbol-name) 3375dfecf96Smrg * Minimal error checking is done. 3385dfecf96Smrg */ 3395dfecf96Smrg 3405dfecf96Smrg if (Oauto_modes->data.atom->a_object) { 3415dfecf96Smrg LispObj *desc, *modes = Oauto_modes->data.atom->property->value; 3425dfecf96Smrg 3435dfecf96Smrg for (; CONSP(modes); modes = CDR(modes)) { 3445dfecf96Smrg list = CAR(modes); 3455dfecf96Smrg 3465dfecf96Smrg desc = NIL; 3475dfecf96Smrg for (i = 0; i < 3 && CONSP(list); i++, list = CDR(list)) { 3485dfecf96Smrg if (i == 1) 3495dfecf96Smrg desc = CAR(list); 3505dfecf96Smrg } 3515dfecf96Smrg if (i == 3 && STRINGP(desc)) { 3525dfecf96Smrg mode_infos = (EditModeInfo*) 3535dfecf96Smrg XtRealloc((XtPointer)mode_infos, sizeof(EditModeInfo) * 3545dfecf96Smrg (num_mode_infos + 1)); 3555dfecf96Smrg mode_infos[num_mode_infos].desc = XtNewString(THESTR(desc)); 3565dfecf96Smrg mode_infos[num_mode_infos].symbol = list; 3575dfecf96Smrg mode_infos[num_mode_infos].syntax = NULL; 3585dfecf96Smrg ++num_mode_infos; 3595dfecf96Smrg } 3605dfecf96Smrg } 3615dfecf96Smrg } 3625dfecf96Smrg} 3635dfecf96Smrg 3645dfecf96Smrgstatic void 3655dfecf96SmrgXeditUpdateModeInfos(void) 3665dfecf96Smrg{ 3675dfecf96Smrg int i; 3685dfecf96Smrg 3695dfecf96Smrg for (i = 0; i < num_mode_infos; i++) { 3705dfecf96Smrg if (mode_infos[i].symbol && 3715dfecf96Smrg mode_infos[i].syntax == NULL && 3725dfecf96Smrg XSYMBOLP(mode_infos[i].symbol) && 3735dfecf96Smrg mode_infos[i].symbol->data.atom->a_object) 3745dfecf96Smrg mode_infos[i].syntax = 3755dfecf96Smrg mode_infos[i].symbol->data.atom->property->value; 3765dfecf96Smrg } 3775dfecf96Smrg} 3785dfecf96Smrg 3795dfecf96Smrgvoid 3805dfecf96SmrgXeditLispExecute(Widget output, XawTextPosition left, XawTextPosition right) 3815dfecf96Smrg{ 3825dfecf96Smrg GC_ENTER(); 3835dfecf96Smrg LISP_SETUP(); 3845dfecf96Smrg int alloced, return_count; 3855dfecf96Smrg XawTextBlock block; 3865dfecf96Smrg XawTextPosition position; 3875dfecf96Smrg char *string, *ptr; 3885dfecf96Smrg LispObj *result, *code, *_cod, *returns; 3895dfecf96Smrg 3905dfecf96Smrg LISP_ENTER(); 3915dfecf96Smrg 3925dfecf96Smrg position = left; 3935dfecf96Smrg XawTextSourceRead(XawTextGetSource(textwindow), left, &block, right - left); 3945dfecf96Smrg if (block.length < right - left) { 3955dfecf96Smrg alloced = 1; 3965dfecf96Smrg string = ptr = LispMalloc(right - left); 3975dfecf96Smrg memcpy(ptr, block.ptr, block.length); 3985dfecf96Smrg position = left + block.length; 3995dfecf96Smrg ptr += block.length; 4005dfecf96Smrg for (; position < right;) { 4015dfecf96Smrg XawTextSourceRead(XawTextGetSource(textwindow), 4025dfecf96Smrg position, &block, right - position); 4035dfecf96Smrg memcpy(ptr, block.ptr, block.length); 4045dfecf96Smrg position += block.length; 4055dfecf96Smrg ptr += block.length; 4065dfecf96Smrg } 4075dfecf96Smrg } 4085dfecf96Smrg else { 4095dfecf96Smrg alloced = 0; 4105dfecf96Smrg string = block.ptr; 4115dfecf96Smrg } 4125dfecf96Smrg 4135dfecf96Smrg execute_string.string = string; 4145dfecf96Smrg execute_string.length = right - left; 4155dfecf96Smrg execute_string.input = 0; 4165dfecf96Smrg LispPushInput(&execute_stream); 4175dfecf96Smrg _cod = COD; 4185dfecf96Smrg result = NIL; 4195dfecf96Smrg if ((code = LispRead()) != NULL) 4205dfecf96Smrg result = EVAL(code); 4215dfecf96Smrg COD = _cod; 4225dfecf96Smrg LispPopInput(&execute_stream); 4235dfecf96Smrg 4245dfecf96Smrg returns = NIL; 4255dfecf96Smrg if (RETURN_COUNT > 0) { 4265dfecf96Smrg GC_PROTECT(result); 4275dfecf96Smrg returns = _cod = CONS(RETURN(0), NIL); 4285dfecf96Smrg GC_PROTECT(returns); 4295dfecf96Smrg for (return_count = 1; return_count < RETURN_COUNT; return_count++) { 4305dfecf96Smrg RPLACD(_cod, CONS(RETURN(return_count), NIL)); 4315dfecf96Smrg _cod = CDR(_cod); 4325dfecf96Smrg } 4335dfecf96Smrg } 4345dfecf96Smrg LispFflush(Stdout); 4355dfecf96Smrg LispUpdateResults(code, result); 4365dfecf96Smrg if (RETURN_COUNT >= 0) { 4375dfecf96Smrg XeditPrint(output, result, 1); 4385dfecf96Smrg for (; CONSP(returns); returns = CDR(returns)) 4395dfecf96Smrg XeditPrint(output, CAR(returns), 0); 4405dfecf96Smrg } 4415dfecf96Smrg 4425dfecf96Smrg if (alloced) 4435dfecf96Smrg LispFree(string); 4445dfecf96Smrg GC_LEAVE(); 4455dfecf96Smrg 4465dfecf96Smrg LISP_LEAVE(); 4475dfecf96Smrg} 4485dfecf96Smrg 4495dfecf96Smrgstatic void 4505dfecf96SmrgXeditPrint(Widget output, LispObj *object, int newline) 4515dfecf96Smrg{ 4525dfecf96Smrg XawTextBlock block; 4535dfecf96Smrg XawTextPosition position; 4545dfecf96Smrg 4555dfecf96Smrg result_string.length = result_string.output = 0; 4565dfecf96Smrg if (newline) { 4575dfecf96Smrg position = XawTextGetInsertionPoint(output); 4585dfecf96Smrg if (position != XawTextSourceScan(XawTextGetSource(output), 4595dfecf96Smrg position, XawstEOL, 4605dfecf96Smrg XawsdLeft, 1, False)) 4615dfecf96Smrg LispSputc(&result_string, '\n'); 4625dfecf96Smrg } 4635dfecf96Smrg LispWriteObject(&result_stream, object); 4645dfecf96Smrg LispSputc(&result_string, '\n'); 4655dfecf96Smrg 4665dfecf96Smrg position = XawTextGetInsertionPoint(output); 4675dfecf96Smrg block.firstPos = 0; 4685dfecf96Smrg block.format = FMT8BIT; 4695dfecf96Smrg block.length = result_string.length; 4705dfecf96Smrg block.ptr = result_string.string; 4715dfecf96Smrg XawTextReplace(output, position, position, &block); 4725dfecf96Smrg XawTextSetInsertionPoint(output, position + block.length); 4735dfecf96Smrg} 4745dfecf96Smrg 4755dfecf96Smrg/* 4765dfecf96Smrg * This function is defined here to avoid exporting all the lisp interfaces 4775dfecf96Smrg * to the core xedit code. 4785dfecf96Smrg */ 4795dfecf96Smrgvoid 4805dfecf96SmrgXeditLispSetEditMode(xedit_flist_item *item, LispObj *symbol) 4815dfecf96Smrg{ 4825dfecf96Smrg GC_ENTER(); 4835dfecf96Smrg LISP_SETUP(); 4845dfecf96Smrg LispObj *syntax, *name; 4855dfecf96Smrg 4865dfecf96Smrg item->xldata = (XeditLispData*)XtCalloc(1, sizeof(XeditLispData)); 4875dfecf96Smrg 4885dfecf96Smrg LISP_ENTER(); 4895dfecf96Smrg 4905dfecf96Smrg /* Create an object that represents the buffer filename. 4915dfecf96Smrg * Note that the entire path is passed to the auto-mode 4925dfecf96Smrg * function, so that directory names may be also be used 4935dfecf96Smrg * when determining a file type. */ 4945dfecf96Smrg name = STRING(item->filename); 4955dfecf96Smrg GC_PROTECT(name); 4965dfecf96Smrg 4975dfecf96Smrg /* Call the AUTO-MODE function to check if there is a 4985dfecf96Smrg * syntax definition for the file being loaded */ 4995dfecf96Smrg if (symbol == NULL) 5005dfecf96Smrg syntax = APPLY1(Oauto_mode, name); 5015dfecf96Smrg else 5025dfecf96Smrg syntax = APPLY2(Oauto_mode, name, symbol); 5035dfecf96Smrg 5045dfecf96Smrg /* Don't need the name object anymore */ 5055dfecf96Smrg GC_LEAVE(); 5065dfecf96Smrg 5075dfecf96Smrg if (syntax != NIL) { 5085dfecf96Smrg Arg arg[1]; 5095dfecf96Smrg LispObj arguments; 5105dfecf96Smrg XawTextPropertyList *property_list; 5115dfecf96Smrg 5125dfecf96Smrg item->xldata->syntax = syntax; 5135dfecf96Smrg 5145dfecf96Smrg /* Apply the syntax highlight to the current buffer */ 5155dfecf96Smrg arguments.type = LispCons_t; 5165dfecf96Smrg arguments.data.cons.car = syntax; 5175dfecf96Smrg arguments.data.cons.cdr = NIL; 5185dfecf96Smrg LispFuncall(Osyntax_highlight, &arguments, 1); 5195dfecf96Smrg 5205dfecf96Smrg /* The previous call added the property list to the widget, 5215dfecf96Smrg * remember it when switching sources. */ 5225dfecf96Smrg XtSetArg(arg[0], XawNtextProperties, &property_list); 5235dfecf96Smrg XtGetValues(XawTextGetSink(textwindow), arg, 1); 5245dfecf96Smrg item->properties = property_list; 5255dfecf96Smrg 5265dfecf96Smrg /* Add callback for interactive changes */ 5275dfecf96Smrg XtAddCallback(item->source, XtNpropertyCallback, 5285dfecf96Smrg XeditInteractiveCallback, item->xldata); 5295dfecf96Smrg 5305dfecf96Smrg /* Update information as a new file may have been loaded */ 5315dfecf96Smrg XeditUpdateModeInfos(); 5325dfecf96Smrg } 5335dfecf96Smrg else 5345dfecf96Smrg item->properties = NULL; 5355dfecf96Smrg 5365dfecf96Smrg LISP_LEAVE(); 5375dfecf96Smrg} 5385dfecf96Smrg 5395dfecf96Smrgvoid 5405dfecf96SmrgXeditLispUnsetEditMode(xedit_flist_item *item) 5415dfecf96Smrg{ 5425dfecf96Smrg if (item->xldata) { 5435dfecf96Smrg XtRemoveCallback(item->source, XtNpropertyCallback, 5445dfecf96Smrg XeditInteractiveCallback, item->xldata); 5455dfecf96Smrg XtFree((XtPointer)item->xldata); 5465dfecf96Smrg item->xldata = NULL; 5475dfecf96Smrg } 5485dfecf96Smrg} 5495dfecf96Smrg 5505dfecf96Smrg#define MAX_INFOS 32 5515dfecf96Smrg/* 5525dfecf96Smrg * This callback tries to do it's best in generating correct output while 5535dfecf96Smrg * also doing minimal work/redrawing of the screen. It probably will fail 5545dfecf96Smrg * for some syntax-definitions, or will just not properly repaint the 5555dfecf96Smrg * screen. In the later case, just press Ctrl+L. 5565dfecf96Smrg * There isn't yet any command to force reparsing of some regions, and if 5575dfecf96Smrg * the parser becomes confused, you may need to go to a line, press a space 5585dfecf96Smrg * and undo, just to force it to reparse the line, and possibly some extra 5595dfecf96Smrg * lines until the parser thinks the display is in sync. 5605dfecf96Smrg * Sometimes it will repaint a lot more of text than what is being requested 5615dfecf96Smrg * by this callback, this should be fixed at some time, as for certain cases 5625dfecf96Smrg * it is also required some redesign in the Xaw interface. 5635dfecf96Smrg */ 5645dfecf96Smrgstatic void 5655dfecf96SmrgXeditInteractiveCallback(Widget w, XtPointer client_data, XtPointer call_data) 5665dfecf96Smrg{ 5675dfecf96Smrg LISP_SETUP(); 5685dfecf96Smrg XeditLispData *data = (XeditLispData*)client_data; 5695dfecf96Smrg LispObj *syntax = data->syntax; 5705dfecf96Smrg XawTextPropertyInfo *info = (XawTextPropertyInfo*)call_data; 5715dfecf96Smrg LispObj *result, *syntable; 5725dfecf96Smrg XawTextAnchor *anchor; 5735dfecf96Smrg XawTextEntity *entity; 5745dfecf96Smrg XawTextPosition first, last, left, right, begin, next, tmp, position; 5755dfecf96Smrg int i, j, indent; 5765dfecf96Smrg TextSrcObject src = (TextSrcObject)w; 5775dfecf96Smrg EntityInfo oinfo[MAX_INFOS], ninfo[MAX_INFOS]; 5785dfecf96Smrg XrmQuark props[MAX_INFOS]; 5795dfecf96Smrg int num_oinfo, num_ninfo, num_props; 5805dfecf96Smrg XmuScanline *clip, *oclip, *nclip; 5815dfecf96Smrg XmuSegment segment, *seg; 5825dfecf96Smrg 5835dfecf96Smrg if (data->disable_highlight) 5845dfecf96Smrg return; 5855dfecf96Smrg 5865dfecf96Smrg LISP_ENTER(); 5875dfecf96Smrg 5885dfecf96Smrg first = XawTextSourceScan(w, 0, XawstAll, XawsdLeft, 1, True); 5895dfecf96Smrg last = XawTextSourceScan(w, 0, XawstAll, XawsdRight, 1, True); 5905dfecf96Smrg 5915dfecf96Smrg left = info->left; 5925dfecf96Smrg right = left + info->block->length; 5935dfecf96Smrg 5945dfecf96Smrg /* For now, only call the indent hook if a single character was typed */ 5955dfecf96Smrg indent = (info->right == left) && (right == left + 1); 5965dfecf96Smrg 5975dfecf96Smrg /* Always reparse full lines */ 5985dfecf96Smrg left = begin = XawTextSourceScan(w, left, XawstEOL, XawsdLeft, 1, False); 5995dfecf96Smrg right = next = XawTextSourceScan(w, right, XawstEOL, XawsdRight, 1, False); 6005dfecf96Smrg 6015dfecf96Smrg 6025dfecf96Smrg /* Check properties in the modified text. If a complex nested syntax 6035dfecf96Smrg * table was parsed, the newline has it's default property, so, while 6045dfecf96Smrg * the newline has a property, backup a line to make sure everything is 6055dfecf96Smrg * properly parsed. 6065dfecf96Smrg * Maybe should limit the number of backuped lines, but if the parsing 6075dfecf96Smrg * becomes noticeable slow, better to rethink the syntax definition. */ 6085dfecf96Smrg while (left > first) { 6095dfecf96Smrg position = XawTextSourceScan(w, left, XawstEOL, XawsdLeft, 1, True); 6105dfecf96Smrg if (XawTextSourceAnchorAndEntity(w, position, &anchor, &entity)) 6115dfecf96Smrg left = XawTextSourceScan(w, left, XawstEOL, XawsdLeft, 2, False); 6125dfecf96Smrg else 6135dfecf96Smrg break; 6145dfecf96Smrg } 6155dfecf96Smrg 6165dfecf96Smrg /* While the newline after the right position has a "hidden" property, 6175dfecf96Smrg * keep incrementing a line to be reparsed. */ 6185dfecf96Smrg while (right < last) { 6195dfecf96Smrg if (XawTextSourceAnchorAndEntity(w, right, &anchor, &entity)) 6205dfecf96Smrg right = XawTextSourceScan(w, right, XawstEOL, XawsdRight, 2, False); 6215dfecf96Smrg else 6225dfecf96Smrg break; 6235dfecf96Smrg } 6245dfecf96Smrg 6255dfecf96Smrg#ifndef MAX 6265dfecf96Smrg#define MAX(a, b) ((a) > (b) ? (a) : (b)) 6275dfecf96Smrg#endif 6285dfecf96Smrg 6295dfecf96Smrg#ifndef MIN 6305dfecf96Smrg#define MIN(a, b) ((a) < (b) ? (a) : (b)) 6315dfecf96Smrg#endif 6325dfecf96Smrg 6335dfecf96Smrg#define STORE_STATE(count, info, from, to) \ 6345dfecf96Smrg (count) = 0; \ 6355dfecf96Smrg if ((anchor = XawTextSourceFindAnchor(w, (from))) != NULL) { \ 6365dfecf96Smrg entity = anchor->entities; \ 6375dfecf96Smrg /* Find first entity in the region to parse */ \ 6385dfecf96Smrg while (entity && \ 6395dfecf96Smrg anchor->position + entity->offset + entity->length <= \ 6405dfecf96Smrg (from)) \ 6415dfecf96Smrg entity = entity->next; \ 6425dfecf96Smrg /* Loop storing information */ \ 6435dfecf96Smrg while (entity && \ 6445dfecf96Smrg (position = anchor->position + entity->offset) < (to)) { \ 6455dfecf96Smrg (info)[(count)].left = MAX(position, (from)); \ 6465dfecf96Smrg position += entity->length; \ 6475dfecf96Smrg (info)[(count)].right = MIN(position, (to)); \ 6485dfecf96Smrg (info)[(count)].property = entity->property; \ 6495dfecf96Smrg /* If the changes are so complex, user need press Ctrl+L */ \ 6505dfecf96Smrg if (++(count) >= MAX_INFOS) \ 6515dfecf96Smrg break; \ 6525dfecf96Smrg if ((entity = entity->next) == NULL && \ 6535dfecf96Smrg (anchor = XawTextSourceNextAnchor(w, anchor)) != NULL) \ 6545dfecf96Smrg entity = anchor->entities; \ 6555dfecf96Smrg } \ 6565dfecf96Smrg } 6575dfecf96Smrg 6585dfecf96Smrg /* Remember old state */ 6595dfecf96Smrg STORE_STATE(num_oinfo, oinfo, begin, right); 6605dfecf96Smrg 6615dfecf96Smrg /* Reparse the lines in the modified/edited range of text */ 6625dfecf96Smrg interactive_arguments[0].data.cons.car = syntax; 6635dfecf96Smrg interactive_arguments[1].data.cons.car = FIXNUM(left); 6645dfecf96Smrg interactive_arguments[2].data.cons.car = FIXNUM(right); 6655dfecf96Smrg result = APPLY(Osyntax_highlight, &interactive_arguments[0]); 6665dfecf96Smrg /* Indent table is the second return value */ 6675dfecf96Smrg if (RETURN_COUNT) 6685dfecf96Smrg syntable = RETURN(0); 6695dfecf96Smrg else 6705dfecf96Smrg syntable = NIL; 6715dfecf96Smrg 6725dfecf96Smrg /* This normally is the same value as right, but the parser may have 6735dfecf96Smrg * continued when the syntax table stack did not finish. */ 6745dfecf96Smrg if (FIXNUMP(result)) 6755dfecf96Smrg right = FIXNUM_VALUE(result); 6765dfecf96Smrg 6775dfecf96Smrg LISP_LEAVE(); 6785dfecf96Smrg 6795dfecf96Smrg /* Check what have changed */ 6805dfecf96Smrg STORE_STATE(num_ninfo, ninfo, begin, right); 6815dfecf96Smrg 6825dfecf96Smrg /* Initialize to redraw everything. */ 6835dfecf96Smrg clip = XmuNewScanline(0, begin, right); 6845dfecf96Smrg 6855dfecf96Smrg#define CLIP_MASK(mask, from, to) \ 6865dfecf96Smrg if ((from) < (to)) { \ 6875dfecf96Smrg segment.x1 = (from); \ 6885dfecf96Smrg segment.x2 = (to); \ 6895dfecf96Smrg XmuScanlineOrSegment((mask), &segment); \ 6905dfecf96Smrg } 6915dfecf96Smrg 6925dfecf96Smrg oclip = XmuNewScanline(0, 0, 0); 6935dfecf96Smrg nclip = XmuNewScanline(0, 0, 0); 6945dfecf96Smrg 6955dfecf96Smrg#define CLIP_DEFAULT(mask, from, info, num_info) \ 6965dfecf96Smrg for (tmp = (from), i = 0; i < (num_info); i++) { \ 6975dfecf96Smrg CLIP_MASK((mask), tmp, (info)[i].left); \ 6985dfecf96Smrg tmp = (info)[i].right; \ 6995dfecf96Smrg } 7005dfecf96Smrg 7015dfecf96Smrg /* First generate masks of regions with the default property */ 7025dfecf96Smrg CLIP_DEFAULT(oclip, begin, oinfo, num_oinfo); 7035dfecf96Smrg CLIP_DEFAULT(nclip, begin, ninfo, num_ninfo); 7045dfecf96Smrg 7055dfecf96Smrg /* Store unchanged region in oclip */ 7065dfecf96Smrg XmuScanlineAnd(oclip, nclip); 7075dfecf96Smrg 7085dfecf96Smrg /* Don't need to redraw the region in oclip */ 7095dfecf96Smrg XmuScanlineXor(clip, oclip); 7105dfecf96Smrg 7115dfecf96Smrg#define LIST_PROPERTIES(prop, num_prop, info, num_info) \ 7125dfecf96Smrg (num_prop) = 0; \ 7135dfecf96Smrg for (i = 0; i < (num_info); i++) { \ 7145dfecf96Smrg for (j = 0; j < (num_prop); j++) \ 7155dfecf96Smrg if ((prop)[j] == (info)[i].property) \ 7165dfecf96Smrg break; \ 7175dfecf96Smrg if (j == (num_prop)) \ 7185dfecf96Smrg (prop)[(num_prop)++] = (info)[i].property; \ 7195dfecf96Smrg } 7205dfecf96Smrg 7215dfecf96Smrg /* Prepare to generate masks of regions of text with defined properties */ 7225dfecf96Smrg LIST_PROPERTIES(props, num_props, oinfo, num_oinfo); 7235dfecf96Smrg 7245dfecf96Smrg#define CLIP_PROPERTY(mask, prop, info, num_info) \ 7255dfecf96Smrg for (j = 0; j < (num_info); j++) { \ 7265dfecf96Smrg if ((info)[j].property == (prop)) { \ 7275dfecf96Smrg CLIP_MASK((mask), (info)[j].left, (info)[j].right); \ 7285dfecf96Smrg } \ 7295dfecf96Smrg } 7305dfecf96Smrg 7315dfecf96Smrg /* Only care about the old properties, new ones need to be redrawn */ 7325dfecf96Smrg for (i = 0; i < num_props; i++) { 7335dfecf96Smrg XrmQuark property = props[i]; 7345dfecf96Smrg 7355dfecf96Smrg /* Reset oclip and nclip */ 7365dfecf96Smrg XmuScanlineXor(oclip, oclip); 7375dfecf96Smrg XmuScanlineXor(nclip, nclip); 7385dfecf96Smrg 7395dfecf96Smrg /* Generate masks */ 7405dfecf96Smrg CLIP_PROPERTY(oclip, property, oinfo, num_oinfo); 7415dfecf96Smrg CLIP_PROPERTY(nclip, property, ninfo, num_ninfo); 7425dfecf96Smrg 7435dfecf96Smrg /* Store unchanged region in oclip */ 7445dfecf96Smrg XmuScanlineAnd(oclip, nclip); 7455dfecf96Smrg 7465dfecf96Smrg /* Don't need to redraw the region in oclip */ 7475dfecf96Smrg XmuScanlineXor(clip, oclip); 7485dfecf96Smrg XmuOptimizeScanline(clip); 7495dfecf96Smrg } 7505dfecf96Smrg 7515dfecf96Smrg XmuDestroyScanline(oclip); 7525dfecf96Smrg XmuDestroyScanline(nclip); 7535dfecf96Smrg 7545dfecf96Smrg /* Tell Xaw that need update some regions */ 7555dfecf96Smrg for (seg = clip->segment; seg; seg = seg->next) { 7565dfecf96Smrg for (i = 0; i < src->textSrc.num_text; i++) 7575dfecf96Smrg /* This really should have an exported interface... */ 7585dfecf96Smrg _XawTextNeedsUpdating((TextWidget)(src->textSrc.text[i]), 7595dfecf96Smrg seg->x1, seg->x2 + (seg->x2 > next)); 7605dfecf96Smrg } 7615dfecf96Smrg XmuDestroyScanline(clip); 7625dfecf96Smrg 7635dfecf96Smrg data->syntable = syntable; 7645dfecf96Smrg /* XXX check lisp__running to know if at the toplevel parsing state */ 7655dfecf96Smrg if (indent && syntable != NIL && !lisp__running && 7665dfecf96Smrg /* Doing an undo, probably will need an exported interface for this 7675dfecf96Smrg * case. Should not change the text now. */ 7685dfecf96Smrg (!src->textSrc.enable_undo || !src->textSrc.undo_state)) 7695dfecf96Smrg XtAddCallback(textwindow, XtNpositionCallback, 7705dfecf96Smrg XeditIndentationCallback, data); 7715dfecf96Smrg} 7725dfecf96Smrg 7735dfecf96Smrg/* 7745dfecf96Smrg * This callback is called if the syntax table where the cursor is located 7755dfecf96Smrg * defines an indentation function. 7765dfecf96Smrg */ 7775dfecf96Smrgstatic void 7785dfecf96SmrgXeditIndentationCallback(Widget w, XtPointer client_data, XtPointer call_data) 7795dfecf96Smrg{ 7805dfecf96Smrg LISP_SETUP(); 7815dfecf96Smrg LispObj *indentp; 7825dfecf96Smrg XeditLispData *data = (XeditLispData*)client_data; 7835dfecf96Smrg 7845dfecf96Smrg data->disable_highlight = True; 7855dfecf96Smrg XtRemoveCallback(w, XtNpositionCallback, XeditIndentationCallback, data); 7865dfecf96Smrg 7875dfecf96Smrg LISP_ENTER(); 7885dfecf96Smrg 7895dfecf96Smrg /* Get pointer to indentation function */ 7905dfecf96Smrg indentp = APPLY1(Osyntable_indent, data->syntable); 7915dfecf96Smrg 7925dfecf96Smrg /* Execute indentation function */ 7935dfecf96Smrg if (indentp != NIL) 7945dfecf96Smrg APPLY2(indentp, data->syntax, data->syntable); 7955dfecf96Smrg 7965dfecf96Smrg data->disable_highlight = False; 7975dfecf96Smrg 7985dfecf96Smrg LISP_LEAVE(); 7995dfecf96Smrg} 8005dfecf96Smrg 8015dfecf96Smrg/************************************************************************ 8025dfecf96Smrg * Builtin functions 8035dfecf96Smrg ************************************************************************/ 8045dfecf96SmrgLispObj * 8055dfecf96SmrgXedit_AddEntity(LispBuiltin *builtin) 8065dfecf96Smrg/* 8075dfecf96Smrg add-entity offset length identifier 8085dfecf96Smrg */ 8095dfecf96Smrg{ 8105dfecf96Smrg LispObj *offset, *length, *identifier; 8115dfecf96Smrg 8125dfecf96Smrg identifier = ARGUMENT(2); 8135dfecf96Smrg length = ARGUMENT(1); 8145dfecf96Smrg offset = ARGUMENT(0); 8155dfecf96Smrg 8165dfecf96Smrg CHECK_INDEX(offset); 8175dfecf96Smrg CHECK_INDEX(length); 8185dfecf96Smrg CHECK_LONGINT(identifier); 8195dfecf96Smrg 8205dfecf96Smrg return (XawTextSourceAddEntity(XawTextGetSource(textwindow), 0, 0, NULL, 8215dfecf96Smrg FIXNUM_VALUE(offset), FIXNUM_VALUE(length), 8225dfecf96Smrg LONGINT_VALUE(identifier)) ? T : NIL); 8235dfecf96Smrg} 8245dfecf96Smrg 8255dfecf96SmrgLispObj * 8265dfecf96SmrgXedit_AutoFill(LispBuiltin *builtin) 8275dfecf96Smrg/* 8285dfecf96Smrg auto-fill &optional value 8295dfecf96Smrg */ 8305dfecf96Smrg{ 8315dfecf96Smrg Arg arg[1]; 8325dfecf96Smrg Boolean state; 8335dfecf96Smrg 8345dfecf96Smrg LispObj *value; 8355dfecf96Smrg 8365dfecf96Smrg value = ARGUMENT(0); 8375dfecf96Smrg 8385dfecf96Smrg if (value != UNSPEC) { 8395dfecf96Smrg XtSetArg(arg[0], XtNautoFill, value == NIL ? False : True); 8405dfecf96Smrg XtSetValues(textwindow, arg, 1); 8415dfecf96Smrg } 8425dfecf96Smrg else { 8435dfecf96Smrg XtSetArg(arg[0], XtNautoFill, &state); 8445dfecf96Smrg XtGetValues(textwindow, arg, 1); 8455dfecf96Smrg value = state ? T : NIL; 8465dfecf96Smrg } 8475dfecf96Smrg 8485dfecf96Smrg return (value); 8495dfecf96Smrg} 8505dfecf96Smrg 8515dfecf96SmrgLispObj * 8525dfecf96SmrgXedit_Background(LispBuiltin *builtin) 8535dfecf96Smrg/* 8545dfecf96Smrg background &optional color 8555dfecf96Smrg */ 8565dfecf96Smrg{ 8575dfecf96Smrg Pixel pixel; 8585dfecf96Smrg Arg arg[1]; 8595dfecf96Smrg XrmValue from, to; 8605dfecf96Smrg 8615dfecf96Smrg LispObj *color; 8625dfecf96Smrg 8635dfecf96Smrg color = ARGUMENT(0); 8645dfecf96Smrg 8655dfecf96Smrg if (color != UNSPEC) { 8665dfecf96Smrg CHECK_STRING(color); 8675dfecf96Smrg 8685dfecf96Smrg from.size = STRLEN(color); 8695dfecf96Smrg from.addr = (XtPointer)THESTR(color); 8705dfecf96Smrg to.size = sizeof(Pixel); 8715dfecf96Smrg to.addr = (XtPointer)&pixel; 8725dfecf96Smrg 8735dfecf96Smrg if (!XtConvertAndStore(XawTextGetSink(textwindow), 8745dfecf96Smrg XtRString, &from, XtRPixel, &to)) 8755dfecf96Smrg LispDestroy("cannot convert %s to Pixel", STROBJ(color)); 8765dfecf96Smrg 8775dfecf96Smrg XtSetArg(arg[0], XtNbackground, pixel); 8785dfecf96Smrg XtSetValues(textwindow, arg, 1); 8795dfecf96Smrg } 8805dfecf96Smrg else { 8815dfecf96Smrg from.size = sizeof(Pixel); 8825dfecf96Smrg from.addr = (XtPointer)&pixel; 8835dfecf96Smrg to.size = 0; 8845dfecf96Smrg to.addr = NULL; 8855dfecf96Smrg 8865dfecf96Smrg XtSetArg(arg[0], XtNbackground, &pixel); 8875dfecf96Smrg XtGetValues(XawTextGetSink(textwindow), arg, 1); 8885dfecf96Smrg /* This cannot fail */ 8895dfecf96Smrg XtConvertAndStore(textwindow, XtRPixel, &from, XtRString, &to); 8905dfecf96Smrg 8915dfecf96Smrg color = STRING(to.addr); 8925dfecf96Smrg } 8935dfecf96Smrg 8945dfecf96Smrg return (color); 8955dfecf96Smrg} 8965dfecf96Smrg 8975dfecf96Smrgstatic LispObj * 8985dfecf96SmrgXeditCharAt(LispBuiltin *builtin, int before) 8995dfecf96Smrg{ 9005dfecf96Smrg Widget source = XawTextGetSource(textwindow); 9015dfecf96Smrg XawTextPosition first, point, last; 9025dfecf96Smrg XawTextBlock block; 9035dfecf96Smrg 9045dfecf96Smrg LispObj *offset; 9055dfecf96Smrg 9065dfecf96Smrg offset = ARGUMENT(0); 9075dfecf96Smrg if (offset != UNSPEC) { 9085dfecf96Smrg CHECK_INDEX(offset); 9095dfecf96Smrg } 9105dfecf96Smrg 9115dfecf96Smrg first = XawTextSourceScan(source, 0, XawstAll, XawsdLeft, 1, True); 9125dfecf96Smrg if (FIXNUMP(offset)) 9135dfecf96Smrg point = FIXNUM_VALUE(offset); 9145dfecf96Smrg else 9155dfecf96Smrg point = XawTextGetInsertionPoint(textwindow); 9165dfecf96Smrg if (before && point > first) { 9175dfecf96Smrg XawTextPosition position = 9185dfecf96Smrg XawTextSourceScan(source, point, XawstPositions, XawsdLeft, 1, True); 9195dfecf96Smrg 9205dfecf96Smrg if (position < point) 9215dfecf96Smrg point = position; 9225dfecf96Smrg else 9235dfecf96Smrg return (NIL); 9245dfecf96Smrg } 9255dfecf96Smrg last = XawTextSourceScan(source, 0, XawstAll, XawsdRight, 1, True); 9265dfecf96Smrg 9275dfecf96Smrg if (point < first || point > last) 9285dfecf96Smrg return (NIL); 9295dfecf96Smrg 9305dfecf96Smrg XawTextSourceRead(source, point, &block, 1); 9315dfecf96Smrg 9325dfecf96Smrg return (block.length ? SCHAR(*(unsigned char*)block.ptr) : NIL); 9335dfecf96Smrg} 9345dfecf96Smrg 9355dfecf96SmrgLispObj * 9365dfecf96SmrgXedit_CharAfter(LispBuiltin *builtin) 9375dfecf96Smrg/* 9385dfecf96Smrg char-after &optional offset 9395dfecf96Smrg */ 9405dfecf96Smrg{ 9415dfecf96Smrg return (XeditCharAt(builtin, 0)); 9425dfecf96Smrg} 9435dfecf96Smrg 9445dfecf96SmrgLispObj * 9455dfecf96SmrgXedit_CharBefore(LispBuiltin *builtin) 9465dfecf96Smrg/* 9475dfecf96Smrg char-before &optional offset 9485dfecf96Smrg */ 9495dfecf96Smrg{ 9505dfecf96Smrg return (XeditCharAt(builtin, 1)); 9515dfecf96Smrg} 9525dfecf96Smrg 9535dfecf96SmrgLispObj * 9545dfecf96SmrgXedit_ClearEntities(LispBuiltin *builtin) 9555dfecf96Smrg/* 9565dfecf96Smrg clear-entities left right 9575dfecf96Smrg */ 9585dfecf96Smrg{ 9595dfecf96Smrg LispObj *left, *right; 9605dfecf96Smrg 9615dfecf96Smrg right = ARGUMENT(1); 9625dfecf96Smrg left = ARGUMENT(0); 9635dfecf96Smrg 9645dfecf96Smrg CHECK_INDEX(left); 9655dfecf96Smrg CHECK_INDEX(right); 9665dfecf96Smrg 9675dfecf96Smrg XawTextSourceClearEntities(XawTextGetSource(textwindow), 9685dfecf96Smrg FIXNUM_VALUE(left), FIXNUM_VALUE(right)); 9695dfecf96Smrg 9705dfecf96Smrg return (T); 9715dfecf96Smrg} 9725dfecf96Smrg 9735dfecf96SmrgLispObj * 9745dfecf96SmrgXedit_ConvertPropertyList(LispBuiltin *builtin) 9755dfecf96Smrg/* 9765dfecf96Smrg convert-property-list name definition 9775dfecf96Smrg */ 9785dfecf96Smrg{ 9795dfecf96Smrg LispObj *result; 9805dfecf96Smrg XawTextPropertyList *property_list; 9815dfecf96Smrg 9825dfecf96Smrg LispObj *name, *definition; 9835dfecf96Smrg 9845dfecf96Smrg definition = ARGUMENT(1); 9855dfecf96Smrg name = ARGUMENT(0); 9865dfecf96Smrg 9875dfecf96Smrg CHECK_STRING(name); 9885dfecf96Smrg CHECK_STRING(definition); 9895dfecf96Smrg 9905dfecf96Smrg result = NIL; 9915dfecf96Smrg property_list = XawTextSinkConvertPropertyList(THESTR(name), 9925dfecf96Smrg THESTR(definition), 9935dfecf96Smrg topwindow->core.screen, 9945dfecf96Smrg topwindow->core.colormap, 9955dfecf96Smrg topwindow->core.depth); 9965dfecf96Smrg 9975dfecf96Smrg if (property_list) { 9985dfecf96Smrg Cardinal i; 9995dfecf96Smrg 10005dfecf96Smrg for (i = 0; i < num_property_lists; i++) 10015dfecf96Smrg /* Check if a new property list was created */ 10025dfecf96Smrg if (property_lists[i]->identifier == property_list->identifier) 10035dfecf96Smrg break; 10045dfecf96Smrg 10055dfecf96Smrg /* Remember this pointer when asked back for it */ 10065dfecf96Smrg if (i == num_property_lists) { 10075dfecf96Smrg property_lists = (XawTextPropertyList**) 10085dfecf96Smrg XtRealloc((XtPointer)property_lists, 10095dfecf96Smrg sizeof(XawTextPropertyList) * 10105dfecf96Smrg (num_property_lists + 1)); 10115dfecf96Smrg property_lists[num_property_lists++] = property_list; 10125dfecf96Smrg } 10135dfecf96Smrg result = INTEGER(property_list->identifier); 10145dfecf96Smrg } 10155dfecf96Smrg 10165dfecf96Smrg return (result); 10175dfecf96Smrg} 10185dfecf96Smrg 10195dfecf96SmrgLispObj * 10205dfecf96SmrgXedit_Font(LispBuiltin *builtin) 10215dfecf96Smrg/* 10225dfecf96Smrg font &optional font 10235dfecf96Smrg */ 10245dfecf96Smrg{ 10255dfecf96Smrg XFontStruct *font_struct; 10265dfecf96Smrg Arg arg[1]; 10275dfecf96Smrg XrmValue from, to; 10285dfecf96Smrg 10295dfecf96Smrg LispObj *font; 10305dfecf96Smrg 10315dfecf96Smrg font = ARGUMENT(0); 10325dfecf96Smrg 10335dfecf96Smrg if (font != UNSPEC) { 10345dfecf96Smrg CHECK_STRING(font); 10355dfecf96Smrg 10365dfecf96Smrg from.size = STRLEN(font); 10375dfecf96Smrg from.addr = (XtPointer)THESTR(font); 10385dfecf96Smrg to.size = sizeof(XFontStruct*); 10395dfecf96Smrg to.addr = (XtPointer)&font_struct; 10405dfecf96Smrg 10415dfecf96Smrg if (!XtConvertAndStore(textwindow, XtRString, &from, XtRFontStruct, &to)) 10425dfecf96Smrg LispDestroy("cannot convert %s to FontStruct", STROBJ(font)); 10435dfecf96Smrg 10445dfecf96Smrg XtSetArg(arg[0], XtNfont, font_struct); 10455dfecf96Smrg XtSetValues(textwindow, arg, 1); 10465dfecf96Smrg } 10475dfecf96Smrg else { 10485dfecf96Smrg from.size = sizeof(XFontStruct*); 10495dfecf96Smrg from.addr = (XtPointer)&font_struct; 10505dfecf96Smrg to.size = 0; 10515dfecf96Smrg to.addr = NULL; 10525dfecf96Smrg 10535dfecf96Smrg XtSetArg(arg[0], XtNfont, &font_struct); 10545dfecf96Smrg XtGetValues(XawTextGetSink(textwindow), arg, 1); 10555dfecf96Smrg /* This cannot fail */ 10565dfecf96Smrg XtConvertAndStore(textwindow, XtRFontStruct, &from, XtRString, &to); 10575dfecf96Smrg 10585dfecf96Smrg font = STRING(to.addr); 10595dfecf96Smrg } 10605dfecf96Smrg 10615dfecf96Smrg return (font); 10625dfecf96Smrg} 10635dfecf96Smrg 10645dfecf96SmrgLispObj * 10655dfecf96SmrgXedit_Foreground(LispBuiltin *builtin) 10665dfecf96Smrg/* 10675dfecf96Smrg foreground &optional color 10685dfecf96Smrg */ 10695dfecf96Smrg{ 10705dfecf96Smrg Pixel pixel; 10715dfecf96Smrg Arg arg[1]; 10725dfecf96Smrg XrmValue from, to; 10735dfecf96Smrg 10745dfecf96Smrg LispObj *color; 10755dfecf96Smrg 10765dfecf96Smrg color = ARGUMENT(0); 10775dfecf96Smrg 10785dfecf96Smrg if (color != UNSPEC) { 10795dfecf96Smrg CHECK_STRING(color); 10805dfecf96Smrg 10815dfecf96Smrg from.size = STRLEN(color); 10825dfecf96Smrg from.addr = (XtPointer)THESTR(color); 10835dfecf96Smrg to.size = sizeof(Pixel); 10845dfecf96Smrg to.addr = (XtPointer)&pixel; 10855dfecf96Smrg 10865dfecf96Smrg if (!XtConvertAndStore(XawTextGetSink(textwindow), 10875dfecf96Smrg XtRString, &from, XtRPixel, &to)) 10885dfecf96Smrg LispDestroy("cannot convert %s to Pixel", STROBJ(color)); 10895dfecf96Smrg 10905dfecf96Smrg XtSetArg(arg[0], XtNforeground, pixel); 10915dfecf96Smrg XtSetValues(textwindow, arg, 1); 10925dfecf96Smrg } 10935dfecf96Smrg else { 10945dfecf96Smrg from.size = sizeof(Pixel); 10955dfecf96Smrg from.addr = (XtPointer)&pixel; 10965dfecf96Smrg to.size = 0; 10975dfecf96Smrg to.addr = NULL; 10985dfecf96Smrg 10995dfecf96Smrg XtSetArg(arg[0], XtNforeground, &pixel); 11005dfecf96Smrg XtGetValues(XawTextGetSink(textwindow), arg, 1); 11015dfecf96Smrg /* This cannot fail */ 11025dfecf96Smrg XtConvertAndStore(textwindow, XtRPixel, &from, XtRString, &to); 11035dfecf96Smrg 11045dfecf96Smrg color = STRING(to.addr); 11055dfecf96Smrg } 11065dfecf96Smrg 11075dfecf96Smrg return (color); 11085dfecf96Smrg} 11095dfecf96Smrg 11105dfecf96SmrgLispObj * 11115dfecf96SmrgXedit_GotoChar(LispBuiltin *builtin) 11125dfecf96Smrg/* 11135dfecf96Smrg goto-char offset 11145dfecf96Smrg */ 11155dfecf96Smrg{ 11165dfecf96Smrg LispObj *offset; 11175dfecf96Smrg XawTextPosition point; 11185dfecf96Smrg 11195dfecf96Smrg offset = ARGUMENT(0); 11205dfecf96Smrg 11215dfecf96Smrg CHECK_INDEX(offset); 11225dfecf96Smrg XawTextSetInsertionPoint(textwindow, FIXNUM_VALUE(offset)); 11235dfecf96Smrg point = XawTextGetInsertionPoint(textwindow); 11245dfecf96Smrg if (point != FIXNUM_VALUE(offset)) 11255dfecf96Smrg offset = FIXNUM(point); 11265dfecf96Smrg 11275dfecf96Smrg return (offset); 11285dfecf96Smrg} 11295dfecf96Smrg 11305dfecf96SmrgLispObj * 11315dfecf96SmrgXedit_HorizontalScrollbar(LispBuiltin *builtin) 11325dfecf96Smrg/* 11335dfecf96Smrg horizontal-scrollbar &optional state 11345dfecf96Smrg */ 11355dfecf96Smrg{ 11365dfecf96Smrg Arg arg[1]; 11375dfecf96Smrg XawTextScrollMode scroll; 11385dfecf96Smrg 11395dfecf96Smrg LispObj *state; 11405dfecf96Smrg 11415dfecf96Smrg state = ARGUMENT(0); 11425dfecf96Smrg 11435dfecf96Smrg if (state != UNSPEC) { 11445dfecf96Smrg scroll = state == NIL ? XawtextScrollNever : XawtextScrollAlways; 11455dfecf96Smrg XtSetArg(arg[0], XtNscrollHorizontal, scroll); 11465dfecf96Smrg XtSetValues(textwindow, arg, 1); 11475dfecf96Smrg } 11485dfecf96Smrg else { 11495dfecf96Smrg XtSetArg(arg[0], XtNscrollHorizontal, &scroll); 11505dfecf96Smrg XtGetValues(textwindow, arg, 1); 11515dfecf96Smrg state = scroll == XawtextScrollAlways ? T : NIL; 11525dfecf96Smrg } 11535dfecf96Smrg 11545dfecf96Smrg return (state); 11555dfecf96Smrg} 11565dfecf96Smrg 11575dfecf96SmrgLispObj * 11585dfecf96SmrgXedit_Insert(LispBuiltin *builtin) 11595dfecf96Smrg/* 11605dfecf96Smrg insert text 11615dfecf96Smrg */ 11625dfecf96Smrg{ 11635dfecf96Smrg XawTextPosition point = XawTextGetInsertionPoint(textwindow); 11645dfecf96Smrg XawTextBlock block; 11655dfecf96Smrg 11665dfecf96Smrg LispObj *text; 11675dfecf96Smrg 11685dfecf96Smrg text = ARGUMENT(0); 11695dfecf96Smrg 11705dfecf96Smrg CHECK_STRING(text); 11715dfecf96Smrg 11725dfecf96Smrg block.firstPos = 0; 11735dfecf96Smrg block.format = FMT8BIT; 11745dfecf96Smrg block.length = STRLEN(text); 11755dfecf96Smrg block.ptr = THESTR(text); 11765dfecf96Smrg XawTextReplace(textwindow, point, point, &block); 11775dfecf96Smrg XawTextSetInsertionPoint(textwindow, point + block.length); 11785dfecf96Smrg 11795dfecf96Smrg return (text); 11805dfecf96Smrg} 11815dfecf96Smrg 11825dfecf96SmrgLispObj * 11835dfecf96SmrgXedit_Justification(LispBuiltin *builtin) 11845dfecf96Smrg/* 11855dfecf96Smrg justification &optional value 11865dfecf96Smrg */ 11875dfecf96Smrg{ 11885dfecf96Smrg int i; 11895dfecf96Smrg Arg arg[1]; 11905dfecf96Smrg XawTextJustifyMode justify; 11915dfecf96Smrg 11925dfecf96Smrg LispObj *value; 11935dfecf96Smrg 11945dfecf96Smrg value = ARGUMENT(0); 11955dfecf96Smrg 11965dfecf96Smrg if (value != UNSPEC) { 11975dfecf96Smrg for (i = 0; i < 4; i++) 11985dfecf96Smrg if (value == justify_modes[i]) 11995dfecf96Smrg break; 12005dfecf96Smrg if (i >= 4) 12015dfecf96Smrg LispDestroy("%s: argument must be " 12025dfecf96Smrg ":LEFT, :RIGHT, :CENTER, or :FULL, not %s", 12035dfecf96Smrg STRFUN(builtin), STROBJ(value)); 12045dfecf96Smrg XtSetArg(arg[0], XtNjustifyMode, (XawTextJustifyMode)i); 12055dfecf96Smrg XtSetValues(textwindow, arg, 1); 12065dfecf96Smrg } 12075dfecf96Smrg else { 12085dfecf96Smrg XtSetArg(arg[0], XtNjustifyMode, &justify); 12095dfecf96Smrg XtGetValues(textwindow, arg, 1); 12105dfecf96Smrg i = (int)justify; 12115dfecf96Smrg if (i <= 0 || i >= 4) 12125dfecf96Smrg i = 0; 12135dfecf96Smrg value = justify_modes[i]; 12145dfecf96Smrg } 12155dfecf96Smrg 12165dfecf96Smrg return (value); 12175dfecf96Smrg} 12185dfecf96Smrg 12195dfecf96SmrgLispObj * 12205dfecf96SmrgXedit_LeftColumn(LispBuiltin *builtin) 12215dfecf96Smrg/* 12225dfecf96Smrg left-column &optional left 12235dfecf96Smrg */ 12245dfecf96Smrg{ 12255dfecf96Smrg short left; 12265dfecf96Smrg Arg arg[1]; 12275dfecf96Smrg 12285dfecf96Smrg LispObj *oleft; 12295dfecf96Smrg 12305dfecf96Smrg oleft = ARGUMENT(0); 12315dfecf96Smrg 12325dfecf96Smrg if (oleft != UNSPEC) { 12335dfecf96Smrg CHECK_INDEX(oleft); 12345dfecf96Smrg if (FIXNUM_VALUE(oleft) >= 32767) 12355dfecf96Smrg left = 32767; 12365dfecf96Smrg else 12375dfecf96Smrg left = FIXNUM_VALUE(oleft); 12385dfecf96Smrg 12395dfecf96Smrg XtSetArg(arg[0], XtNleftColumn, left); 12405dfecf96Smrg XtSetValues(textwindow, arg, 1); 12415dfecf96Smrg } 12425dfecf96Smrg else { 12435dfecf96Smrg XtSetArg(arg[0], XtNleftColumn, &left); 12445dfecf96Smrg XtGetValues(textwindow, arg, 1); 12455dfecf96Smrg 12465dfecf96Smrg oleft = FIXNUM((long)left); 12475dfecf96Smrg } 12485dfecf96Smrg 12495dfecf96Smrg return (oleft); 12505dfecf96Smrg} 12515dfecf96Smrg 12525dfecf96SmrgLispObj * 12535dfecf96SmrgXedit_Point(LispBuiltin *builtin) 12545dfecf96Smrg/* 12555dfecf96Smrg point 12565dfecf96Smrg */ 12575dfecf96Smrg{ 12585dfecf96Smrg return (FIXNUM(XawTextGetInsertionPoint(textwindow))); 12595dfecf96Smrg} 12605dfecf96Smrg 12615dfecf96SmrgLispObj * 12625dfecf96SmrgXedit_PointMax(LispBuiltin *builtin) 12635dfecf96Smrg/* 12645dfecf96Smrg point-max 12655dfecf96Smrg */ 12665dfecf96Smrg{ 12675dfecf96Smrg return (FIXNUM(XawTextSourceScan(XawTextGetSource(textwindow), 0, 12685dfecf96Smrg XawstAll, XawsdRight, 1, True))); 12695dfecf96Smrg} 12705dfecf96Smrg 12715dfecf96SmrgLispObj * 12725dfecf96SmrgXedit_PointMin(LispBuiltin *builtin) 12735dfecf96Smrg/* 12745dfecf96Smrg point-min 12755dfecf96Smrg */ 12765dfecf96Smrg{ 12775dfecf96Smrg return (FIXNUM(XawTextSourceScan(XawTextGetSource(textwindow), 0, 12785dfecf96Smrg XawstAll, XawsdLeft, 1, True))); 12795dfecf96Smrg} 12805dfecf96Smrg 12815dfecf96SmrgLispObj * 12825dfecf96SmrgXedit_PropertyList(LispBuiltin *builtin) 12835dfecf96Smrg/* 12845dfecf96Smrg property-list &optional value 12855dfecf96Smrg */ 12865dfecf96Smrg{ 12875dfecf96Smrg Arg arg[1]; 12885dfecf96Smrg XawTextPropertyList *property_list; 12895dfecf96Smrg 12905dfecf96Smrg LispObj *value; 12915dfecf96Smrg 12925dfecf96Smrg value = ARGUMENT(0); 12935dfecf96Smrg 12945dfecf96Smrg if (value != UNSPEC) { 12955dfecf96Smrg Cardinal i; 12965dfecf96Smrg XrmQuark quark; 12975dfecf96Smrg 12985dfecf96Smrg CHECK_LONGINT(value); 12995dfecf96Smrg property_list = NULL; 13005dfecf96Smrg quark = LONGINT_VALUE(value); 13015dfecf96Smrg for (i = 0; i < num_property_lists; i++) 13025dfecf96Smrg if (property_lists[i]->identifier == quark) { 13035dfecf96Smrg property_list = property_lists[i]; 13045dfecf96Smrg break; 13055dfecf96Smrg } 13065dfecf96Smrg 13075dfecf96Smrg if (property_list) { 13085dfecf96Smrg XtSetArg(arg[0], XawNtextProperties, property_list); 13095dfecf96Smrg XtSetValues(XawTextGetSink(textwindow), arg, 1); 13105dfecf96Smrg } 13115dfecf96Smrg else 13125dfecf96Smrg /* Maybe should generate an error here */ 13135dfecf96Smrg value = NIL; 13145dfecf96Smrg } 13155dfecf96Smrg else { 13165dfecf96Smrg XtSetArg(arg[0], XawNtextProperties, &property_list); 13175dfecf96Smrg XtGetValues(XawTextGetSink(textwindow), arg, 1); 13185dfecf96Smrg if (property_list) 13195dfecf96Smrg value = INTEGER(property_list->identifier); 13205dfecf96Smrg } 13215dfecf96Smrg 13225dfecf96Smrg return (value); 13235dfecf96Smrg} 13245dfecf96Smrg 13255dfecf96SmrgLispObj * 13265dfecf96SmrgXedit_ReadText(LispBuiltin *builtin) 13275dfecf96Smrg/* 13285dfecf96Smrg read-text offset length 13295dfecf96Smrg */ 13305dfecf96Smrg{ 13315dfecf96Smrg XawTextPosition last = XawTextSourceScan(XawTextGetSource(textwindow), 0, 13325dfecf96Smrg XawstAll, XawsdRight, 1, True); 13335dfecf96Smrg XawTextPosition from, to, len; 13345dfecf96Smrg XawTextBlock block; 13355dfecf96Smrg char *string, *ptr; 13365dfecf96Smrg 13375dfecf96Smrg LispObj *offset, *length; 13385dfecf96Smrg 13395dfecf96Smrg length = ARGUMENT(1); 13405dfecf96Smrg offset = ARGUMENT(0); 13415dfecf96Smrg 13425dfecf96Smrg CHECK_INDEX(offset); 13435dfecf96Smrg CHECK_INDEX(length); 13445dfecf96Smrg 13455dfecf96Smrg from = FIXNUM_VALUE(offset); 13465dfecf96Smrg to = from + FIXNUM_VALUE(length); 13475dfecf96Smrg if (from > last) 13485dfecf96Smrg from = last; 13495dfecf96Smrg if (to > last) 13505dfecf96Smrg to = last; 13515dfecf96Smrg 13525dfecf96Smrg if (from == to) 13535dfecf96Smrg return (STRING("")); 13545dfecf96Smrg 13555dfecf96Smrg len = to - from; 13565dfecf96Smrg string = LispMalloc(len); 13575dfecf96Smrg 13585dfecf96Smrg for (ptr = string; from < to;) { 13595dfecf96Smrg XawTextSourceRead(XawTextGetSource(textwindow), from, &block, to - from); 13605dfecf96Smrg memcpy(ptr, block.ptr, block.length); 13615dfecf96Smrg ptr += block.length; 13625dfecf96Smrg from += block.length; 13635dfecf96Smrg } 13645dfecf96Smrg 13655dfecf96Smrg return (LSTRING2(string, len)); 13665dfecf96Smrg} 13675dfecf96Smrg 13685dfecf96SmrgLispObj * 13695dfecf96SmrgXedit_ReplaceText(LispBuiltin *builtin) 13705dfecf96Smrg/* 13715dfecf96Smrg replace-text left right text 13725dfecf96Smrg */ 13735dfecf96Smrg{ 13745dfecf96Smrg XawTextPosition last = XawTextSourceScan(XawTextGetSource(textwindow), 0, 13755dfecf96Smrg XawstAll, XawsdRight, 1, True); 13765dfecf96Smrg XawTextPosition left, right; 13775dfecf96Smrg XawTextBlock block; 13785dfecf96Smrg 13795dfecf96Smrg LispObj *oleft, *oright, *text; 13805dfecf96Smrg 13815dfecf96Smrg text = ARGUMENT(2); 13825dfecf96Smrg oright = ARGUMENT(1); 13835dfecf96Smrg oleft = ARGUMENT(0); 13845dfecf96Smrg 13855dfecf96Smrg CHECK_INDEX(oleft); 13865dfecf96Smrg CHECK_INDEX(oright); 13875dfecf96Smrg CHECK_STRING(text); 13885dfecf96Smrg 13895dfecf96Smrg left = FIXNUM_VALUE(oleft); 13905dfecf96Smrg right = FIXNUM_VALUE(oright); 13915dfecf96Smrg if (left > last) 13925dfecf96Smrg left = last; 13935dfecf96Smrg if (left > right) 13945dfecf96Smrg right = left; 13955dfecf96Smrg else if (right > last) 13965dfecf96Smrg right = last; 13975dfecf96Smrg 13985dfecf96Smrg block.firstPos = 0; 13995dfecf96Smrg block.format = FMT8BIT; 14005dfecf96Smrg block.length = STRLEN(text); 14015dfecf96Smrg block.ptr = THESTR(text); 14025dfecf96Smrg XawTextReplace(textwindow, left, right, &block); 14035dfecf96Smrg 14045dfecf96Smrg return (text); 14055dfecf96Smrg} 14065dfecf96Smrg 14075dfecf96SmrgLispObj * 14085dfecf96SmrgXedit_RightColumn(LispBuiltin *builtin) 14095dfecf96Smrg/* 14105dfecf96Smrg right-column &optional right 14115dfecf96Smrg */ 14125dfecf96Smrg{ 14135dfecf96Smrg short right; 14145dfecf96Smrg Arg arg[1]; 14155dfecf96Smrg 14165dfecf96Smrg LispObj *oright; 14175dfecf96Smrg 14185dfecf96Smrg oright = ARGUMENT(0); 14195dfecf96Smrg 14205dfecf96Smrg if (oright != UNSPEC) { 14215dfecf96Smrg CHECK_INDEX(oright); 14225dfecf96Smrg if (FIXNUM_VALUE(oright) >= 32767) 14235dfecf96Smrg right = 32767; 14245dfecf96Smrg else 14255dfecf96Smrg right = FIXNUM_VALUE(oright); 14265dfecf96Smrg 14275dfecf96Smrg XtSetArg(arg[0], XtNrightColumn, right); 14285dfecf96Smrg XtSetValues(textwindow, arg, 1); 14295dfecf96Smrg } 14305dfecf96Smrg else { 14315dfecf96Smrg XtSetArg(arg[0], XtNrightColumn, &right); 14325dfecf96Smrg XtGetValues(textwindow, arg, 1); 14335dfecf96Smrg 14345dfecf96Smrg oright = FIXNUM(right); 14355dfecf96Smrg } 14365dfecf96Smrg 14375dfecf96Smrg return (oright); 14385dfecf96Smrg} 14395dfecf96Smrg 14405dfecf96SmrgLispObj * 14415dfecf96SmrgXedit_Scan(LispBuiltin *builtin) 14425dfecf96Smrg/* 14435dfecf96Smrg scan offset type direction &key count include 14445dfecf96Smrg */ 14455dfecf96Smrg{ 14465dfecf96Smrg int i; 14475dfecf96Smrg XawTextPosition offset; 14485dfecf96Smrg XawTextScanType type; 14495dfecf96Smrg XawTextScanDirection direction; 14505dfecf96Smrg int count; 14515dfecf96Smrg 14525dfecf96Smrg LispObj *ooffset, *otype, *odirection, *ocount, *include; 14535dfecf96Smrg 14545dfecf96Smrg include = ARGUMENT(4); 14555dfecf96Smrg if (include == UNSPEC) 14565dfecf96Smrg include = NIL; 14575dfecf96Smrg ocount = ARGUMENT(3); 14585dfecf96Smrg odirection = ARGUMENT(2); 14595dfecf96Smrg otype = ARGUMENT(1); 14605dfecf96Smrg ooffset = ARGUMENT(0); 14615dfecf96Smrg 14625dfecf96Smrg CHECK_INDEX(ooffset); 14635dfecf96Smrg offset = FIXNUM_VALUE(ooffset); 14645dfecf96Smrg 14655dfecf96Smrg for (i = 0; i < 2; i++) 14665dfecf96Smrg if (odirection == scan_directions[i]) 14675dfecf96Smrg break; 14685dfecf96Smrg if (i >= 2) 14695dfecf96Smrg LispDestroy("%s: direction must be " 14705dfecf96Smrg ":LEFT or :RIGHT, not %s", 14715dfecf96Smrg STRFUN(builtin), STROBJ(odirection)); 14725dfecf96Smrg direction = (XawTextScanDirection)i; 14735dfecf96Smrg 14745dfecf96Smrg for (i = 0; i < 6; i++) 14755dfecf96Smrg if (otype == scan_types[i]) 14765dfecf96Smrg break; 14775dfecf96Smrg if (i >= 6) 14785dfecf96Smrg LispDestroy("%s: direction must be " 14795dfecf96Smrg ":POSITIONS, :WHITE-SPACE, :EOL, " 14805dfecf96Smrg ":PARAGRAPH, :ALL, or :ALPHA-NUMERIC, not %s", 14815dfecf96Smrg STRFUN(builtin), STROBJ(otype)); 14825dfecf96Smrg type = (XawTextScanType)i; 14835dfecf96Smrg 14845dfecf96Smrg if (ocount == UNSPEC) 14855dfecf96Smrg count = 1; 14865dfecf96Smrg else { 14875dfecf96Smrg CHECK_INDEX(ocount); 14885dfecf96Smrg count = FIXNUM_VALUE(ocount); 14895dfecf96Smrg } 14905dfecf96Smrg 14915dfecf96Smrg offset = XawTextSourceScan(XawTextGetSource(textwindow), 14925dfecf96Smrg offset, type, direction, count, 14935dfecf96Smrg include != NIL); 14945dfecf96Smrg 14955dfecf96Smrg return (FIXNUM(offset)); 14965dfecf96Smrg} 14975dfecf96Smrg 14985dfecf96Smrgstatic LispObj * 14995dfecf96SmrgXeditSearch(LispBuiltin *builtin, XawTextScanDirection direction) 15005dfecf96Smrg{ 15015dfecf96Smrg XawTextBlock block; 15025dfecf96Smrg XawTextPosition position; 15035dfecf96Smrg 15045dfecf96Smrg LispObj *string, *offset, *ignore_case; 15055dfecf96Smrg 15065dfecf96Smrg ignore_case = ARGUMENT(2); 15075dfecf96Smrg offset = ARGUMENT(1); 15085dfecf96Smrg string = ARGUMENT(0); 15095dfecf96Smrg 15105dfecf96Smrg CHECK_STRING(string); 15115dfecf96Smrg if (offset != UNSPEC) { 15125dfecf96Smrg CHECK_INDEX(offset); 15135dfecf96Smrg position = FIXNUM_VALUE(offset); 15145dfecf96Smrg } 15155dfecf96Smrg else 15165dfecf96Smrg position = XawTextGetInsertionPoint(textwindow); 15175dfecf96Smrg 15185dfecf96Smrg block.firstPos = (ignore_case != UNSPEC && ignore_case != NIL) ? 1 : 0; 15195dfecf96Smrg block.format = FMT8BIT; 15205dfecf96Smrg block.length = STRLEN(string); 15215dfecf96Smrg block.ptr = THESTR(string); 15225dfecf96Smrg position = XawTextSourceSearch(XawTextGetSource(textwindow), 15235dfecf96Smrg position, direction, &block); 15245dfecf96Smrg 15255dfecf96Smrg return (position != XawTextSearchError ? FIXNUM(position) : NIL); 15265dfecf96Smrg} 15275dfecf96Smrg 15285dfecf96Smrg 15295dfecf96SmrgLispObj * 15305dfecf96SmrgXedit_SearchBackward(LispBuiltin *builtin) 15315dfecf96Smrg/* 15325dfecf96Smrg search-backward string &optional offset ignore-case 15335dfecf96Smrg */ 15345dfecf96Smrg{ 15355dfecf96Smrg return (XeditSearch(builtin, XawsdLeft)); 15365dfecf96Smrg} 15375dfecf96Smrg 15385dfecf96SmrgLispObj * 15395dfecf96SmrgXedit_SearchForward(LispBuiltin *builtin) 15405dfecf96Smrg/* 15415dfecf96Smrg search-forward string &optional offset ignore-case 15425dfecf96Smrg */ 15435dfecf96Smrg{ 15445dfecf96Smrg return (XeditSearch(builtin, XawsdRight)); 15455dfecf96Smrg} 15465dfecf96Smrg 15475dfecf96SmrgLispObj * 15485dfecf96SmrgXedit_VerticalScrollbar(LispBuiltin *builtin) 15495dfecf96Smrg/* 15505dfecf96Smrg vertical-scrollbar &optional state 15515dfecf96Smrg */ 15525dfecf96Smrg{ 15535dfecf96Smrg Arg arg[1]; 15545dfecf96Smrg XawTextScrollMode scroll; 15555dfecf96Smrg 15565dfecf96Smrg LispObj *state; 15575dfecf96Smrg 15585dfecf96Smrg state = ARGUMENT(0); 15595dfecf96Smrg 15605dfecf96Smrg if (state != UNSPEC) { 15615dfecf96Smrg scroll = state == NIL ? XawtextScrollNever : XawtextScrollAlways; 15625dfecf96Smrg XtSetArg(arg[0], XtNscrollVertical, scroll); 15635dfecf96Smrg XtSetValues(textwindow, arg, 1); 15645dfecf96Smrg } 15655dfecf96Smrg else { 15665dfecf96Smrg XtSetArg(arg[0], XtNscrollVertical, &scroll); 15675dfecf96Smrg XtGetValues(textwindow, arg, 1); 15685dfecf96Smrg state = scroll == XawtextScrollAlways ? T : NIL; 15695dfecf96Smrg } 15705dfecf96Smrg 15715dfecf96Smrg return (state); 15725dfecf96Smrg} 15735dfecf96Smrg 15745dfecf96SmrgLispObj * 15755dfecf96SmrgXedit_WrapMode(LispBuiltin *builtin) 15765dfecf96Smrg/* 15775dfecf96Smrg wrap-mode &optional value 15785dfecf96Smrg */ 15795dfecf96Smrg{ 15805dfecf96Smrg int i; 15815dfecf96Smrg Arg arg[1]; 15825dfecf96Smrg XawTextWrapMode wrap; 15835dfecf96Smrg 15845dfecf96Smrg LispObj *value; 15855dfecf96Smrg 15865dfecf96Smrg value = ARGUMENT(0); 15875dfecf96Smrg 15885dfecf96Smrg if (value != UNSPEC) { 15895dfecf96Smrg for (i = 0; i < 3; i++) 15905dfecf96Smrg if (value == wrap_modes[i]) 15915dfecf96Smrg break; 15925dfecf96Smrg if (i >= 3) 15935dfecf96Smrg LispDestroy("%s: argument must be " 15945dfecf96Smrg ":NEVER, :LINE, or :WORD, not %s", 15955dfecf96Smrg STRFUN(builtin), STROBJ(value)); 15965dfecf96Smrg XtSetArg(arg[0], XtNwrap, (XawTextWrapMode)i); 15975dfecf96Smrg XtSetValues(textwindow, arg, 1); 15985dfecf96Smrg } 15995dfecf96Smrg else { 16005dfecf96Smrg XtSetArg(arg[0], XtNwrap, &wrap); 16015dfecf96Smrg XtGetValues(textwindow, arg, 1); 16025dfecf96Smrg i = (int)wrap; 16035dfecf96Smrg if (i <= 0 || i >= 3) 16045dfecf96Smrg i = 0; 16055dfecf96Smrg value = wrap_modes[i]; 16065dfecf96Smrg } 16075dfecf96Smrg 16085dfecf96Smrg return (value); 16095dfecf96Smrg} 16105dfecf96Smrg 16115dfecf96SmrgLispObj * 16125dfecf96SmrgXedit_XrmStringToQuark(LispBuiltin *builtin) 16135dfecf96Smrg/* 16145dfecf96Smrg xrm-string-to-quark string 16155dfecf96Smrg */ 16165dfecf96Smrg{ 16175dfecf96Smrg LispObj *string; 16185dfecf96Smrg 16195dfecf96Smrg string = ARGUMENT(0); 16205dfecf96Smrg 16215dfecf96Smrg CHECK_STRING(string); 16225dfecf96Smrg 16235dfecf96Smrg return (INTEGER(XrmStringToQuark(THESTR(string)))); 16245dfecf96Smrg} 1625