15dfecf96Smrg/*
25dfecf96Smrg * Copyright (c) 2001 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.c,v 1.20tsi Exp $ */
315dfecf96Smrg
325dfecf96Smrg#include "xedit.h"
335dfecf96Smrg#include "lisp/lisp.h"
345dfecf96Smrg#include "lisp/xedit.h"
355dfecf96Smrg#include <unistd.h>
365dfecf96Smrg#include <locale.h>
375dfecf96Smrg#include <ctype.h>
385dfecf96Smrg
395dfecf96Smrg#include <X11/Xaw/SmeBSB.h>
405dfecf96Smrg#include <X11/Xaw/SimpleMenu.h>
415dfecf96Smrg
425dfecf96Smrg/*
435dfecf96Smrg * Prototypes
445dfecf96Smrg */
455dfecf96Smrgstatic void XeditDoLispEval(Widget);
465dfecf96Smrgstatic void EditModeCallback(Widget, XtPointer, XtPointer);
475dfecf96Smrg
485dfecf96Smrg/*
495dfecf96Smrg * Initialization
505dfecf96Smrg */
515dfecf96Smrgstatic int lisp_initialized;
525dfecf96Smrgextern Widget scratch;
535dfecf96Smrgstatic Widget edit_mode_menu, edit_mode_entry, edit_mode_none;
545dfecf96Smrg
555dfecf96Smrg/*
565dfecf96Smrg * Implementation
575dfecf96Smrg */
585dfecf96Smrgvoid
595dfecf96SmrgXeditLispInitialize(void)
605dfecf96Smrg{
615dfecf96Smrg    setlocale(LC_NUMERIC, "C");
625dfecf96Smrg    lisp_initialized = 1;
635dfecf96Smrg    LispBegin();
645dfecf96Smrg    LispXeditInitialize();
655dfecf96Smrg}
665dfecf96Smrg
675dfecf96Smrgvoid
685dfecf96SmrgXeditLispCleanUp(void)
695dfecf96Smrg{
705dfecf96Smrg    LispEnd();
715dfecf96Smrg}
725dfecf96Smrg
735dfecf96Smrgvoid
745dfecf96SmrgXeditLispEval(Widget w, XEvent *event, String *params, Cardinal *num_params)
755dfecf96Smrg{
765dfecf96Smrg    XeditDoLispEval(messwidget);
775dfecf96Smrg}
785dfecf96Smrg
795dfecf96Smrgvoid
805dfecf96SmrgXeditPrintLispEval(Widget w, XEvent *event, String *params, Cardinal *num_params)
815dfecf96Smrg{
825dfecf96Smrg    if (XawTextGetSource(w) == scratch) {
835dfecf96Smrg	XtCallActionProc(w, "newline", event, params, *num_params);
845dfecf96Smrg	XeditDoLispEval(w);
855dfecf96Smrg    }
865dfecf96Smrg    else
875dfecf96Smrg	XtCallActionProc(w, "newline-and-indent", event, params, *num_params);
885dfecf96Smrg}
895dfecf96Smrg
905dfecf96Smrgvoid
915dfecf96SmrgXeditKeyboardReset(Widget w, XEvent *event, String *params, Cardinal *num_params)
925dfecf96Smrg{
935dfecf96Smrg    XtCallActionProc(w, "keyboard-reset", event, params, *num_params);
945dfecf96Smrg}
955dfecf96Smrg
965dfecf96Smrgvoid
975dfecf96SmrgSetTextProperties(xedit_flist_item *item)
985dfecf96Smrg{
995dfecf96Smrg    if (lisp_initialized) {
1005dfecf96Smrg	Widget source = XawTextGetSource(textwindow);
1015dfecf96Smrg	XawTextPosition top = XawTextTopPosition(textwindow);
1025dfecf96Smrg
1035dfecf96Smrg	if (source != item->source)
1045dfecf96Smrg	    XawTextSetSource(textwindow, item->source, 0);
1055dfecf96Smrg	XeditLispSetEditMode(item, NULL);
1065dfecf96Smrg	if (source != item->source)
1075dfecf96Smrg	    XawTextSetSource(textwindow, source, top);
1085dfecf96Smrg    }
1095dfecf96Smrg}
1105dfecf96Smrg
1115dfecf96Smrgvoid
1125dfecf96SmrgUnsetTextProperties(xedit_flist_item *item)
1135dfecf96Smrg{
1145dfecf96Smrg    XeditLispUnsetEditMode(item);
1155dfecf96Smrg}
1165dfecf96Smrg
1175dfecf96Smrgstatic void
1185dfecf96SmrgXeditDoLispEval(Widget output)
1195dfecf96Smrg{
1205dfecf96Smrg    Widget src;
1215dfecf96Smrg    XawTextBlock block;
1225dfecf96Smrg    XawTextPosition position, end;
1235dfecf96Smrg
1245dfecf96Smrg    /* get lisp expression */
1255dfecf96Smrg    src = XawTextGetSource(textwindow);
1265dfecf96Smrg    position = XawTextGetInsertionPoint(textwindow);
1275dfecf96Smrg    --position;
1285dfecf96Smrg    while (position >= 0) {
1295dfecf96Smrg	(void)XawTextSourceRead(src, position, &block, 1);
1305dfecf96Smrg	if (!isspace(block.ptr[0]))
1315dfecf96Smrg	    break;
1325dfecf96Smrg	--position;
1335dfecf96Smrg    }
1345dfecf96Smrg    end = position + 1;
1355dfecf96Smrg
1365dfecf96Smrg    if (block.ptr[0] != ')') {
1375dfecf96Smrg	while (position >= 0) {
1385dfecf96Smrg	    (void)XawTextSourceRead(src, position, &block, 1);
1395dfecf96Smrg	    if (isspace(block.ptr[0]) ||
1405dfecf96Smrg		block.ptr[0] == '(' ||
1415dfecf96Smrg		block.ptr[0] == ')' ||
1425dfecf96Smrg		block.ptr[0] == '"' ||
1435dfecf96Smrg		block.ptr[0] == '|')
1445dfecf96Smrg		break;
1455dfecf96Smrg	    --position;
1465dfecf96Smrg	}
1475dfecf96Smrg	if (!isspace(block.ptr[0]))
1485dfecf96Smrg	    ++position;
1495dfecf96Smrg    }
1505dfecf96Smrg    else {
1515dfecf96Smrg	/* XXX note that embedded '(' and ')' will confuse this code */
1525dfecf96Smrg	XawTextPosition last, tmp;
1535dfecf96Smrg	int level = 0;
1545dfecf96Smrg	char ptr[2];
1555dfecf96Smrg
1565dfecf96Smrg	last = position;
1575dfecf96Smrg	ptr[1] = '\0';
1585dfecf96Smrg	block.ptr = ptr;
1595dfecf96Smrg	do {
1605dfecf96Smrg	    block.ptr[0] = '(';
1615dfecf96Smrg	    position = XawTextSourceSearch(src, last, XawsdLeft, &block);
1625dfecf96Smrg	    if (position == XawTextSearchError) {
1635dfecf96Smrg		Feep();
1645dfecf96Smrg		return;
1655dfecf96Smrg	    }
1665dfecf96Smrg	    block.ptr[0] = ')';
1675dfecf96Smrg	    tmp = position;
1685dfecf96Smrg	    do {
1695dfecf96Smrg		tmp = XawTextSourceSearch(src, tmp, XawsdRight, &block);
1705dfecf96Smrg		if (tmp == XawTextSearchError) {
1715dfecf96Smrg		    Feep();
1725dfecf96Smrg		    return;
1735dfecf96Smrg		}
1745dfecf96Smrg		if (tmp <= last)
1755dfecf96Smrg		    ++level;
1765dfecf96Smrg	    } while (++tmp <= last);
1775dfecf96Smrg	    --level;
1785dfecf96Smrg	    last = position;
1795dfecf96Smrg	} while (level);
1805dfecf96Smrg	/* check for extra characters */
1815dfecf96Smrg	while (position > 0) {
1825dfecf96Smrg	    (void)XawTextSourceRead(src, position - 1, &block, 1);
1835dfecf96Smrg	    if (block.length != 1 ||
1845dfecf96Smrg		isspace(block.ptr[0]) ||
1855dfecf96Smrg		block.ptr[0] == ')' ||
1865dfecf96Smrg		block.ptr[0] == '"' ||
1875dfecf96Smrg		block.ptr[0] == '|')
1885dfecf96Smrg		break;
1895dfecf96Smrg	    --position;
1905dfecf96Smrg	}
1915dfecf96Smrg    }
1925dfecf96Smrg
1935dfecf96Smrg    if (position < 0 || position >= end)
1945dfecf96Smrg	Feep();
1955dfecf96Smrg    else
1965dfecf96Smrg	XeditLispExecute(output, position, end);
1975dfecf96Smrg}
1985dfecf96Smrg
1995dfecf96Smrgvoid
2005dfecf96SmrgCreateEditModePopup(Widget parent)
2015dfecf96Smrg{
2025dfecf96Smrg    int i;
2035dfecf96Smrg    Widget sme;
2045dfecf96Smrg    static char *editModes = "editModes";
2055dfecf96Smrg
2065dfecf96Smrg    XtVaCreateManagedWidget("modeMenuItem", smeBSBObjectClass, parent,
2075dfecf96Smrg			    XtNmenuName, editModes, NULL);
2085dfecf96Smrg    edit_mode_menu = XtCreatePopupShell(editModes, simpleMenuWidgetClass,
2095dfecf96Smrg					parent, NULL, 0);
2105dfecf96Smrg    XtRealizeWidget(edit_mode_menu);
2115dfecf96Smrg
2125dfecf96Smrg    edit_mode_none = XtCreateManagedWidget("none", smeBSBObjectClass,
2135dfecf96Smrg					   edit_mode_menu, NULL, 0);
2145dfecf96Smrg    XtAddCallback(edit_mode_none, XtNcallback, EditModeCallback, NULL);
2155dfecf96Smrg
2165dfecf96Smrg    for (i = 0; i < num_mode_infos; i++) {
2175dfecf96Smrg	sme = XtVaCreateManagedWidget("mode", smeBSBObjectClass, edit_mode_menu,
2185dfecf96Smrg				      XtNlabel, mode_infos[i].desc, NULL);
2195dfecf96Smrg	XtAddCallback(sme, XtNcallback, EditModeCallback,
2205dfecf96Smrg		      (XtPointer)(mode_infos + i));
2215dfecf96Smrg	mode_infos[i].sme = sme;
2225dfecf96Smrg    }
2235dfecf96Smrg}
2245dfecf96Smrg
2255dfecf96Smrgvoid
2265dfecf96SmrgSetEditModeMenu(void)
2275dfecf96Smrg{
2285dfecf96Smrg    int i;
2295dfecf96Smrg    Widget old_entry = edit_mode_entry, new_entry = edit_mode_none;
2305dfecf96Smrg    xedit_flist_item *item = FindTextSource(XawTextGetSource(textwindow), NULL);
2315dfecf96Smrg
2325dfecf96Smrg    for (i = 0; i < num_mode_infos; i++) {
2335dfecf96Smrg	if (item->xldata && item->xldata->syntax &&
2345dfecf96Smrg	    mode_infos[i].syntax == item->xldata->syntax) {
2355dfecf96Smrg	    new_entry = mode_infos[i].sme;
2365dfecf96Smrg	    break;
2375dfecf96Smrg	}
2385dfecf96Smrg    }
2395dfecf96Smrg
2405dfecf96Smrg    if (old_entry != new_entry) {
2415dfecf96Smrg	if (old_entry)
2425dfecf96Smrg	    XtVaSetValues(old_entry, XtNleftBitmap, None, NULL);
2435dfecf96Smrg	XtVaSetValues(new_entry, XtNleftBitmap, flist.pixmap, NULL);
2445dfecf96Smrg	edit_mode_entry = new_entry;
2455dfecf96Smrg    }
2465dfecf96Smrg}
2475dfecf96Smrg
2485dfecf96Smrgstatic void
2495dfecf96SmrgEditModeCallback(Widget w, XtPointer client_data, XtPointer call_data)
2505dfecf96Smrg{
2515dfecf96Smrg    Widget source = XawTextGetSource(textwindow);
2525dfecf96Smrg    EditModeInfo *info = (EditModeInfo*)client_data;
2535dfecf96Smrg    xedit_flist_item *item = FindTextSource(source, NULL);
2545dfecf96Smrg
2555dfecf96Smrg    /* If no edit mode selected and selecting the plain/none mode */
2565dfecf96Smrg    if ((info == NULL &&
2575dfecf96Smrg	 (item->xldata == NULL || item->xldata->syntax == NULL)) ||
2585dfecf96Smrg	/* if selecting the current mode */
2595dfecf96Smrg	(info && item && item->xldata && info->syntax &&
2605dfecf96Smrg	 info->syntax == item->xldata->syntax))
2615dfecf96Smrg	return;
2625dfecf96Smrg
2635dfecf96Smrg    XawTextSourceClearEntities(source,
2645dfecf96Smrg			       XawTextSourceScan(source, 0, XawstAll,
2655dfecf96Smrg						 XawsdLeft, 1, True),
2665dfecf96Smrg			       XawTextSourceScan(source, 0, XawstAll,
2675dfecf96Smrg						 XawsdRight, 1, True));
2685dfecf96Smrg    XeditLispUnsetEditMode(item);
2695dfecf96Smrg    if (info)
2705dfecf96Smrg	XeditLispSetEditMode(item, info->symbol);
2715dfecf96Smrg    else
2725dfecf96Smrg	item->properties = NULL;
2735dfecf96Smrg    UpdateTextProperties(1);
2745dfecf96Smrg}
275