1/* 2 * Copyright (c) 2001 by The XFree86 Project, Inc. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 * THE XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 18 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF 19 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 * SOFTWARE. 21 * 22 * Except as contained in this notice, the name of the XFree86 Project shall 23 * not be used in advertising or otherwise to promote the sale, use or other 24 * dealings in this Software without prior written authorization from the 25 * XFree86 Project. 26 * 27 * Author: Paulo César Pereira de Andrade 28 */ 29 30/* $XFree86: xc/programs/xedit/lisp.c,v 1.20tsi Exp $ */ 31 32#include "xedit.h" 33#include "lisp/lisp.h" 34#include "lisp/xedit.h" 35#include <unistd.h> 36#include <locale.h> 37#include <ctype.h> 38 39#include <X11/Xaw/SmeBSB.h> 40#include <X11/Xaw/SimpleMenu.h> 41 42/* 43 * Prototypes 44 */ 45static void XeditDoLispEval(Widget); 46static void EditModeCallback(Widget, XtPointer, XtPointer); 47 48/* 49 * Initialization 50 */ 51static int lisp_initialized; 52extern Widget scratch; 53static Widget edit_mode_menu, edit_mode_entry, edit_mode_none; 54 55/* 56 * Implementation 57 */ 58void 59XeditLispInitialize(void) 60{ 61 setlocale(LC_NUMERIC, "C"); 62 lisp_initialized = 1; 63 LispBegin(); 64 LispXeditInitialize(); 65} 66 67void 68XeditLispCleanUp(void) 69{ 70 LispEnd(); 71} 72 73void 74XeditLispEval(Widget w, XEvent *event, String *params, Cardinal *num_params) 75{ 76 XeditDoLispEval(messwidget); 77} 78 79void 80XeditPrintLispEval(Widget w, XEvent *event, String *params, Cardinal *num_params) 81{ 82 if (XawTextGetSource(w) == scratch) { 83 XtCallActionProc(w, "newline", event, params, *num_params); 84 XeditDoLispEval(w); 85 } 86 else 87 XtCallActionProc(w, "newline-and-indent", event, params, *num_params); 88} 89 90void 91XeditKeyboardReset(Widget w, XEvent *event, String *params, Cardinal *num_params) 92{ 93 XtCallActionProc(w, "keyboard-reset", event, params, *num_params); 94} 95 96void 97SetTextProperties(xedit_flist_item *item) 98{ 99 if (lisp_initialized) { 100 Widget source = XawTextGetSource(textwindow); 101 XawTextPosition top = XawTextTopPosition(textwindow); 102 103 if (source != item->source) 104 XawTextSetSource(textwindow, item->source, 0); 105 XeditLispSetEditMode(item, NULL); 106 if (source != item->source) 107 XawTextSetSource(textwindow, source, top); 108 } 109} 110 111void 112UnsetTextProperties(xedit_flist_item *item) 113{ 114 XeditLispUnsetEditMode(item); 115} 116 117static void 118XeditDoLispEval(Widget output) 119{ 120 Widget src; 121 XawTextBlock block; 122 XawTextPosition position, end; 123 124 /* get lisp expression */ 125 src = XawTextGetSource(textwindow); 126 position = XawTextGetInsertionPoint(textwindow); 127 --position; 128 while (position >= 0) { 129 (void)XawTextSourceRead(src, position, &block, 1); 130 if (!isspace(block.ptr[0])) 131 break; 132 --position; 133 } 134 end = position + 1; 135 136 if (block.ptr[0] != ')') { 137 while (position >= 0) { 138 (void)XawTextSourceRead(src, position, &block, 1); 139 if (isspace(block.ptr[0]) || 140 block.ptr[0] == '(' || 141 block.ptr[0] == ')' || 142 block.ptr[0] == '"' || 143 block.ptr[0] == '|') 144 break; 145 --position; 146 } 147 if (!isspace(block.ptr[0])) 148 ++position; 149 } 150 else { 151 /* XXX note that embedded '(' and ')' will confuse this code */ 152 XawTextPosition last, tmp; 153 int level = 0; 154 char ptr[2]; 155 156 last = position; 157 ptr[1] = '\0'; 158 block.ptr = ptr; 159 do { 160 block.ptr[0] = '('; 161 position = XawTextSourceSearch(src, last, XawsdLeft, &block); 162 if (position == XawTextSearchError) { 163 Feep(); 164 return; 165 } 166 block.ptr[0] = ')'; 167 tmp = position; 168 do { 169 tmp = XawTextSourceSearch(src, tmp, XawsdRight, &block); 170 if (tmp == XawTextSearchError) { 171 Feep(); 172 return; 173 } 174 if (tmp <= last) 175 ++level; 176 } while (++tmp <= last); 177 --level; 178 last = position; 179 } while (level); 180 /* check for extra characters */ 181 while (position > 0) { 182 (void)XawTextSourceRead(src, position - 1, &block, 1); 183 if (block.length != 1 || 184 isspace(block.ptr[0]) || 185 block.ptr[0] == ')' || 186 block.ptr[0] == '"' || 187 block.ptr[0] == '|') 188 break; 189 --position; 190 } 191 } 192 193 if (position < 0 || position >= end) 194 Feep(); 195 else 196 XeditLispExecute(output, position, end); 197} 198 199void 200CreateEditModePopup(Widget parent) 201{ 202 int i; 203 Widget sme; 204 static char *editModes = "editModes"; 205 206 XtVaCreateManagedWidget("modeMenuItem", smeBSBObjectClass, parent, 207 XtNmenuName, editModes, NULL); 208 edit_mode_menu = XtCreatePopupShell(editModes, simpleMenuWidgetClass, 209 parent, NULL, 0); 210 XtRealizeWidget(edit_mode_menu); 211 212 edit_mode_none = XtCreateManagedWidget("none", smeBSBObjectClass, 213 edit_mode_menu, NULL, 0); 214 XtAddCallback(edit_mode_none, XtNcallback, EditModeCallback, NULL); 215 216 for (i = 0; i < num_mode_infos; i++) { 217 sme = XtVaCreateManagedWidget("mode", smeBSBObjectClass, edit_mode_menu, 218 XtNlabel, mode_infos[i].desc, NULL); 219 XtAddCallback(sme, XtNcallback, EditModeCallback, 220 (XtPointer)(mode_infos + i)); 221 mode_infos[i].sme = sme; 222 } 223} 224 225void 226SetEditModeMenu(void) 227{ 228 int i; 229 Widget old_entry = edit_mode_entry, new_entry = edit_mode_none; 230 xedit_flist_item *item = FindTextSource(XawTextGetSource(textwindow), NULL); 231 232 for (i = 0; i < num_mode_infos; i++) { 233 if (item->xldata && item->xldata->syntax && 234 mode_infos[i].syntax == item->xldata->syntax) { 235 new_entry = mode_infos[i].sme; 236 break; 237 } 238 } 239 240 if (old_entry != new_entry) { 241 if (old_entry) 242 XtVaSetValues(old_entry, XtNleftBitmap, None, NULL); 243 XtVaSetValues(new_entry, XtNleftBitmap, flist.pixmap, NULL); 244 edit_mode_entry = new_entry; 245 } 246} 247 248static void 249EditModeCallback(Widget w, XtPointer client_data, XtPointer call_data) 250{ 251 Widget source = XawTextGetSource(textwindow); 252 EditModeInfo *info = (EditModeInfo*)client_data; 253 xedit_flist_item *item = FindTextSource(source, NULL); 254 255 /* If no edit mode selected and selecting the plain/none mode */ 256 if ((info == NULL && 257 (item->xldata == NULL || item->xldata->syntax == NULL)) || 258 /* if selecting the current mode */ 259 (info && item && item->xldata && info->syntax && 260 info->syntax == item->xldata->syntax)) 261 return; 262 263 XawTextSourceClearEntities(source, 264 XawTextSourceScan(source, 0, XawstAll, 265 XawsdLeft, 1, True), 266 XawTextSourceScan(source, 0, XawstAll, 267 XawsdRight, 1, True)); 268 XeditLispUnsetEditMode(item); 269 if (info) 270 XeditLispSetEditMode(item, info->symbol); 271 else 272 item->properties = NULL; 273 UpdateTextProperties(1); 274} 275