19105df34Sshatty/*
25b41331fSSiarzhuk Zharski * Copyright 2001-2013, Haiku, Inc.
39105df34Sshatty * Copyright (c) 2003-4 Kian Duffy <myob@users.sourceforge.net>
421543141SAxel Dörfler * Parts Copyright (C) 1998,99 Kazuho Okui and Takashi Murai.
58eb8269dSAxel Dörfler * Distributed under the terms of the MIT license.
65b41331fSSiarzhuk Zharski *
75b41331fSSiarzhuk Zharski * Authors:
85b41331fSSiarzhuk Zharski *		Kian Duffy, myob@users.sourceforge.net
98840b3dbSSimon South *		Simon South, simon@simonsouth.net
105b41331fSSiarzhuk Zharski *		Siarzhuk Zharski, zharik@gmx.li
119105df34Sshatty */
1221543141SAxel Dörfler
1362a8fd3bSAxel Dörfler
1421543141SAxel Dörfler//! Escape sequence parse and character encoding.
1521543141SAxel Dörfler
1662a8fd3bSAxel Dörfler
17abc47202SStefano Ceccherini#include "TermParse.h"
18abc47202SStefano Ceccherini
19fdfbd664SJérôme Duval#include <ctype.h>
209105df34Sshatty#include <errno.h>
219105df34Sshatty#include <stdio.h>
2268ea9ce5SSiarzhuk Zharski#include <stdlib.h>
239105df34Sshatty#include <signal.h>
2415cdb346SIngo Weinhold#include <string.h>
259105df34Sshatty#include <unistd.h>
269105df34Sshatty
2752b1d543SIngo Weinhold#include <Autolock.h>
2863dc9cc2SStefano Ceccherini#include <Beep.h>
298989d8a5SStephan Aßmus#include <Catalog.h>
308989d8a5SStephan Aßmus#include <Locale.h>
319105df34Sshatty#include <Message.h>
3274d2e159SStefano Ceccherini#include <UTF8.h>
339105df34Sshatty
3468ea9ce5SSiarzhuk Zharski#include "Colors.h"
354386ce02SIngo Weinhold#include "TermConst.h"
364386ce02SIngo Weinhold#include "TerminalBuffer.h"
374386ce02SIngo Weinhold#include "VTparse.h"
384386ce02SIngo Weinhold
399105df34Sshatty
4087f17bdfSStefano Ceccheriniextern int gUTF8GroundTable[];		/* UTF8 Ground table */
4187f17bdfSStefano Ceccheriniextern int gISO8859GroundTable[];	/* ISO8859 & EUC Ground table */
42f3782185SSiarzhuk Zharskiextern int gWinCPGroundTable[];		/* Windows cp1252, cp1251, koi-8r */
4387f17bdfSStefano Ceccheriniextern int gSJISGroundTable[];		/* Shift-JIS Ground table */
4463dc9cc2SStefano Ceccherini
4521543141SAxel Dörflerextern int gEscTable[];				/* ESC */
4621543141SAxel Dörflerextern int gCsiTable[];				/* ESC [ */
4721543141SAxel Dörflerextern int gDecTable[];				/* ESC [ ? */
4821543141SAxel Dörflerextern int gScrTable[];				/* ESC # */
4921543141SAxel Dörflerextern int gIgnoreTable[];			/* ignore table */
5021543141SAxel Dörflerextern int gIesTable[];				/* ignore ESC table */
5187f17bdfSStefano Ceccheriniextern int gEscIgnoreTable[];		/* ESC ignore table */
5263dc9cc2SStefano Ceccherini
53daebca78SSiarzhuk Zharskiextern const char* gLineDrawGraphSet[]; /* may be used for G0, G1, G2, G3 */
5463dc9cc2SStefano Ceccherini
5563dc9cc2SStefano Ceccherini#define DEFAULT -1
5663dc9cc2SStefano Ceccherini#define NPARAM 10		// Max parameters
5763dc9cc2SStefano Ceccherini
587f108511SAxel Dörfler
59540e66d6SIngo Weinhold//! Get char from pty reader buffer.
6074d2e159SStefano Ceccheriniinline uchar
6174d2e159SStefano CeccheriniTermParse::_NextParseChar()
62540e66d6SIngo Weinhold{
63540e66d6SIngo Weinhold	if (fParserBufferOffset >= fParserBufferSize) {
64540e66d6SIngo Weinhold		// parser buffer empty
65540e66d6SIngo Weinhold		status_t error = _ReadParserBuffer();
66540e66d6SIngo Weinhold		if (error != B_OK)
6774d2e159SStefano Ceccherini			throw error;
68540e66d6SIngo Weinhold	}
69540e66d6SIngo Weinhold
7013d04396SSiarzhuk Zharski#ifdef USE_DEBUG_SNAPSHOTS
7113d04396SSiarzhuk Zharski	fBuffer->CaptureChar(fParserBuffer[fParserBufferOffset]);
7213d04396SSiarzhuk Zharski#endif
7313d04396SSiarzhuk Zharski
7474d2e159SStefano Ceccherini	return fParserBuffer[fParserBufferOffset++];
75540e66d6SIngo Weinhold}
76540e66d6SIngo Weinhold
77540e66d6SIngo Weinhold
78ac3a8f54SStefano CeccheriniTermParse::TermParse(int fd)
7963dc9cc2SStefano Ceccherini	:
8063dc9cc2SStefano Ceccherini	fFd(fd),
8163dc9cc2SStefano Ceccherini	fParseThread(-1),
8263dc9cc2SStefano Ceccherini	fReaderThread(-1),
8363dc9cc2SStefano Ceccherini	fReaderSem(-1),
8463dc9cc2SStefano Ceccherini	fReaderLocker(-1),
85066dcdc3SIngo Weinhold	fBufferPosition(0),
86066dcdc3SIngo Weinhold	fReadBufferSize(0),
87540e66d6SIngo Weinhold	fParserBufferSize(0),
88540e66d6SIngo Weinhold	fParserBufferOffset(0),
894386ce02SIngo Weinhold	fBuffer(NULL),
90abc47202SStefano Ceccherini	fQuitting(true)
9163dc9cc2SStefano Ceccherini{
92a2f89c58SSiarzhuk Zharski	memset(fReadBuffer, 0, READ_BUF_SIZE);
93a2f89c58SSiarzhuk Zharski	memset(fParserBuffer, 0, ESC_PARSER_BUFFER_SIZE);
9463dc9cc2SStefano Ceccherini}
9563dc9cc2SStefano Ceccherini
9663dc9cc2SStefano Ceccherini
9763dc9cc2SStefano CeccheriniTermParse::~TermParse()
9863dc9cc2SStefano Ceccherini{
99ac3a8f54SStefano Ceccherini	StopThreads();
10063dc9cc2SStefano Ceccherini}
10163dc9cc2SStefano Ceccherini
10263dc9cc2SStefano Ceccherini
10363dc9cc2SStefano Ceccherinistatus_t
1044386ce02SIngo WeinholdTermParse::StartThreads(TerminalBuffer *buffer)
10563dc9cc2SStefano Ceccherini{
1064386ce02SIngo Weinhold	if (fBuffer != NULL)
107abc47202SStefano Ceccherini		return B_ERROR;
108abc47202SStefano Ceccherini
109abc47202SStefano Ceccherini	fQuitting = false;
1104386ce02SIngo Weinhold	fBuffer = buffer;
1116c514d3eSMatt Madia
11274d2e159SStefano Ceccherini	status_t status = _InitPtyReader();
113abc47202SStefano Ceccherini	if (status < B_OK) {
11421543141SAxel Dörfler		fBuffer = NULL;
11563dc9cc2SStefano Ceccherini		return status;
116abc47202SStefano Ceccherini	}
11763dc9cc2SStefano Ceccherini
11874d2e159SStefano Ceccherini	status = _InitTermParse();
11963dc9cc2SStefano Ceccherini	if (status < B_OK) {
12071ddd07bSStefano Ceccherini		_StopPtyReader();
1214386ce02SIngo Weinhold		fBuffer = NULL;
12221543141SAxel Dörfler		return status;
12363dc9cc2SStefano Ceccherini	}
12421543141SAxel Dörfler
12563dc9cc2SStefano Ceccherini	return B_OK;
12663dc9cc2SStefano Ceccherini}
12763dc9cc2SStefano Ceccherini
1289105df34Sshatty
129ac3a8f54SStefano Ceccherinistatus_t
130ac3a8f54SStefano CeccheriniTermParse::StopThreads()
131ac3a8f54SStefano Ceccherini{
1324386ce02SIngo Weinhold	if (fBuffer == NULL)
133abc47202SStefano Ceccherini		return B_ERROR;
134abc47202SStefano Ceccherini
135ac3a8f54SStefano Ceccherini	fQuitting = true;
136ac3a8f54SStefano Ceccherini
13774d2e159SStefano Ceccherini	_StopPtyReader();
13874d2e159SStefano Ceccherini	_StopTermParse();
13921543141SAxel Dörfler
1404386ce02SIngo Weinhold	fBuffer = NULL;
14121543141SAxel Dörfler
142ac3a8f54SStefano Ceccherini	return B_OK;
143ac3a8f54SStefano Ceccherini}
144ac3a8f54SStefano Ceccherini
145ac3a8f54SStefano Ceccherini
1467f108511SAxel Dörfler//! Initialize and spawn EscParse thread.
1479105df34Sshattystatus_t
14874d2e159SStefano CeccheriniTermParse::_InitTermParse()
1499105df34Sshatty{
15063dc9cc2SStefano Ceccherini	if (fParseThread >= 0)
15163dc9cc2SStefano Ceccherini		return B_ERROR; // we might want to return B_OK instead ?
15263dc9cc2SStefano Ceccherini
1537f108511SAxel Dörfler	fParseThread = spawn_thread(_escparse_thread, "EscParse",
1547f108511SAxel Dörfler		B_DISPLAY_PRIORITY, this);
1557f108511SAxel Dörfler
15674d2e159SStefano Ceccherini	if (fParseThread < 0)
15774d2e159SStefano Ceccherini		return fParseThread;
1586c514d3eSMatt Madia
159d7b25be8SStefano Ceccherini	resume_thread(fParseThread);
16021543141SAxel Dörfler
161d7b25be8SStefano Ceccherini	return B_OK;
16263dc9cc2SStefano Ceccherini}
1639105df34Sshatty
1649105df34Sshatty
1657f108511SAxel Dörfler//! Initialize and spawn PtyReader thread.
166d7b25be8SStefano Ceccherinistatus_t
16774d2e159SStefano CeccheriniTermParse::_InitPtyReader()
1689105df34Sshatty{
16963dc9cc2SStefano Ceccherini	if (fReaderThread >= 0)
17063dc9cc2SStefano Ceccherini		return B_ERROR; // same as above
1719105df34Sshatty
17263dc9cc2SStefano Ceccherini	fReaderSem = create_sem(0, "pty_reader_sem");
17363dc9cc2SStefano Ceccherini	if (fReaderSem < 0)
17463dc9cc2SStefano Ceccherini		return fReaderSem;
1759105df34Sshatty
17663dc9cc2SStefano Ceccherini	fReaderLocker = create_sem(0, "pty_locker_sem");
17763dc9cc2SStefano Ceccherini	if (fReaderLocker < 0) {
17863dc9cc2SStefano Ceccherini		delete_sem(fReaderSem);
179d7b25be8SStefano Ceccherini		fReaderSem = -1;
18021543141SAxel Dörfler		return fReaderLocker;
18163dc9cc2SStefano Ceccherini	}
1829105df34Sshatty
1837f108511SAxel Dörfler	fReaderThread = spawn_thread(_ptyreader_thread, "PtyReader",
1847f108511SAxel Dörfler		B_NORMAL_PRIORITY, this);
1855b41331fSSiarzhuk Zharski	if (fReaderThread < 0) {
18663dc9cc2SStefano Ceccherini		delete_sem(fReaderSem);
187d7b25be8SStefano Ceccherini		fReaderSem = -1;
18863dc9cc2SStefano Ceccherini		delete_sem(fReaderLocker);
189d7b25be8SStefano Ceccherini		fReaderLocker = -1;
19021543141SAxel Dörfler		return fReaderThread;
19121543141SAxel Dörfler	}
1927f108511SAxel Dörfler
193d7b25be8SStefano Ceccherini	resume_thread(fReaderThread);
194d7b25be8SStefano Ceccherini
195d7b25be8SStefano Ceccherini	return B_OK;
196d7b25be8SStefano Ceccherini}
197d7b25be8SStefano Ceccherini
198d7b25be8SStefano Ceccherini
199d7b25be8SStefano Ceccherinivoid
20074d2e159SStefano CeccheriniTermParse::_StopTermParse()
201d7b25be8SStefano Ceccherini{
202d7b25be8SStefano Ceccherini	if (fParseThread >= 0) {
203d7b25be8SStefano Ceccherini		status_t dummy;
204d7b25be8SStefano Ceccherini		wait_for_thread(fParseThread, &dummy);
20521543141SAxel Dörfler		fParseThread = -1;
206d7b25be8SStefano Ceccherini	}
207d7b25be8SStefano Ceccherini}
208d7b25be8SStefano Ceccherini
209d7b25be8SStefano Ceccherini
210d7b25be8SStefano Ceccherinivoid
21174d2e159SStefano CeccheriniTermParse::_StopPtyReader()
212d7b25be8SStefano Ceccherini{
213d7b25be8SStefano Ceccherini	if (fReaderSem >= 0) {
214d7b25be8SStefano Ceccherini		delete_sem(fReaderSem);
215d7b25be8SStefano Ceccherini		fReaderSem = -1;
216d7b25be8SStefano Ceccherini	}
21721543141SAxel Dörfler	if (fReaderLocker >= 0) {
218d7b25be8SStefano Ceccherini		delete_sem(fReaderLocker);
219d7b25be8SStefano Ceccherini		fReaderLocker = -1;
220d7b25be8SStefano Ceccherini	}
221d7b25be8SStefano Ceccherini
222d7b25be8SStefano Ceccherini	if (fReaderThread >= 0) {
223871d97a9SAxel Dörfler		suspend_thread(fReaderThread);
224871d97a9SAxel Dörfler
225871d97a9SAxel Dörfler		status_t status;
226871d97a9SAxel Dörfler		wait_for_thread(fReaderThread, &status);
227871d97a9SAxel Dörfler
22821543141SAxel Dörfler		fReaderThread = -1;
229d7b25be8SStefano Ceccherini	}
230d7b25be8SStefano Ceccherini}
231d7b25be8SStefano Ceccherini
232d7b25be8SStefano Ceccherini
233d7b25be8SStefano Ceccherini//! Get data from pty device.
234d7b25be8SStefano Ceccheriniint32
235d7b25be8SStefano CeccheriniTermParse::PtyReader()
236d7b25be8SStefano Ceccherini{
237066dcdc3SIngo Weinhold	int32 bufferSize = 0;
238066dcdc3SIngo Weinhold	int32 readPos = 0;
239d7b25be8SStefano Ceccherini	while (!fQuitting) {
240d7b25be8SStefano Ceccherini		// If Pty Buffer nearly full, snooze this thread, and continue.
241066dcdc3SIngo Weinhold		while (READ_BUF_SIZE - bufferSize < MIN_PTY_BUFFER_SPACE) {
242d7b25be8SStefano Ceccherini			status_t status;
24321543141SAxel Dörfler			do {
244d7b25be8SStefano Ceccherini				status = acquire_sem(fReaderLocker);
245d7b25be8SStefano Ceccherini			} while (status == B_INTERRUPTED);
246d7b25be8SStefano Ceccherini			if (status < B_OK)
24721543141SAxel Dörfler				return status;
248066dcdc3SIngo Weinhold
249066dcdc3SIngo Weinhold			bufferSize = fReadBufferSize;
250d7b25be8SStefano Ceccherini		}
251d7b25be8SStefano Ceccherini
252d7b25be8SStefano Ceccherini		// Read PTY
253d7b25be8SStefano Ceccherini		uchar buf[READ_BUF_SIZE];
254066dcdc3SIngo Weinhold		ssize_t nread = read(fFd, buf, READ_BUF_SIZE - bufferSize);
255d7b25be8SStefano Ceccherini		if (nread <= 0) {
2564386ce02SIngo Weinhold			fBuffer->NotifyQuit(errno);
25769f6c88dSAxel Dörfler			return B_OK;
258d7b25be8SStefano Ceccherini		}
259d7b25be8SStefano Ceccherini
260d7b25be8SStefano Ceccherini		// Copy read string to PtyBuffer.
261d7b25be8SStefano Ceccherini
262066dcdc3SIngo Weinhold		int32 left = READ_BUF_SIZE - readPos;
263d7b25be8SStefano Ceccherini
264d7b25be8SStefano Ceccherini		if (nread >= left) {
265066dcdc3SIngo Weinhold			memcpy(fReadBuffer + readPos, buf, left);
266d7b25be8SStefano Ceccherini			memcpy(fReadBuffer, buf + left, nread - left);
267d7b25be8SStefano Ceccherini		} else
268066dcdc3SIngo Weinhold			memcpy(fReadBuffer + readPos, buf, nread);
269d7b25be8SStefano Ceccherini
270066dcdc3SIngo Weinhold		bufferSize = atomic_add(&fReadBufferSize, nread);
2718d5e9931SMichael Lotz		if (bufferSize == 0)
272066dcdc3SIngo Weinhold			release_sem(fReaderSem);
273d7b25be8SStefano Ceccherini
274066dcdc3SIngo Weinhold		bufferSize += nread;
275066dcdc3SIngo Weinhold		readPos = (readPos + nread) % READ_BUF_SIZE;
276d7b25be8SStefano Ceccherini	}
277d7b25be8SStefano Ceccherini
278d7b25be8SStefano Ceccherini	return B_OK;
2799105df34Sshatty}
2809105df34Sshatty
2818eb8269dSAxel Dörfler
2823082bb7dSFrançois Revolvoid
2833082bb7dSFrançois RevolTermParse::DumpState(int *groundtable, int *parsestate, uchar c)
2843082bb7dSFrançois Revol{
2853082bb7dSFrançois Revol	static const struct {
2863082bb7dSFrançois Revol		int *p;
2873082bb7dSFrançois Revol		const char *name;
2883082bb7dSFrançois Revol	} tables[] = {
2893082bb7dSFrançois Revol#define T(t) \
2903082bb7dSFrançois Revol	{ t, #t }
29162a8fd3bSAxel Dörfler		T(gUTF8GroundTable),
29262a8fd3bSAxel Dörfler		T(gISO8859GroundTable),
293f3782185SSiarzhuk Zharski		T(gWinCPGroundTable),
29462a8fd3bSAxel Dörfler		T(gSJISGroundTable),
29562a8fd3bSAxel Dörfler		T(gEscTable),
29662a8fd3bSAxel Dörfler		T(gCsiTable),
29762a8fd3bSAxel Dörfler		T(gDecTable),
29862a8fd3bSAxel Dörfler		T(gScrTable),
29962a8fd3bSAxel Dörfler		T(gIgnoreTable),
30062a8fd3bSAxel Dörfler		T(gIesTable),
30162a8fd3bSAxel Dörfler		T(gEscIgnoreTable),
30262a8fd3bSAxel Dörfler		{ NULL, NULL }
3033082bb7dSFrançois Revol	};
3043082bb7dSFrançois Revol	int i;
30562a8fd3bSAxel Dörfler	fprintf(stderr, "groundtable: ");
30674d2e159SStefano Ceccherini	for (i = 0; tables[i].p; i++) {
3073082bb7dSFrançois Revol		if (tables[i].p == groundtable)
3083082bb7dSFrançois Revol			fprintf(stderr, "%s\t", tables[i].name);
30974d2e159SStefano Ceccherini	}
31062a8fd3bSAxel Dörfler	fprintf(stderr, "parsestate: ");
31174d2e159SStefano Ceccherini	for (i = 0; tables[i].p; i++) {
3123082bb7dSFrançois Revol		if (tables[i].p == parsestate)
3133082bb7dSFrançois Revol			fprintf(stderr, "%s\t", tables[i].name);
31474d2e159SStefano Ceccherini	}
31562a8fd3bSAxel Dörfler	fprintf(stderr, "char: 0x%02x (%d)\n", c, c);
3163082bb7dSFrançois Revol}
3173082bb7dSFrançois Revol
3183082bb7dSFrançois Revol
319f3782185SSiarzhuk Zharskiint *
320f3782185SSiarzhuk ZharskiTermParse::_GuessGroundTable(int encoding)
321f3782185SSiarzhuk Zharski{
322f3782185SSiarzhuk Zharski	switch (encoding) {
323f3782185SSiarzhuk Zharski		case B_ISO1_CONVERSION:
324f3782185SSiarzhuk Zharski		case B_ISO2_CONVERSION:
325f3782185SSiarzhuk Zharski		case B_ISO3_CONVERSION:
326f3782185SSiarzhuk Zharski		case B_ISO4_CONVERSION:
327f3782185SSiarzhuk Zharski		case B_ISO5_CONVERSION:
328f3782185SSiarzhuk Zharski		case B_ISO6_CONVERSION:
329f3782185SSiarzhuk Zharski		case B_ISO7_CONVERSION:
330f3782185SSiarzhuk Zharski		case B_ISO8_CONVERSION:
331f3782185SSiarzhuk Zharski		case B_ISO9_CONVERSION:
332f3782185SSiarzhuk Zharski		case B_ISO10_CONVERSION:
333f3782185SSiarzhuk Zharski		case B_ISO13_CONVERSION:
334f3782185SSiarzhuk Zharski		case B_ISO14_CONVERSION:
335f3782185SSiarzhuk Zharski		case B_ISO15_CONVERSION:
336f3782185SSiarzhuk Zharski		case B_EUC_CONVERSION:
337f3782185SSiarzhuk Zharski		case B_EUC_KR_CONVERSION:
338f3782185SSiarzhuk Zharski		case B_JIS_CONVERSION:
339f3782185SSiarzhuk Zharski		case B_BIG5_CONVERSION:
340f3782185SSiarzhuk Zharski			return gISO8859GroundTable;
341f3782185SSiarzhuk Zharski
342f3782185SSiarzhuk Zharski		case B_KOI8R_CONVERSION:
343f3782185SSiarzhuk Zharski		case B_MS_WINDOWS_1251_CONVERSION:
344f3782185SSiarzhuk Zharski		case B_MS_WINDOWS_CONVERSION:
345f3782185SSiarzhuk Zharski		case B_MAC_ROMAN_CONVERSION:
346f3782185SSiarzhuk Zharski		case B_MS_DOS_866_CONVERSION:
347bf88d81eSSiarzhuk Zharski		case B_GBK_CONVERSION:
348f3782185SSiarzhuk Zharski		case B_MS_DOS_CONVERSION:
349f3782185SSiarzhuk Zharski			return gWinCPGroundTable;
350f3782185SSiarzhuk Zharski
351f3782185SSiarzhuk Zharski		case B_SJIS_CONVERSION:
352f3782185SSiarzhuk Zharski			return gSJISGroundTable;
353f3782185SSiarzhuk Zharski
354f3782185SSiarzhuk Zharski		case M_UTF8:
355f3782185SSiarzhuk Zharski		default:
356f3782185SSiarzhuk Zharski			break;
357f3782185SSiarzhuk Zharski	}
358f3782185SSiarzhuk Zharski
359f3782185SSiarzhuk Zharski	return gUTF8GroundTable;
360f3782185SSiarzhuk Zharski}
361f3782185SSiarzhuk Zharski
362f3782185SSiarzhuk Zharski
3639105df34Sshattyint32
36463dc9cc2SStefano CeccheriniTermParse::EscParse()
3659105df34Sshatty{
366b2a3f5b1SAdrien Destugues	int top = 0;
367b2a3f5b1SAdrien Destugues	int bottom = 0;
36821543141SAxel Dörfler
369f3782185SSiarzhuk Zharski	char cbuf[4] = { 0 };
370f3782185SSiarzhuk Zharski	char dstbuf[4] = { 0 };
3719105df34Sshatty
37274d2e159SStefano Ceccherini	int currentEncoding = -1;
3739105df34Sshatty
3748eb8269dSAxel Dörfler	int param[NPARAM];
3758eb8269dSAxel Dörfler	int nparam = 1;
376b2a3f5b1SAdrien Destugues	for (int i = 0; i < NPARAM; i++)
377b2a3f5b1SAdrien Destugues		param[i] = DEFAULT;
3789105df34Sshatty
379b2a3f5b1SAdrien Destugues	int row = 0;
380b2a3f5b1SAdrien Destugues	int column = 0;
3819105df34Sshatty
382e0fcd629SSiarzhuk Zharski	// default encoding system is UTF8
38387f17bdfSStefano Ceccherini	int *groundtable = gUTF8GroundTable;
38474d2e159SStefano Ceccherini	int *parsestate = gUTF8GroundTable;
3858eb8269dSAxel Dörfler
386e0fcd629SSiarzhuk Zharski	// handle alternative character sets G0 - G4
387daebca78SSiarzhuk Zharski	const char** graphSets[4] = { NULL, NULL, NULL, NULL };
388daebca78SSiarzhuk Zharski	int curGL = 0;
389daebca78SSiarzhuk Zharski	int curGR = 0;
3903eedbbbfSAdrien Destugues
391540e66d6SIngo Weinhold	BAutolock locker(fBuffer);
39252b1d543SIngo Weinhold
393540e66d6SIngo Weinhold	while (!fQuitting) {
39474d2e159SStefano Ceccherini		try {
39574d2e159SStefano Ceccherini			uchar c = _NextParseChar();
39674d2e159SStefano Ceccherini
39774d2e159SStefano Ceccherini			//DumpState(groundtable, parsestate, c);
39874d2e159SStefano Ceccherini
39974d2e159SStefano Ceccherini			if (currentEncoding != fBuffer->Encoding()) {
40062a8fd3bSAxel Dörfler				// Change coding, change parse table.
401f3782185SSiarzhuk Zharski				groundtable = _GuessGroundTable(fBuffer->Encoding());
40274d2e159SStefano Ceccherini				parsestate = groundtable;
40374d2e159SStefano Ceccherini				currentEncoding = fBuffer->Encoding();
4048eb8269dSAxel Dörfler			}
4058eb8269dSAxel Dörfler
40674d2e159SStefano Ceccherini	//debug_printf("TermParse: char: '%c' (%d), parse state: %d\n", c, c, parsestate[c]);
407bf88d81eSSiarzhuk Zharski			int32 srcLen = 0;
408bf88d81eSSiarzhuk Zharski			int32 dstLen = sizeof(dstbuf);
409bf88d81eSSiarzhuk Zharski			int32 dummyState = 0;
410718a28ceSSiarzhuk Zharski
41174d2e159SStefano Ceccherini			switch (parsestate[c]) {
41274d2e159SStefano Ceccherini				case CASE_PRINT:
413daebca78SSiarzhuk Zharski				{
414daebca78SSiarzhuk Zharski					int curGS = c < 128 ? curGL : curGR;
415daebca78SSiarzhuk Zharski					const char** curGraphSet = graphSets[curGS];
416daebca78SSiarzhuk Zharski					if (curGraphSet != NULL) {
417daebca78SSiarzhuk Zharski						int offset = c - (c < 128 ? 0x20 : 0xA0);
418daebca78SSiarzhuk Zharski						if (offset >= 0 && offset < 96
419e0fcd629SSiarzhuk Zharski							&& curGraphSet[offset] != 0) {
420daebca78SSiarzhuk Zharski							fBuffer->InsertChar(curGraphSet[offset]);
421daebca78SSiarzhuk Zharski							break;
422daebca78SSiarzhuk Zharski						}
423daebca78SSiarzhuk Zharski					}
424e0fcd629SSiarzhuk Zharski					fBuffer->InsertChar((char)c);
42574d2e159SStefano Ceccherini					break;
426daebca78SSiarzhuk Zharski				}
42774d2e159SStefano Ceccherini				case CASE_PRINT_GR:
428bf88d81eSSiarzhuk Zharski				{
42974d2e159SStefano Ceccherini					/* case iso8859 gr character, or euc */
430bf88d81eSSiarzhuk Zharski					switch (currentEncoding) {
431bf88d81eSSiarzhuk Zharski						case B_EUC_CONVERSION:
432bf88d81eSSiarzhuk Zharski						case B_EUC_KR_CONVERSION:
433bf88d81eSSiarzhuk Zharski						case B_JIS_CONVERSION:
434bf88d81eSSiarzhuk Zharski						case B_BIG5_CONVERSION:
435bf88d81eSSiarzhuk Zharski							cbuf[srcLen++] = c;
436bf88d81eSSiarzhuk Zharski							c = _NextParseChar();
437bf88d81eSSiarzhuk Zharski							cbuf[srcLen++] = c;
438bf88d81eSSiarzhuk Zharski							break;
4398eb8269dSAxel Dörfler
440bf88d81eSSiarzhuk Zharski						case B_GBK_CONVERSION:
441bf88d81eSSiarzhuk Zharski							cbuf[srcLen++] = c;
442bf88d81eSSiarzhuk Zharski							do {
443bf88d81eSSiarzhuk Zharski								// GBK-compatible codepoints are 2-bytes long
44474d2e159SStefano Ceccherini								c = _NextParseChar();
445bf88d81eSSiarzhuk Zharski								cbuf[srcLen++] = c;
4468eb8269dSAxel Dörfler
447bf88d81eSSiarzhuk Zharski								// GB18030 extends GBK with 4-byte codepoints
448bf88d81eSSiarzhuk Zharski								// using 2nd byte from range 0x30...0x39
449bf88d81eSSiarzhuk Zharski								if (srcLen == 2 && (c < 0x30 || c > 0x39))
450bf88d81eSSiarzhuk Zharski									break;
451bf88d81eSSiarzhuk Zharski							} while (srcLen < 4);
452bf88d81eSSiarzhuk Zharski							break;
4538eb8269dSAxel Dörfler
454bf88d81eSSiarzhuk Zharski						default: // ISO-8859-1...10 and MacRoman
455bf88d81eSSiarzhuk Zharski							cbuf[srcLen++] = c;
456bf88d81eSSiarzhuk Zharski							break;
45774d2e159SStefano Ceccherini					}
4588eb8269dSAxel Dörfler
459bf88d81eSSiarzhuk Zharski					if (srcLen > 0) {
460bf88d81eSSiarzhuk Zharski						int encoding = currentEncoding == B_JIS_CONVERSION
461bf88d81eSSiarzhuk Zharski							? B_EUC_CONVERSION : currentEncoding;
4628eb8269dSAxel Dörfler
463bf88d81eSSiarzhuk Zharski						convert_to_utf8(encoding, cbuf, &srcLen,
464bf88d81eSSiarzhuk Zharski								dstbuf, &dstLen, &dummyState, '?');
465bf88d81eSSiarzhuk Zharski
466bf88d81eSSiarzhuk Zharski						fBuffer->InsertChar(UTF8Char(dstbuf, dstLen));
467bf88d81eSSiarzhuk Zharski					}
46874d2e159SStefano Ceccherini					break;
469bf88d81eSSiarzhuk Zharski				}
4708eb8269dSAxel Dörfler
47174d2e159SStefano Ceccherini				case CASE_LF:
47274d2e159SStefano Ceccherini					fBuffer->InsertLF();
47374d2e159SStefano Ceccherini					break;
4748eb8269dSAxel Dörfler
47574d2e159SStefano Ceccherini				case CASE_CR:
476b512213bSSiarzhuk Zharski					fBuffer->InsertCR();
47774d2e159SStefano Ceccherini					break;
4788eb8269dSAxel Dörfler
47962eadc5eSJérôme Duval				case CASE_INDEX:
48062eadc5eSJérôme Duval					fBuffer->InsertLF();
48162eadc5eSJérôme Duval					parsestate = groundtable;
48262eadc5eSJérôme Duval					break;
48362eadc5eSJérôme Duval
48462eadc5eSJérôme Duval				case CASE_NEXT_LINE:
48562eadc5eSJérôme Duval					fBuffer->NextLine();
48662eadc5eSJérôme Duval					parsestate = groundtable;
48762eadc5eSJérôme Duval					break;
48862eadc5eSJérôme Duval
48974d2e159SStefano Ceccherini				case CASE_SJIS_KANA:
490bf88d81eSSiarzhuk Zharski					cbuf[srcLen++] = c;
49174d2e159SStefano Ceccherini					convert_to_utf8(currentEncoding, cbuf, &srcLen,
492dbf7fa87SAdrien Destugues							dstbuf, &dstLen, &dummyState, '?');
4933d149248SSiarzhuk Zharski					fBuffer->InsertChar(UTF8Char(dstbuf, dstLen));
49474d2e159SStefano Ceccherini					break;
4958eb8269dSAxel Dörfler
49674d2e159SStefano Ceccherini				case CASE_SJIS_INSTRING:
497bf88d81eSSiarzhuk Zharski					cbuf[srcLen++] = c;
49874d2e159SStefano Ceccherini					c = _NextParseChar();
499bf88d81eSSiarzhuk Zharski					cbuf[srcLen++] = c;
500bf88d81eSSiarzhuk Zharski
50174d2e159SStefano Ceccherini					convert_to_utf8(currentEncoding, cbuf, &srcLen,
502dbf7fa87SAdrien Destugues							dstbuf, &dstLen, &dummyState, '?');
5033d149248SSiarzhuk Zharski					fBuffer->InsertChar(UTF8Char(dstbuf, dstLen));
50474d2e159SStefano Ceccherini					break;
5058eb8269dSAxel Dörfler
50674d2e159SStefano Ceccherini				case CASE_UTF8_2BYTE:
507bf88d81eSSiarzhuk Zharski					cbuf[srcLen++] = c;
50874d2e159SStefano Ceccherini					c = _NextParseChar();
50974d2e159SStefano Ceccherini					if (groundtable[c] != CASE_UTF8_INSTRING)
5108eb8269dSAxel Dörfler						break;
511bf88d81eSSiarzhuk Zharski					cbuf[srcLen++] = c;
5128eb8269dSAxel Dörfler
513bf88d81eSSiarzhuk Zharski					fBuffer->InsertChar(UTF8Char(cbuf, srcLen));
51474d2e159SStefano Ceccherini					break;
5158eb8269dSAxel Dörfler
51674d2e159SStefano Ceccherini				case CASE_UTF8_3BYTE:
517bf88d81eSSiarzhuk Zharski					cbuf[srcLen++] = c;
518ae29b1c3SRene Gollent
519bf88d81eSSiarzhuk Zharski					do {
520bf88d81eSSiarzhuk Zharski						c = _NextParseChar();
521bf88d81eSSiarzhuk Zharski						if (groundtable[c] != CASE_UTF8_INSTRING) {
522