/* ** Pad the requested row from the current width to 'newWidth' with spaces... */ void _DtTermPrimBufferPadLineWc ( const TermBuffer tb, const short row, const short width ) { short i; short widthInc; TermLine line; wchar_t *pwc; line = LINE_OF_TBUF(tb, row); if (isDebugFSet('i', 1)) { #ifdef BBA #pragma BBA_IGNORE #endif /*BBA*/ (void) _termBufferValidateLineWc(tb, row); } /* ** if this line is part of the selection, disown the selection... */ if (IS_IN_SELECTION(line, MIN(width, WIDTH(line)), MAX(width, WIDTH(line)))) { (void) _DtTermPrimSelectDisown(WIDGET(tb)); } widthInc = MIN(COLS(tb), width) - WIDTH(line); for (i = 0, pwc = (wchar_t *)BUFFER(line) + MAX(0, LENGTH(line)); i < widthInc; i++, pwc++) { *pwc = L' '; LENGTH(line)++; } if (CLEAR_ENH(tb)) { (*CLEAR_ENH(tb))(tb, row, WIDTH(line), widthInc); } _DtTermPrimBufferSetLineWidth(tb, row, WIDTH(line) + widthInc); if (isDebugFSet('i', 1)) { #ifdef BBA #pragma BBA_IGNORE #endif /*BBA*/ _termBufferValidateLineWc(tb, row); } }
static pid_t FakeFork (void) { static Boolean debugInit = True; static int debugForkFailures = 0; char *c; if (isDebugFSet('f', 10)) { #ifdef BBA #pragma BBA_IGNORE #endif /*BBA*/ _DtTermProcessLock(); if (debugInit) { if (c = getenv("dttermDebugForkFailures")) { debugForkFailures = strtol(c, (char **) 0, 0); debugInit = 0; } } if (debugForkFailures > 0) { /* decrement the number of failures... */ (void) debugForkFailures--; /* set our error return... */ errno = EAGAIN; /* and error out... */ _DtTermProcessUnlock(); return(-1); } _DtTermProcessUnlock(); } /* just do a fork()... */ return(fork()); }
/* ** Parse the character, tell the calling routine if we are not ** in the start state. */ Boolean _DtTermPrimParse ( Widget w, unsigned char *parseChar, int parseCharLen ) { ParserContext context = GetParserContext(w); StateEntry thisEntry; StateEntry thisPreParseEntry; #ifdef NOCODE /* ** This decision should be made somewhere else. */ if (tp->t_modes.disp_func == 1) { in_disp_func(); return(False); } #endif /* NOCODE */ if (parseCharLen == 1) { *context->inputChar = *parseChar; } else { (void) memmove(context->inputChar, parseChar, parseCharLen); } context->inputCharLen = parseCharLen; if (isDebugFSet('p', 1)) { #ifdef BBA #pragma BBA_IGNORE #endif /*BBA*/ static unsigned char debugChar; static Boolean first = True; char *c; if (parseCharLen == 1) { _DtTermProcessLock(); if (first) { if (!(c = getenv("dttermDebugParseChar"))) { c = "0x03"; } debugChar = strtol(c, (char **) 0, 0); first = False; } _DtTermProcessUnlock(); if (*parseChar == debugChar) { ParseTrap(); return 0; } } } /* ** Determine which state entry to use. */ thisPreParseEntry = context->stateTable->statePreParseEntry; thisEntry = context->stateTable->stateEntry; /* first run through the preParse entry... */ if (thisPreParseEntry && (parseCharLen == 1)) { while ((*parseChar < thisPreParseEntry->lower) || (*parseChar > thisPreParseEntry->upper)) { thisPreParseEntry++; } /* if we hit the end, ignore it... */ if ((0x00 == thisPreParseEntry->lower) && (0xff == thisPreParseEntry->upper)) { thisPreParseEntry = (StateEntry) 0; } } /* if we hit a valid preParseEntry, then let's execute it and * return... */ if (thisPreParseEntry) { /* ** Now change states. If the next state is NULL, stay in the ** current state. This is for parse entries that do not break us ** out of the current parse thread. If we need to bail out of the ** current parse thread, then we have a new state specified and ** will switch to it. We do this before we execute the function ** incase the function needs to change the state as well... */ if (thisPreParseEntry->nextState) { context->stateTable = thisPreParseEntry->nextState; } /* ** Execute the action associated with the entry. */ if (thisPreParseEntry->action) { (*thisPreParseEntry->action)(w); } return(!context->stateTable->startState); } /* HACK ALERT!!!! * * We need two different search algorithms - the first to deal * with single byte characters, the second to deal with multi-byte * characters. For now, we will match multi-byte character with * the parse entry that covers 0..255. If we find that this will * not work for everything, we may need to rethink this. */ if (parseCharLen == 1) { while ((*parseChar < thisEntry->lower) || (*parseChar > thisEntry->upper)) { thisEntry++; } } else { while ((0x00 != thisEntry->lower) || (0xff != thisEntry->upper)) { thisEntry++; } } /* ** Now change states. We do this before we execute the function incase ** the function needs to change the state as well... */ context->stateTable = thisEntry->nextState; /* ** Execute the action associated with the entry. */ if (thisEntry->action) { (*thisEntry->action)(w); } return(!context->stateTable->startState); }
void _DtTermPrimRefreshText(Widget w, short startColumn, short startRow, short endColumn, short endRow) { DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) w; struct termData *tpd = tw->term.tpd; TermBuffer tBuffer = tpd->termBuffer; int lineWidth; unsigned char *linePtr; TermFont termFont; int currentColorPair = 0; int currentVideo = 0; short chunkStartColumn; short chunkWidth; enhValues enhancements; int i; int lineNum; unsigned long valueMask; GC gc; XGCValues values; TermEnhInfoRec enhInfo; Boolean checkSelection = False; int selectionEnd; Pixel tmpPixel; XmTextPosition begin, end; DebugF('t', 0, fprintf(stderr, ">>_DtTermPrimRefreshText() starting\n")); DebugF('t', 0, fprintf(stderr, ">>_DtTermPrimRefreshText() startCol=%hd startRow=%hd endCol=%hd endRow=%hd\n", startColumn, startRow, endColumn, endRow)); if (tpd->mbCurMax > 1) { _DtTermPrimRefreshTextWc(w, startColumn, startRow, endColumn, endRow); return; } /* clip start/end x/y... */ if (startColumn <= 0) startColumn = 0; if (startRow <= 0) startRow = 0; if (endColumn >= tw->term.columns) endColumn = tw->term.columns - 1; if (endRow >= tw->term.rows) endRow = tw->term.rows - 1; /* ** don't display if we are in jump scroll and in the process ** of scrolling and inside the scroll region... */ if (tw->term.jumpScroll && tpd->scroll.jump.scrolled) { /* set all the scrollRefreshRows flags... */ for (; startRow <= endRow; startRow++) { tpd->scrollRefreshRows[startRow] = True; } DebugF('t', 0, fprintf(stderr, ">>_DtTermPrimRefreshText() jump scroll in progress, no render\n")); return; } if (!tpd->renderGC.gc) { /* get a drawImageString GC... */ int i; XGCValues values; /*********************************************************** * renderGC... */ /* set the GC fg and bg... */ values.foreground = tw->term.reverseVideo ? tw->core.background_pixel : tw->primitive.foreground; values.background = tw->term.reverseVideo ? tw->primitive.foreground : tw->core.background_pixel; tpd->renderGC.gc = XCreateGC(XtDisplay(w), XtWindow(w), GCForeground | GCBackground, &values); /* set the GC cache values... */ tpd->renderGC.foreground = values.foreground; tpd->renderGC.background = values.background; tpd->renderGC.fid = (Font) 0; /*********************************************************** * renderReverseGC... */ values.foreground = tw->term.reverseVideo ? tw->primitive.foreground : tw->core.background_pixel; values.background = tw->term.reverseVideo ? tw->core.background_pixel : tw->primitive.foreground; tpd->renderReverseGC.gc = XCreateGC(XtDisplay(w), XtWindow(w), GCForeground | GCBackground, &values); /* set the GC cache values... */ tpd->renderReverseGC.foreground = values.foreground; tpd->renderReverseGC.background = values.background; tpd->renderReverseGC.fid = (Font) 0; /*********************************************************** * clearGC... */ values.foreground = tw->term.reverseVideo ? tw->primitive.foreground : tw->core.background_pixel; values.background = tw->term.reverseVideo ? tw->core.background_pixel : tw->primitive.foreground; tpd->clearGC.gc = XCreateGC(XtDisplay(w), XtWindow(w), GCForeground | GCBackground, &values); /* set the GC cache values... */ tpd->clearGC.foreground = values.foreground; tpd->clearGC.background = values.background; tpd->clearGC.fid = (Font) 0; } #ifdef SUN_MOTIF_PERF /* use the clear GC... */ gc = tpd->clearGC.gc; valueMask = (unsigned long) 0; if (tpd->clearGC.foreground != tw->term.reverseVideo ? tw->core.background_pixel : tw->primitive.foreground) { values.foreground = tw->term.reverseVideo ? tw->primitive.foreground : tw->core.background_pixel; tpd->clearGC.foreground = values.foreground; valueMask |= GCForeground; } if (tpd->clearGC.background != tw->term.reverseVideo ? tw->primitive.foreground : tw->core.background_pixel) { values.background = tw->term.reverseVideo ? tw->core.background_pixel : tw->primitive.foreground; tpd->clearGC.background = values.background; valueMask |= GCBackground; } if (valueMask) { (void) XChangeGC(XtDisplay(w), tpd->clearGC.gc, valueMask, &values); } (void) XFillRectangle(XtDisplay(w), /* Display */ XtWindow(w), /* Drawable */ gc, /* GC */ startColumn * tpd->cellWidth + tpd->offsetX, /* x */ startRow * tpd->cellHeight + tpd->offsetY, /* y */ (endColumn - startColumn + 1) * tpd->cellWidth, /* width */ (endRow - startRow + 1) * tpd->cellHeight); /* height */ #endif /* SUN_MOTIF_PERF */ for (; startRow <= endRow; startRow++) { /* if we are refreshing a full line, then we can clear the * scrollRefreshRows flag for this line... */ if ((startColumn == 0) && (endColumn >= tw->term.columns - 1)) { tpd->scrollRefreshRows[startRow] = False; } lineNum = startRow + tpd->topRow; if (!tw->term.jumpScroll && tpd->scroll.nojump.pendingScroll) { if (lineNum != tpd->scrollLockBottomRow) { lineNum -= tpd->scroll.nojump.pendingScrollLines; } } /* are we in the selected area?... */ if (tpd->useHistoryBuffer) { if (_DtTermPrimSelectGetSelection(w, &begin, &end) && (begin < end) && (lineNum >= (begin / (tpd->selectInfo->columns + 1)) - tpd->lastUsedHistoryRow) && (lineNum <= (end / (tpd->selectInfo->columns + 1)) - tpd->lastUsedHistoryRow)) { checkSelection = True; } else { checkSelection = False; } } else { if (_DtTermPrimSelectGetSelection(w, &begin, &end) && (begin < end) && (lineNum >= (begin / (tpd->selectInfo->columns + 1))) && (lineNum <= (end / (tpd->selectInfo->columns + 1)))) { checkSelection = True; } else { checkSelection = False; } } chunkStartColumn = startColumn; if (startColumn > endColumn) { /* nothing to render on this line... */ continue; } if (lineNum >= tpd->lastUsedRow) { /* we are pointing to empty screen space below the last used * line of the display... */ lineWidth = 0; linePtr = NULL; } else if (lineNum < 0) { if ((tpd->useHistoryBuffer) && (-lineNum <= tpd->lastUsedHistoryRow)) { /* get a line out of the history buffer... */ lineWidth = MAX(0, MIN(endColumn - startColumn + 1, _DtTermPrimBufferGetLineWidth(tpd->historyBuffer, tpd->lastUsedHistoryRow + lineNum) - startColumn)); linePtr = _DtTermPrimBufferGetCharacterPointer(tpd->historyBuffer, tpd->lastUsedHistoryRow + lineNum, startColumn); } else { /* we are above the history buffer. Should not happen, but... */ lineWidth = 0; linePtr = NULL; } } else { /* get the line width and a pointer to the data... */ lineWidth = MAX(0, MIN(endColumn - startColumn + 1, _DtTermPrimBufferGetLineWidth(tBuffer, lineNum) - startColumn)); linePtr = _DtTermPrimBufferGetCharacterPointer(tBuffer, lineNum, startColumn); } while (lineWidth > 0) { /* get the enhancement values for the first chunk of the * string... */ if (lineNum >= 0) { (void) _DtTermPrimBufferGetEnhancement(tBuffer, /* TermBuffer */ lineNum, /* row */ chunkStartColumn, /* col */ &enhancements, /* enhancements */ &chunkWidth, /* width */ countAll); /* countWhich */ } else { /* get it from the history buffer... */ (void) _DtTermPrimBufferGetEnhancement(tpd->historyBuffer, /* TermBuffer */ tpd->lastUsedHistoryRow + lineNum, /* row */ chunkStartColumn, /* col */ &enhancements, /* enhancements */ &chunkWidth, /* width */ countAll); /* countWhich */ } /* clip chunkWidth... */ if (chunkWidth > lineWidth) chunkWidth = lineWidth; /* set reasonable defaults for our render info... */ enhInfo.fg = tw->primitive.foreground; enhInfo.bg = tw->core.background_pixel; enhInfo.font = tpd->defaultTermFont; enhInfo.flags = (unsigned long) 0; /* set our font and color from the enhancements... */ if (ENH_PROC(tBuffer)) { (void) (*(ENH_PROC(tBuffer)))(w, enhancements, &enhInfo); } /* if we are in reverse video mode... */ if (tw->term.reverseVideo) { /* flip fg and bg... */ tmpPixel = enhInfo.fg; enhInfo.fg = enhInfo.bg; enhInfo.bg = tmpPixel; } /* are we in the selection area?... */ if (checkSelection && _DtTermPrimSelectIsInSelection(w, lineNum, chunkStartColumn, chunkWidth, &chunkWidth)) { /* flip fg and bg... */ tmpPixel = enhInfo.fg; enhInfo.fg = enhInfo.bg; enhInfo.bg = tmpPixel; } /* if secure, we will use a XFillRectangle, and we need * foreground set to the background... */ if (TermIS_SECURE(enhInfo.flags)) { /* render secure video locally... */ /* set the renderReverseGC... */ valueMask = (unsigned long) 0; if (tpd->renderReverseGC.foreground != enhInfo.bg) { tpd->renderReverseGC.foreground = enhInfo.bg; values.foreground = enhInfo.bg; valueMask |= GCForeground; } if (valueMask) { (void) XChangeGC(XtDisplay(w), tpd->renderReverseGC.gc, valueMask, &values); } (void) XFillRectangle(XtDisplay(w), XtWindow(w), tpd->renderReverseGC.gc, chunkStartColumn * tpd->cellWidth + tpd->offsetX, startRow * tpd->cellHeight + tpd->offsetY, tpd->cellWidth * chunkWidth, tpd->cellHeight); /* underline as well... */ if (TermIS_UNDERLINE(enhInfo.flags)) { valueMask = (unsigned long) 0; if (tpd->renderGC.foreground != enhInfo.fg) { tpd->renderGC.foreground = enhInfo.fg; values.foreground = enhInfo.fg; valueMask |= GCForeground; } if (valueMask) { (void) XChangeGC(XtDisplay(w), tpd->renderGC.gc, valueMask, &values); } (void) XDrawLine(XtDisplay(w), /* Display */ XtWindow(w), /* Drawable */ tpd->renderGC.gc, /* GC */ chunkStartColumn * tpd->cellWidth + tpd->offsetX, /* X1 */ startRow * tpd->cellHeight + tpd->offsetY + tpd->cellHeight - 1, /* Y1 */ (chunkStartColumn + chunkWidth) * tpd->cellWidth + tpd->offsetX, /* X2 */ startRow * tpd->cellHeight + tpd->offsetY + tpd->cellHeight - 1); /* Y2 */ } } else { (void) _DtTermPrimRenderText( w, /* Widget */ enhInfo.font, /* TermFont */ enhInfo.fg, /* fg Pixel */ enhInfo.bg, /* bg Pixel */ enhInfo.flags, /* flags */ chunkStartColumn * tpd->cellWidth + tpd->offsetX, /* x */ startRow * tpd->cellHeight + tpd->offsetY, /* y */ linePtr, /* string */ chunkWidth); /* width */ } chunkStartColumn += chunkWidth; lineWidth -= chunkWidth; linePtr += chunkWidth; } /* clear any extra space in the line. chunkStartColumn now points to * the end of the line, and lineWidth == 0... */ while (endColumn - chunkStartColumn >= 0) { chunkWidth = endColumn - chunkStartColumn + 1; if (checkSelection && _DtTermPrimSelectIsInSelection(w, lineNum, chunkStartColumn, chunkWidth, &chunkWidth)) { /* use the render gc set to the fg color... */ gc = tpd->renderReverseGC.gc; valueMask = (unsigned long) 0; if (tpd->renderReverseGC.foreground != tw->term.reverseVideo ? tw->core.background_pixel : tw->primitive.foreground) { values.foreground = tw->term.reverseVideo ? tw->core.background_pixel : tw->primitive.foreground; tpd->renderReverseGC.foreground = values.foreground; valueMask |= GCForeground; } if (valueMask) { (void) XChangeGC(XtDisplay(w), tpd->renderReverseGC.gc, valueMask, &values); } #ifndef SUN_MOTIF_PERF } else { /* use the clear GC... */ gc = tpd->clearGC.gc; valueMask = (unsigned long) 0; if (tpd->clearGC.foreground != tw->term.reverseVideo ? tw->core.background_pixel : tw->primitive.foreground) { values.foreground = tw->term.reverseVideo ? tw->primitive.foreground : tw->core.background_pixel; tpd->clearGC.foreground = values.foreground; valueMask |= GCForeground; } if (tpd->clearGC.background != tw->term.reverseVideo ? tw->primitive.foreground : tw->core.background_pixel) { values.background = tw->term.reverseVideo ? tw->core.background_pixel : tw->primitive.foreground; tpd->clearGC.background = values.background; valueMask |= GCBackground; } if (valueMask) { (void) XChangeGC(XtDisplay(w), tpd->clearGC.gc, valueMask, &values); } } #endif /* not SUN_MOTIF_PERF */ if (isDebugFSet('t', 1)) { #ifdef BBA #pragma BBA_IGNORE #endif /*BBA*/ /* Fill in the clear area so we can see what is going to * be displayed... */ (void) XFillRectangle(XtDisplay(w), XtWindow(w), tpd->renderGC.gc, chunkStartColumn * tpd->cellWidth + tpd->offsetX, startRow * tpd->cellHeight + tpd->offsetY, chunkWidth * tpd->cellWidth, tpd->cellHeight); (void) XSync(XtDisplay(w), False); (void) shortSleep(100000); } (void) XFillRectangle(XtDisplay(w), /* Display */ XtWindow(w), /* Drawable */ gc, /* GC */ chunkStartColumn * tpd->cellWidth + tpd->offsetX, /* x */ startRow * tpd->cellHeight + tpd->offsetY, /* y */ chunkWidth * tpd->cellWidth, /* width */ tpd->cellHeight); /* height */ #ifdef SUN_MOTIF_PERF } #endif /* SUN_MOTIF_PERF */ chunkStartColumn += chunkWidth; } }
/* ** Insert as many characters as possible at the specified row,col ** return a count of the number of characters bumped off the end of the line ** in 'returnLength' and a pointer to a buffer containing those characters ** 'returnChars'. ** ** The the new column width of the line is returned as the value of the ** function. ** ** NOTES: ** We are trying to implement mechanism and not policy. This ** routine does a minimum of checking for boundary conditions. */ short _DtTermPrimBufferInsertWc ( const TermBuffer tb, const short row, const short col, wchar_t *newChars, short numChars, Boolean insertFlag, /* if TRUE, insert, else overwrite */ termChar **returnChars, /* pointer to overflow buffer */ short *returnLength /* count of characters in overflow buffer */ ) { short widthInc; /* incremental change in line width */ short lengthInc; /* incremental change in line length */ short widthInsert; /* column width of chars inserted */ short localCol; TermLine line; if (!VALID_ROW(tb, row) || !VALID_COL(tb, col)) { *returnLength = 0; return(0); } if (isDebugFSet('i', 1)) { #ifdef BBA #pragma BBA_IGNORE #endif /*BBA*/ (void) _termBufferValidateLineWc(tb, row); } line = LINE_OF_TBUF(tb, row); localCol = col; if (WIDTH(line) < col) { /* ** We're adding characters past the current end of line, ** pad it out. */ _DtTermPrimBufferPadLineWc(tb, row, col); } /* ** It doesn't matter if we're overwriting, or inserting at the end ** of the line, the result is the same... */ if (insertFlag == False || col == WIDTH(line)) { _primBufferOverwriteWc(tb, row, &localCol, newChars, numChars, &lengthInc, &widthInc, &widthInsert, *returnChars, returnLength); } else { _primBufferInsertWc(tb, row, &localCol, newChars, numChars, &lengthInc, &widthInc, &widthInsert, *returnChars, returnLength); } /* ** Everything's ready: ** - put the characters into the line ** - adjust the line width (_DtTermPrimBufferSetLineWidth won't ** let the line get shorter)... ** - adjust the line length ** - update the enhancements */ WIDTH(line) += widthInc; LENGTH(line) += lengthInc; /* ** fix up the enhancments... */ if (INSERT_ENH(tb)) { (*INSERT_ENH(tb))(tb, row, col, widthInsert, insertFlag); } if (isDebugFSet('i', 1)) { #ifdef BBA #pragma BBA_IGNORE #endif /*BBA*/ (void) _termBufferValidateLineWc(tb, row); } return(WIDTH(line)); }
static int GetPty(char **ptySlave, char **ptyMaster) { char *c; int ptyFd; int ttyFd; *ptyMaster = malloc(strlen(PTY_CLONE_DEVICE) + 1); (void) strcpy(*ptyMaster, PTY_CLONE_DEVICE); if (isDebugFSet('p', 10)) { #ifdef BBA #pragma BBA_IGNORE #endif /*BBA*/ return(-1); } if ((ptyFd = open(*ptyMaster, O_RDWR, 0))) { _Xttynameparams tty_buf; #if defined(linux) if (c = _XTtyname(ptyFd)) { #else if (c = _XTtyname(ptyFd, tty_buf)) { #endif *ptySlave = malloc(strlen(c) + 1); (void) strcpy(*ptySlave, c); if ((ttyFd = open(*ptySlave, O_RDWR | O_NOCTTY, 0)) < 0) { /* failure... */ (void) perror(*ptySlave); (void) close(ptyFd); } else { /* success... */ /* close off the pty slave... */ (void) close(ttyFd); /* fix the owner, mode, and group... */ #ifdef HP_ARCHITECTURE { struct group *grp; gid_t gid; _Xgetgrparams grp_buf; if (grp = _XGetgrnam("tty", grp_buf)) { gid = grp->gr_gid; } else { gid = 0; } (void) endgrent(); (void) chown(*ptySlave, getuid(), gid); (void) chmod(*ptySlave, 0620); } #else /* HP_ARCHITECTURE */ (void) chown(*ptySlave, getuid(), getgid()); (void) chmod(*ptySlave, 0622); #endif /* HP_ARCHITECTURE */ /* pty master and slave names are already set. Return * the file descriptor... */ return(ptyFd); } } else { /* ttyname on the pty master failed. This should not happen!... */ (void) perror("ttyname"); (void) close(ptyFd); } } else { (void) perror(*ptyMaster); } return(-1); } /* this is a public wrapper around the previous function that runs the * previous function setuid root... */ int _DtTermPrimGetPty(char **ptySlave, char **ptyMaster) { int retValue; /* this function needs to be suid root... */ (void) _DtTermPrimToggleSuidRoot(True); retValue = GetPty(ptySlave, ptyMaster); /* we now need to turn off setuid root... */ (void) _DtTermPrimToggleSuidRoot(False); return(retValue); }