#include "univ.h" #include #include #include #include #include #include #include #include #include #include void textmarginCB(); void textbuttonCB(); void textmotionCB(); void textkeyhitCB(); void textmodifyCB(); void windowunmapEH(); void windowpopdownCB(); WindowCreate(p) register Pad *p; { register PadLine *l, *last; int lineno; char *res; Widget control2; TextLocation locs; char *buf, *cp; int cnt; res = padnametoresource(p->sentinel.text); p->pane = XtVaAppCreateShell(res, "Pads", topLevelShellWidgetClass, XtDisplay(basepane), XtNtitle, p->sentinel.text, XtNwinType, OL_WT_CMD, XtNpushpin, OL_IN, XtNallowShellResize, FALSE, NULL); XtAddEventHandler(p->pane, StructureNotifyMask, FALSE, windowunmapEH, p); wmcatch(p); p->form = XtVaCreateManagedWidget("pane", formWidgetClass, p->pane, NULL); p->control = XtVaCreateManagedWidget("control", controlAreaWidgetClass, p->form, NULL); control2 = XtVaCreateManagedWidget("control2", controlAreaWidgetClass, p->form, XtNxRefWidget, p->control, XtNxAddWidth, TRUE, NULL); texteditmenu(p, control2); p->scrollwin = XtVaCreateManagedWidget("scrollw", scrolledWindowWidgetClass, p->form, XtNyRefWidget, control2, XtNyAddHeight, TRUE, XtNxResizable, TRUE, XtNyResizable, TRUE, XtNyAttachBottom, TRUE, XtNxAttachRight, TRUE, NULL); p->textw = XtVaCreateManagedWidget("text", textEditWidgetClass, p->scrollwin, XtNwrapMode, OL_WRAP_OFF, NULL); p->textb = OlTextEditTextBuffer(p->textw); XtAddCallback(p->textw, XtNmargin, textmarginCB, (XtPointer)p); XtAddCallback(p->textw, XtNbuttons, textbuttonCB, (XtPointer)p); XtAddCallback(p->textw, XtNkeys, textkeyhitCB, (XtPointer)p); XtAddCallback(p->textw, XtNmodifyVerification, textmodifyCB, (XtPointer)p); XtAddCallback(p->textw, XtNmotionVerification, textmotionCB, (XtPointer)p); WindowChangeMenu(p); /* * Copy the whole string in at once for efficiency, in case * the size of the window is large. */ last = &p->sentinel; cnt = 0; for(lineno = 0, l = last->down; l != last; l = l->down, lineno++) { l->windowline = lineno; cnt += strlen(l->text) + 1; } cp = buf = (char *)XtMalloc(cnt + 1); for(l = last->down; l != last; l = l->down) { cnt = strlen(l->text); strcpy(cp, l->text); cp += cnt; *cp++ = '\n'; } *cp = 0; locs = LocationOfPosition(p->textb, 0); ReplaceBlockInTextBuffer(p->textb, &locs, &locs, buf, NULL, NULL); XtFree(buf); last->windowline = lineno; XtRealizeWidget(p->pane); } WindowDestroy(p) register Pad *p; { XtDestroyWidget(p->pane); p->nomenus = 0; p->nopopups = 0; p->popstate = 0; } void windowpopdownCB(w, p, call_data) Widget w; Pad *p; XtPointer call_data; { if (!keyinputclosed) DeletePad(p); } void windowunmapEH(w, p, ev) Widget w; Pad *p; XEvent *ev; { switch (ev->type) { case UnmapNotify: if (!keyinputclosed) DeletePad(p); break; } } void textbuttonCB(tw, p, cd) Widget tw; register Pad *p; OlInputCallData *cd; { TextPosition start, end, cursor; Index index; int line; switch(cd->ol_event) { case OL_SELECT: break; case OL_MENU: cd->consumed = TRUE; OlTextEditGetCursorPosition(p->textw, &start, &end, &cursor); line = LineOfPosition(p->textb, start); LineMenu(p, line, cd->event->xbutton.x_root, cd->event->xbutton.y_root); break; } } void textkeyhitCB(tw, p, cd) Widget tw; Pad *p; OlInputCallData *cd; { TextPosition start, end, cursor; int line; switch(cd->ol_event) { case OL_UNKNOWN_KEY_INPUT: case OL_RETURN: OlTextEditGetCursorPosition(p->textw, &start, &end, &cursor); line = LineOfPosition(p->textb, start); ChangeSelection(p, line, (PadLine*)0); if (cd->ol_event == OL_RETURN) OlTextEditInsert(keytextw, "\n", 1); else if (*cd->length) OlTextEditInsert(keytextw, cd->buffer, *cd->length); cd->consumed = TRUE; break; case OL_DELCHARBAK: OlTextEditGetCursorPosition(keytextw, &start, &end, &cursor); if (start < end) OlTextEditInsert(keytextw, "", 0); else if (--start >= 0) { OlTextEditSetCursorPosition(keytextw, start,end,cursor); OlTextEditInsert(keytextw, "", 0); } cd->consumed = TRUE; break; } } /* * Since all modifications are made directly to the TextBuffer (to keep * the TextEdit Widget from moving the display around with its own algorithms) * this routine is only called when a key stroke or mouse operation tries * to edit the text. This isn't allowed with pads windows, so all requests * are rejected */ void textmodifyCB(tw, p, cd) Widget tw; Pad *p; OlTextModifyCallData *cd; { cd->ok = FALSE; } void textmotionCB(tw, p, cd) Widget tw; Pad *p; OlTextMotionCallData *cd; { int line; line = LineOfPosition(p->textb, cd->select_start); ChangeSelection(p, line, (PadLine *)0); } void textmarginCB(tw, p, md) Widget tw; register Pad *p; OlTextMarginCallData *md; { int nlines; int startline; int endline; int position; int reqlines, startkey; register PadLine *l; XtVaGetValues(tw, XtNlinesVisible, &nlines, XtNdisplayPosition, &position, NULL); startline = LineOfPosition(p->textb, position); endline = startline + nlines; if (endline >= p->sentinel.windowline) endline = p->sentinel.windowline; l = LineiToPadLine(p, startline); reqlines = 0; while (startline++ < endline) { if (l->po.attributes & FAKELINE) { if (!reqlines) startkey = l->key; reqlines++; l->po.attributes &= ~FAKELINE; } else if (reqlines) { LineReq(p, startkey, startkey + reqlines - 1); reqlines = 0; } l = l->down; } if (reqlines) LineReq(p, startkey, startkey + reqlines - 1); } WindowDeleteLine(p, l) Pad *p; int l; { TextPosition start, end; TextLocation locs, loce; start = PositionOfLine(p->textb, l); if (start == EOF) return; end = start + LengthOfTextBufferLine(p->textb, l); locs = LocationOfPosition(p->textb, start); loce = LocationOfPosition(p->textb, end); ReplaceBlockInTextBuffer(p->textb, &locs, &loce, "", NULL, NULL); } WindowInsertLine(p, l, t) Pad *p; int l; register char *t; { TextLocation loc; TextPosition start; register char *s; char buffer[257]; for (s = buffer; *t; ) *s++ = *t++; *s++ = '\n'; *s = 0; start = PositionOfLine(p->textb, l); loc = LocationOfPosition(p->textb, start); ReplaceBlockInTextBuffer(p->textb, &loc, &loc, buffer, NULL, NULL); } WindowReplaceLine(p, l, t) Pad *p; int l; register char *t; { TextPosition start, end; TextLocation locs, loce; register char *s; char buffer[257]; for (s = buffer; *t; ) *s++ = *t++; *s++ = '\n'; *s = 0; start = PositionOfLine(p->textb, l); if (start == EOF) end = EOF; else end = start + LengthOfTextBufferLine(p->textb, l); locs = LocationOfPosition(p->textb, start); loce = LocationOfPosition(p->textb, end); ReplaceBlockInTextBuffer(p->textb, &locs, &loce, buffer, NULL, NULL); } WindowClear(p) Pad *p; { TextLocation locs, loce; locs = LocationOfPosition(p->textb, 0); loce = LastTextBufferLocation(p->textb); ReplaceBlockInTextBuffer(p->textb, &locs, &loce, "", NULL, NULL); } WindowUpdate(p, onoff) Pad *p; int onoff; { if (onoff) OlTextEditUpdate(p->textw, TRUE); else OlTextEditUpdate(p->textw, FALSE); } WindowSelectLine(p, l, a) Pad *p; int l; Attrib a; { TextPosition start, end; int nlines, needtomove = 0; int startline, endline, newfirst; TextPosition position; XtVaGetValues(p->textw, XtNlinesVisible, &nlines, XtNdisplayPosition, &position, NULL); startline = LineOfPosition(p->textb, position); endline = startline + nlines - 1; if (a & SELECTLINET) { if (startline != l) { newfirst = l; needtomove = 1; } } else if (l <= startline || l >= endline) { newfirst = l - (nlines >> 1); needtomove = 1; } if (needtomove) { if (newfirst < 0) newfirst = 0; else if ((newfirst + nlines) > p->sentinel.windowline) newfirst = p->sentinel.windowline - nlines; position = PositionOfLine(p->textb, newfirst); XtVaSetValues(p->textw, XtNdisplayPosition, position, NULL); } start = PositionOfLine(p->textb, l); end = start + LengthOfTextBufferLine(p->textb, l); OlTextEditSetCursorPosition(p->textw, start, end, end); } WindowShowLine(p, l) Pad *p; int l; { int nlines; int startline, endline; TextPosition position; XtVaGetValues(p->textw, XtNlinesVisible, &nlines, XtNdisplayPosition, &position, NULL); startline = LineOfPosition(p->textb, position); endline = startline + nlines - 1; if (l >= endline + nlines) { position = PositionOfLine(p->textb, endline + 1); XtVaSetValues(p->textw, XtNdisplayPosition, position, NULL); } } void texteditsendCB(w, p, call_data) Widget w; Pad *p; XtPointer call_data; { TextPosition start, end, cursor; char *buf; OlTextEditGetCursorPosition(p->textw, &start, &end, &cursor); if (start >= end) return; OlTextEditReadSubString(p->textw, &buf, start, end - 1); OlTextEditInsert(keytextw, buf, end - start); free(buf); } void texteditcopyCB(w, p, call_data) Widget w; Pad *p; XtPointer call_data; { OlTextEditCopySelection(p->textw, False); } void texteditcutCB(w, p, call_data) Widget w; Pad *p; XtPointer call_data; { TextPosition start, end, cursor; int first, last; OlTextEditGetCursorPosition(p->textw, &start, &end, &cursor); first = LineOfPosition(p->textb, start); if (first >= p->sentinel.windowline) return; /* If a complete line is selected, end may be on the next line */ if (end > start) end--; last = LineOfPosition(p->textb, end); if (last >= p->sentinel.windowline) last = p->sentinel.windowline - 1; CutLines(p, first, last); } void texteditclearCB(w, p, call_data) Widget w; Pad *p; XtPointer call_data; { CutLines(p, 0, p->sentinel.windowline - 1); } void texteditcloseCB(w, p, call_data) Widget w; Pad *p; XtPointer call_data; { DeletePad(p); } texteditmenu(p, c) Pad *p; Widget c; { Widget menu, pane, send, copy, cut, close, clear; menu = XtVaCreateManagedWidget("edit", menuButtonWidgetClass, c, XtNpushpin, OL_NONE, NULL); XtVaGetValues(menu, XtNmenuPane, &pane, NULL); send = XtVaCreateManagedWidget("send", oblongButtonWidgetClass, pane, XtNlabelJustify, OL_CENTER, NULL); cut = XtVaCreateManagedWidget("cut", oblongButtonWidgetClass, pane, XtNlabelJustify, OL_CENTER, NULL); clear = XtVaCreateManagedWidget("clear", oblongButtonWidgetClass, pane, XtNlabelJustify, OL_CENTER, NULL); copy = XtVaCreateManagedWidget("copy", oblongButtonWidgetClass, pane, XtNlabelJustify, OL_CENTER, NULL); close = XtVaCreateManagedWidget("close", oblongButtonWidgetClass, pane, XtNlabelJustify, OL_CENTER, NULL); XtAddCallback(send, XtNselect, texteditsendCB, (XtPointer)p); XtAddCallback(cut, XtNselect, texteditcutCB, (XtPointer)p); XtAddCallback(clear, XtNselect, texteditclearCB, (XtPointer)p); XtAddCallback(copy, XtNselect, texteditcopyCB, (XtPointer)p); XtAddCallback(close, XtNselect, texteditcloseCB, (XtPointer)p); if (p->helpcarte) addhelpmenu(p, pane); } static void helpmenuCB(w, user_data, call_data) Widget w; XtPointer user_data; XtPointer call_data; { long data; PadObj *po; po = (PadObj *)user_data; XtVaGetValues(w, XtNuserData, &data, NULL); ToHost(P_ACTION, data, po, po); } addhelpmenu(p, w) Pad *p; Widget w; { Widget helpm, helpp, hw; Carte *c; char *s; int i; c = IndexToCarte(p->helpcarte); if (!c->bin[0]) return; s = IndexToStr(c->bin[0]); if (c->size == 1) { hw = XtVaCreateManagedWidget(s, oblongButtonWidgetClass, w, XtNuserData, (XtPointer)c->bin[1], XtNlabelJustify, OL_CENTER, NULL); XtAddCallback(hw, XtNselect, helpmenuCB, (XtPointer)&p->po); return; } helpm = XtVaCreateManagedWidget(s, menuButtonWidgetClass, w, XtNpushpin, OL_NONE, NULL); XtVaGetValues(helpm, XtNmenuPane, &helpp, NULL); for(i = 1; i <= c->size; i++) { s = IndexToStr(c->bin[i]); hw = XtVaCreateManagedWidget(s, oblongButtonWidgetClass, helpp, XtNuserData, (XtPointer)c->bin[i], XtNlabelJustify, OL_CENTER, NULL); XtAddCallback(hw, XtNselect, helpmenuCB, (XtPointer)&p->po); } } void wmmesgCB(w, p, verify) Widget w; Pad *p; OlWMProtocolVerify *verify; { if (verify->msgtype == OL_WM_DELETE_WINDOW) DeletePad(p); } wmcatch(p) Pad *p; { OlAddCallback(p->pane, XtNwmProtocol, wmmesgCB, (XtPointer)p); }