21 #include "environment.h" 28 #include <sys/ioctl.h> 35 #include "pedigree/native/graphics/Graphics.h" 37 #include <cairo/cairo.h> 42 char *pName,
size_t nWidth,
size_t nHeight,
size_t offsetLeft,
43 size_t offsetTop,
rgb_t *pBackground, cairo_t *pCairo,
44 class Widget *pWidget,
class Tui *pTui,
class Font *pNormalFont,
45 class Font *pBoldFont)
46 : m_pBuffer(0), m_pFramebuffer(0), m_pXterm(0), m_Len(0),
47 m_WriteBufferLen(0), m_bHasPendingRequest(false), m_PendingRequestSz(0),
48 m_Pid(0), m_OffsetLeft(offsetLeft), m_OffsetTop(offsetTop), m_Cancel(0),
52 cairo_set_operator(pCairo, CAIRO_OPERATOR_SOURCE);
54 cairo_set_source_rgba(pCairo, 0, 0, 0, 0.8);
56 cairo_rectangle(pCairo, m_OffsetLeft, m_OffsetTop, nWidth, nHeight);
59 cairo_restore(pCairo);
61 strncpy(m_pName, pName, 256);
66 0, nWidth, nHeight, m_OffsetLeft, m_OffsetTop,
this, pWidget, pTui,
67 pNormalFont, pBoldFont);
70 mode.width = nWidth - 1;
71 mode.height = nHeight - offsetTop - 1;
79 mode.pf.
nPitch = nWidth * 3;
81 mode, reinterpret_cast<uint8_t *>(m_pBuffer) + nWidth * offsetTop);
87 m_MasterPty = posix_openpt(O_RDWR | O_NOCTTY);
90 klog(LOG_INFO,
"TUI: Couldn't create terminal: %s", strerror(errno));
96 unlockpt(m_MasterPty);
98 char slavename[16] = {0};
99 strncpy(slavename, ptsname(m_MasterPty), 16);
102 struct winsize ptySize;
103 memset(&ptySize, 0,
sizeof(ptySize));
104 ptySize.ws_row = m_pXterm->getRows();
105 ptySize.ws_col = m_pXterm->getCols();
106 ioctl(m_MasterPty, TIOCSWINSZ, &ptySize);
109 int pid = m_Pid = fork();
112 klog(LOG_INFO,
"TUI: Couldn't fork: %s", strerror(errno));
114 write(
"Couldn't fork: ", rect);
115 write(strerror(errno), rect);
131 int n = open(slavename, O_RDONLY);
132 open(slavename, O_WRONLY);
133 open(slavename, O_WRONLY);
137 klog(LOG_INFO,
"opening %s failed", slavename);
139 LOG_INFO,
"opening stdin failed %d %s", errno, strerror(errno));
143 klog(LOG_INFO,
"Trying to set CTTY");
144 ioctl(1, TIOCSCTTY, 0);
147 tcsetpgrp(1, getpgrp());
150 setenv(
"TERM",
"xterm", 1);
153 struct passwd *pw = getpwuid(getuid());
156 const char *prog = pw->pw_shell;
159 prog = getenv(
"SHELL");
165 "$SHELL unset, falling back to /applications/bash");
166 prog =
"/applications/bash";
174 ut.ut_type = USER_PROCESS;
175 ut.ut_pid = getpid();
176 const char *ttyid = slavename + strlen(
"/dev/");
177 strncpy(ut.ut_id, ttyid + strlen(
"tty"), UT_LINESIZE);
178 strncpy(ut.ut_line, ttyid, UT_LINESIZE);
179 strncpy(ut.ut_user, pw->pw_name, UT_NAMESIZE);
180 gettimeofday(&ut.ut_tv, NULL);
188 execl(prog, prog, NULL);
191 "Launching shell failed (next line is the error in errno...)");
192 klog(LOG_ALERT,
"error: %s", strerror(errno));
195 write(
"Couldn't load shell for this terminal... ", rect);
196 write(strerror(errno), rect);
198 "\r\n\r\nYour installation of Pedigree may not be complete, or you " 199 "may have hit a bug.",
211 Terminal::~Terminal()
216 kill(m_Pid, SIGTERM);
219 waitpid(m_Pid, 0, 0);
230 pid_t result = waitpid(m_Pid, 0, WNOHANG);
242 m_pXterm->resize(nWidth, nHeight, 0);
245 struct winsize ptySize;
246 ptySize.ws_row = m_pXterm->getRows();
247 ptySize.ws_col = m_pXterm->getCols();
248 ioctl(m_MasterPty, TIOCSWINSZ, &ptySize);
253 m_pXterm->processKey(key);
260 char c = m_pQueue[0];
261 for (
size_t i = 0; i < m_Len - 1; i++)
262 m_pQueue[i] = m_pQueue[i + 1];
277 m_pXterm->hideCursor(rect);
279 bool bWasAlreadyRunning = m_WriteInProgress;
280 m_WriteInProgress =
true;
282 while (!m_Cancel && (*pStr || m_WriteBufferLen))
285 while (*pStr && !m_Cancel)
287 if (m_WriteBufferLen < 4)
288 m_pWriteBuffer[m_WriteBufferLen++] = *pStr++;
299 if ((m_pWriteBuffer[0] & 0x80) == 0x00)
301 utf32 =
static_cast<uint32_t
>(m_pWriteBuffer[0]);
304 else if ((m_pWriteBuffer[0] & 0xE0) == 0xC0)
306 if (m_WriteBufferLen < 2)
308 utf32 = ((
static_cast<uint32_t
>(m_pWriteBuffer[0]) & 0x1F) << 6) |
309 (static_cast<uint32_t>(m_pWriteBuffer[1]) & 0x3F);
312 else if ((m_pWriteBuffer[0] & 0xF0) == 0xE0)
314 if (m_WriteBufferLen < 3)
316 utf32 = ((
static_cast<uint32_t
>(m_pWriteBuffer[0]) & 0x0F) << 12) |
317 ((static_cast<uint32_t>(m_pWriteBuffer[1]) & 0x3F) << 6) |
318 (
static_cast<uint32_t
>(m_pWriteBuffer[2]) & 0x3F);
321 else if ((m_pWriteBuffer[0] & 0xF8) == 0xF0)
323 if (m_WriteBufferLen < 4)
325 utf32 = ((
static_cast<uint32_t
>(m_pWriteBuffer[0]) & 0x0F) << 18) |
326 ((static_cast<uint32_t>(m_pWriteBuffer[1]) & 0x3F) << 12) |
327 ((
static_cast<uint32_t
>(m_pWriteBuffer[2]) & 0x3F) << 6) |
328 (static_cast<uint32_t>(m_pWriteBuffer[3]) & 0x3F);
333 m_WriteBufferLen = 0;
337 memmove(m_pWriteBuffer, &m_pWriteBuffer[nBytes], 4 - nBytes);
338 m_WriteBufferLen -= nBytes;
342 m_pXterm->write(utf32, rect);
344 rect.point(m_OffsetLeft, m_OffsetTop);
346 m_pXterm->getCols() * 8 + m_OffsetLeft,
347 m_pXterm->getRows() * 16 + m_OffsetTop);
348 m_pXterm->write(static_cast<uint8_t>(utf32 & 0xFF));
354 if (!bWasAlreadyRunning)
358 m_WriteInProgress =
false;
361 m_pXterm->showCursor(rect);
364 void Terminal::addToQueue(
char c,
bool bFlush)
367 if ((c != 0) && (m_Len >= 256))
371 if ((c == 0) && (!m_Len))
377 m_pQueue[m_Len++] = c;
381 ssize_t result = ::write(m_MasterPty, m_pQueue, m_Len);
384 size_t missing = m_Len - result;
386 memmove(m_pQueue, &m_pQueue[result], missing);
391 klog(LOG_ALERT,
"Terminal::addToQueue flush failed");
void processKey(uint64_t key)
void write(const char *pStr, DirtyRectangle &rect)
void renewBuffer(size_t nWidth, size_t nHeight)