Esempio n. 1
0
void UMcf::parseUpdateXml(const XML::gcXMLDocument &xmlDocument)
{
    auto uNode = xmlDocument.GetRoot("appupdate");

    if (!uNode.IsValid())
        return;

    auto mcfNode = uNode.FirstChildElement("mcf");

    if (!mcfNode.IsValid())
        return;


    const std::string appid = mcfNode.GetAtt("appid");

    if (!appid.empty())
        m_iAppId = Safe::atoi(appid.c_str());
    else
        m_iAppId = 100;

    const std::string build = mcfNode.GetAtt("build");

    if (!build.empty())
        m_iAppBuild = Safe::atoi(build.c_str());
    else
        m_iAppBuild = 0;

    mcfNode.GetChild("url", m_szUrl);
    parseXml(mcfNode.FirstChildElement("files"));
}
Esempio n. 2
0
std::vector<std::map<gcString, gcString>> GetLanguages()
{
	std::vector<std::map<gcString, gcString>> ret;

	std::vector<UTIL::FS::Path> fileList;
	std::vector<std::string> filter;
	filter.push_back("xml");

	UTIL::FS::getAllFiles(UTIL::FS::Path(UTIL::OS::getDataPath(L"language"),
		L"", false), fileList, &filter);
	
	std::map<gcString, uint32> mSeenBefore;

	for (size_t x=0; x<fileList.size(); x++)
	{
		XML::gcXMLDocument doc(fileList[x].getFullPath().c_str());
				
		auto uNode = doc.GetRoot("lang");

		if (!uNode.IsValid())
			continue;

		gcString name = uNode.GetAtt("name");
		gcString skip = uNode.GetAtt("skip");

		if (name.size() == 0)
			continue;

		if (skip == "true")
			continue;

		gcString file(fileList[x].getFile().getFile());
		size_t pos = file.find_last_of(".");

		if (pos != std::string::npos)
			file[pos] = '\0';

		if (mSeenBefore[name])
			name += gcString("({0})", mSeenBefore[name]);

		mSeenBefore[name]++;

		std::map<gcString, gcString> map;

		map["file"] = file;
		map["name"] = name;
	
		ret.push_back(map);
	}

	return ret;
}
Esempio n. 3
0
// draw a box, with an optional shadow & connectors
void _box(int top, int left, int bottom, int right, int style, int attribute, int fill, int box_flags, int connector)
{
	int width;
	int v_zoom_top, v_zoom_bottom, h_zoom_left, h_zoom_right;
	int row_diff, col_diff, row_inc, col_inc, fWait = 0;

	// zoom the window?
	if (box_flags & BOX_ZOOMED) {

		fWait = 1;

		// zooming requires a fill color; use default if none specified
		if (fill == -1)
			GetAtt((unsigned int *)&fill,(unsigned int *)&v_zoom_top);

		v_zoom_top = v_zoom_bottom = (top + bottom) / 2;
		h_zoom_left = h_zoom_right = (left + right) / 2;

		// get the increment for each zoom
		// (This makes the zoom smooth in all dimensions)
		if ((row_diff = v_zoom_top - top) <= 0)
			row_diff = 1;
		if ((col_diff = h_zoom_left - left) <= 0)
			col_diff = 1;

		if (row_diff > col_diff) {
			// tall skinny box
			row_inc = (row_diff / col_diff);
			col_inc = 1;
		} else {
			// short wide box
			col_inc = (col_diff / row_diff);
			row_inc = 1;
		}

	} else {

		v_zoom_top = top;
		v_zoom_bottom = bottom;
		h_zoom_left = left;
		h_zoom_right = right;
	}

	do {

		if (box_flags & BOX_ZOOMED) {

			// if zooming, increment the box size
			v_zoom_top -= row_inc;
			if (v_zoom_top < top)
				v_zoom_top = top;

			v_zoom_bottom += row_inc;
			if (v_zoom_bottom > bottom)
				v_zoom_bottom = bottom;

			h_zoom_left -= col_inc;
			if (h_zoom_left < left)
				h_zoom_left = left;

			h_zoom_right += col_inc;
			if (h_zoom_right > right)
				h_zoom_right = right;
		}

		// clear the box to the specified attribute
		if (fill != -1)
			Scroll(v_zoom_top,h_zoom_left,v_zoom_bottom,h_zoom_right,0,fill);

		if (style == 0)
			width = 0;
		else if ((style == 2) || (style == 4))
			width = 2;
		else
			width = 1;

		// draw the two horizontals & the two verticals
		_line(v_zoom_top,h_zoom_left,(h_zoom_right-h_zoom_left)+1,width,0,attribute,connector);
		_line(v_zoom_bottom,h_zoom_left,(h_zoom_right-h_zoom_left)+1,width,0,attribute,connector);

		if (style == 3)
			width = 2;
		else if (style == 4)
			width = 1;

		_line(v_zoom_top,h_zoom_left,(v_zoom_bottom-v_zoom_top)+1,width,1,attribute,connector);
		_line(v_zoom_top,h_zoom_right,(v_zoom_bottom-v_zoom_top)+1,width,1,attribute,connector);

		// if on a fast system, slow things down a bit
		if (fWait)
			SysBeep(0,1);

	} while ((box_flags & BOX_ZOOMED) && ((v_zoom_top > top) || (v_zoom_bottom < bottom) || (h_zoom_left > left) || (h_zoom_right < right)));

	// check for a shadow
	if (box_flags & BOX_SHADOWED) {

		left += 2;
		right++;
		if ( left >= right )
			left = right - 1;

		// read the character and attribute, and change
		//   the attribute to black background, low intensity
		//   foreground
		SetLineColor(++bottom,left,(right-left),7);

		// shadow the right side of the window
		for (top++; (top <= bottom); top++)
			SetLineColor(top,right,2,7);
	}
}
//this is a feature of webcore but we need it here in case we need to shutdown during a download
void DownloadUpdateTask::downloadUpdate()
{
#ifdef DEBUG
	return;
#endif

	uint32 appver = m_uiAppVer;
	uint32 appbuild = m_uiAppBuild;


	HttpHandle wc(PRIMUPDATE);
	getWebCore()->setWCCookies(wc);
	
	wc->addPostText("appid", appver);
	wc->postWeb();


	if (wc->getDataSize() == 0)
		throw gcException(ERR_INVALIDDATA);


	XML::gcXMLDocument doc(const_cast<char*>(wc->getData()), wc->getDataSize());
	doc.ProcessStatus("appupdate");

	auto mNode = doc.GetRoot("appupdate").FirstChildElement("mcf");

	if (!mNode.IsValid())
		throw gcException(ERR_BADXML);

	uint32 version = 0;
	uint32 build = 0;
	
	mNode.GetAtt("appid", version);
	mNode.GetAtt("build", build);

	if (version == 0 || build == 0)
		throw gcException(ERR_BADXML);

	//check to see if its newer than last
	if (appbuild != 0 && build <= appbuild && appver == version)
		return;

	gcString url = mNode.GetChild("url");

	if (url.size() == 0)
		throw gcException(ERR_BADXML);

#ifdef WIN32
	const char *comAppPath = getUserCore()->getAppDataPath();
	m_szPath = gcString("{0}{1}{2}", comAppPath, DIRS_STR, UPDATEFILE);
#else
	m_szPath = gcString("{0}", UPDATEFILE);
#endif

	m_hMcfHandle->setFile(m_szPath.c_str());
	m_hMcfHandle->setWorkerCount(1);
	
	try
	{
		m_hMcfHandle->dlHeaderFromHttp(url.c_str());

#ifdef WIN32
		const char* dir = ".\\";
#else
		const char* dir = "./";
#endif

		//Dont use courgette for non admins for now
		bool useCourgette = false;

#ifdef WIN32
		if (getUserCore()->isAdmin())
			useCourgette = true;
#endif

		bool res = m_hMcfHandle->verifyInstall(dir, true, useCourgette);

		m_hMcfHandle->getProgEvent() += delegate(this, &DownloadUpdateTask::onDownloadProgress);

		UserCore::Misc::update_s info;
		info.build = build;

		if (!res)
		{
			Msg(gcString("Downloading " PRODUCT_NAME " update: Ver {0} build {1}\n", appver, build));
			info.alert = true;

			onDownloadStartEvent(info);

			if (useCourgette)
				m_hMcfHandle->dlFilesFromHttp(url.c_str(), dir);
			else
				m_hMcfHandle->dlFilesFromHttp(url.c_str());

			if (!isStopped())
				onDownloadCompleteEvent(info);
		}
		else
		{
			//sometimes this gets called after shutdown and causes major problems
			if (!getUserCore() || !getUserCore()->getServiceMain())
				return;

			gcString av("{0}", appver);
			gcString ab("{0}", build);
			info.alert = false;

			try
			{
				getUserCore()->getServiceMain()->updateRegKey(APPID, av.c_str());
				getUserCore()->getServiceMain()->updateRegKey(APPBUILD, ab.c_str());
			}
			catch (gcException &e)
			{
				Warning(gcString("Failed to update reg key: {0}\n", e));
			}

			onDownloadCompleteEvent(info);
		}
	}
	catch (gcException &e)
	{
		Warning(gcString("Download update failed: {0}\n", e));
	}
}
Esempio n. 5
0
// draw a box, with an optional shadow & connectors
void PASCAL _box( register int nTop, int nLeft, int nBottom, int nRight, int nStyle, int nAttribute, int nFill, int nFlags, int nConnector )
{
	register int nWidth;
	int nZoomTop, nZoomBottom, nZoomLeft, nZoomRight;
	int nRowDiff, nColumnDiff, nRowInc = 0, nColumnInc = 0;

	// zoom the window?
	if ( nFlags & BOX_ZOOMED ) {

		// zooming requires a fill color; use default if none specified
		if ( nFill == -1 )
			GetAtt( (unsigned int *)&nFill, (unsigned int *)&nZoomTop );

		nZoomTop = nZoomBottom = ( nTop + nBottom ) / 2;
		nZoomLeft = nZoomRight = ( nLeft + nRight ) / 2;

		// get the increment for each zoom
		// (This makes the zoom smooth in all dimensions)
		if (( nRowDiff = nZoomTop - nTop ) <= 0 )
			nRowDiff = 1;
		if (( nColumnDiff = nZoomLeft - nLeft ) <= 0 )
			nColumnDiff = 1;

		if ( nRowDiff > nColumnDiff ) {
			// tall skinny box
			nRowInc = ( nRowDiff / nColumnDiff );
			nColumnInc = 1;
		} else {
			// short wide box
			nColumnInc = ( nColumnDiff / nRowDiff );
			nRowInc = 1;
		}

	} else {

		nZoomTop = nTop;
		nZoomBottom = nBottom;
		nZoomLeft = nLeft;
		nZoomRight = nRight;
	}

	do {

		if ( nFlags & BOX_ZOOMED ) {

			// if zooming, increment the box size
			nZoomTop -= nRowInc;
			if ( nZoomTop < nTop )
				nZoomTop = nTop;

			nZoomBottom += nRowInc;
			if ( nZoomBottom > nBottom )
				nZoomBottom = nBottom;

			nZoomLeft -= nColumnInc;
			if ( nZoomLeft < nLeft )
				nZoomLeft = nLeft;

			nZoomRight += nColumnInc;
			if ( nZoomRight > nRight )
				nZoomRight = nRight;
		}

		// clear the box to the specified attribute
		if ( nFill != -1 )
			Scroll( nZoomTop, nZoomLeft, nZoomBottom, nZoomRight, 0, nFill );

		if ( nStyle == 0 )
			nWidth = 0;
		else if (( nStyle == 2 ) || ( nStyle == 4 ))
			nWidth = 2;
		else
			nWidth = 1;

		// draw the two horizontals & the two verticals
		_line( nZoomTop, nZoomLeft, (nZoomRight-nZoomLeft)+1, nWidth, 0, nAttribute, nConnector );
		_line( nZoomBottom, nZoomLeft, (nZoomRight-nZoomLeft)+1, nWidth, 0, nAttribute, nConnector );

		if ( nStyle == 3 )
			nWidth = 2;
		else if ( nStyle == 4 )
			nWidth = 1;

		_line( nZoomTop, nZoomLeft, (nZoomBottom-nZoomTop)+1, nWidth, 1, nAttribute, nConnector );
		_line( nZoomTop, nZoomRight, (nZoomBottom-nZoomTop)+1, nWidth, 1, nAttribute, nConnector );

		// slow things down a bit
		SysBeep( 0, 1 );

	} while (( nFlags & BOX_ZOOMED ) && (( nZoomTop > nTop ) || ( nZoomBottom < nBottom ) || ( nZoomLeft > nLeft ) || ( nZoomRight < nRight )));

	// check for a shadow
	if ( nFlags & BOX_SHADOWED ) {

		nLeft += 2;
		nRight++;
		if ( nLeft >= nRight )
			nLeft = nRight - 1;

		// read the character and attribute, and change
		//   the attribute to black background, low intensity
		//   foreground
		SetLineColor( ++nBottom, nLeft, (nRight-nLeft), 7 );

		// shadow the right side of the window
		for ( nTop++; ( nTop <= nBottom ); nTop++ )
			SetLineColor( nTop, nRight, 2, 7 );
	}
}
Esempio n. 6
0
static int _fastcall _list( LPTSTR pszFileName )
{
	register int c, i;
	TCHAR szDescription[512], szHeader[132], szLine[32];
	long lTemp, lRow;
	POPWINDOWPTR wn = NULL;
	FILESEARCH dir;
	
	// get default normal and inverse attributes
	if ( gpIniptr->ListColor != 0 ) {
		SetScrColor( nScreenRows, nScreenColumns, gpIniptr->ListColor );

	}
	
	// set colors
	GetAtt( (unsigned int *)&nNormal, (unsigned int *)&nInverse );
	if ( gpIniptr->ListStatusColor != 0 )
		nInverse = gpIniptr->ListStatusColor;
	
	// flip the first line to inverse video
	clear_header();
	
	// open the file & initialize buffers
	if ( ListOpenFile( pszFileName ))
		return ERROR_EXIT;
	
	// kludge for empty files or pipes
	if ( LFile.lSize == 0L )
		LFile.lSize = 1L;
	
	for ( ; ; ) {
		
		// display header
		if ( fDirtyHeader ) {
			clear_header();
			sprintf( szHeader, LIST_HEADER, fname_part(LFile.szName), gchVerticalBar, gchVerticalBar, gchVerticalBar );
			WriteStrAtt( 0, 0, nInverse, szHeader );
			fDirtyHeader = 0;
		}
		
		// display location within file
		//	(don't use color_printf() so we won't have
		//	problems with windowed sessions)

		i = sprintf( szHeader, LIST_LINE, LFile.nListHorizOffset, LFile.lCurrentLine + gpIniptr->ListRowStart, (int)((( LFile.lViewPtr + 1 ) * 100 ) / LFile.lSize ));

		WriteStrAtt( 0, ( nScreenColumns - i ), nInverse, szHeader );
		SetCurPos( 0, 0 );
		
		if ( lListFlags & LIST_SEARCH ) {
			
			lListFlags &= ~LIST_SEARCH;
			fSearchFlags = 0;
			if ( lListFlags & LIST_REVERSE ) {
				
				c = LIST_FIND_CHAR_REVERSE;
				fSearchFlags |= FFIND_REVERSE_SEARCH;
				
				// goto the last row
				while ( ListMoveLine( 1 ) != 0 )
					;
			} else
				c = LIST_FIND_CHAR;
			
			if ( lListFlags & LIST_NOWILDCARDS )
				fSearchFlags |= FFIND_NOWILDCARDS;
			bListSkipLine = 0;
			goto FindNext;
		}
		
		// get the key from the BIOS, because
		//	 STDIN might be redirected
		
		if ((( c = cvtkey( GetKeystroke( EDIT_NO_ECHO | EDIT_BIOS_KEY | EDIT_UC_SHIFT), MAP_GEN | MAP_LIST)) == (TCHAR)ESC ))
			break;
		
		switch ( c ) {
		case CTRLC:
			return CTRLC;
			
		case CUR_LEFT:
		case CTL_LEFT:
			
			if (( lListFlags & LIST_WRAP ) || ( LFile.nListHorizOffset == 0 ))
				goto bad_key;
			
			if (( LFile.nListHorizOffset -= (( c == CUR_LEFT ) ? 8 : 40 )) < 0 )
				LFile.nListHorizOffset = 0;
			break;
			
		case CUR_RIGHT:
		case CTL_RIGHT:
			
			if (( lListFlags & LIST_WRAP ) || ( LFile.nListHorizOffset >= MAXLISTLINE + 1 ))
				goto bad_key;
			
			if ((LFile.nListHorizOffset += ((c == CUR_RIGHT) ? 8 : 40 )) > MAXLISTLINE + 1 )
				LFile.nListHorizOffset = MAXLISTLINE+1;
			break;
			
		case CUR_UP:
			
			if ( ListMoveLine( -1 ) == 0 )
				goto bad_key;
			
			Scroll(1, 0, nScreenRows, nScreenColumns, -1, nNormal);
			DisplayLine( 1, LFile.lViewPtr );
			continue;
			
		case CUR_DOWN:
			
			if ( ListMoveLine( 1 ) == 0 )
				goto bad_key;
			
			Scroll( 1, 0, nScreenRows, nScreenColumns, 1, nNormal );
			
			// display last line
			lTemp = LFile.lViewPtr;
			lRow = (nScreenRows - 1);
			lTemp += MoveViewPtr( lTemp, &lRow );
			if ( lRow == ( nScreenRows - 1 ))
				DisplayLine( nScreenRows, lTemp );
			continue;
			
		case HOME:
			
			ListHome();
			break;
			
		case END:
			
			// goto the last row
			list_wait( LIST_WAIT );
			while ( ListMoveLine( 1 ) != 0 )
				;

		case PgUp:
			
			// already at TOF?
			if ( LFile.lViewPtr == 0L )
				goto bad_key;
			
			for ( i = 1; (( i < nScreenRows ) && ( ListMoveLine( -1 ) != 0 )); i++ )
				;
			
			break;
			
		case PgDn:
		case SPACE:
			
			if ( ListMoveLine( nScreenRows - 1 ) == 0 )
				goto bad_key;
			
			break;
			
		case F1:	// help

			// don't allow a ^X exit from HELP
			_help( gpInternalName, HELP_NX );

			continue;
			
		case TAB:
			// change tab size
			
			// disable ^C / ^BREAK handling
			HoldSignals();
			
			wn = wOpen( 2, 5, 4, strlen( LIST_TABSIZE ) + 10, nInverse, LIST_TABSIZE_TITLE, NULL );
			wn->nAttrib = nNormal;
			wClear();
			
			wWriteListStr( 0, 1, wn, LIST_TABSIZE );
			egets( szLine, 2, (EDIT_DIALOG | EDIT_BIOS_KEY | EDIT_NO_CRLF | EDIT_DIGITS));
			wRemove( wn );
			if (( i = atoi( szLine )) > 0 )
				TABSIZE = i;
			
			// enable ^C / ^BREAK handling
			EnableSignals();
			break;
			
		case DEL:
			// delete this file
			if (( lListFlags & LIST_STDIN ) == 0 ) {
				
				// disable ^C / ^BREAK handling
				HoldSignals();
				
				wn = wOpen( 2, 5, 4, strlen( LIST_DELETE ) + 10, nInverse, LIST_DELETE_TITLE, NULL );
				wn->nAttrib = nNormal;
				wClear();
				
				wWriteListStr( 0, 1, wn, LIST_DELETE );
				i = GetKeystroke( EDIT_ECHO | EDIT_BIOS_KEY | EDIT_UC_SHIFT );
				wRemove( wn );
				
				// enable ^C / ^BREAK handling
				EnableSignals();
				
				if ( i == (TCHAR)YES_CHAR ) {
					if ( LFile.hHandle > 0 )
						_close( LFile.hHandle );
					LFile.hHandle = -1;
					
					remove( pszFileName );
					return 0;
				}
			}
			break;
			
		case INS:
			// save to a file
			ListSaveFile();
			break;
			
		case LIST_INFO_CHAR:
			{
				unsigned int uSize = 1024;
				TCHAR _far *lpszText, _far *lpszArg;
				int fFSType, fSFN = 1;
				TCHAR szBuf[16];

				DOSFILEDATE laDir, crDir;

				// disable ^C / ^BREAK handling
				HoldSignals();
				
				memset( &dir, '\0', sizeof(FILESEARCH) );
				if (( lListFlags & LIST_STDIN ) == 0 ) {
					if ( find_file( FIND_FIRST, LFile.szName, 0x07 | FIND_CLOSE | FIND_EXACTLY, &dir, NULL ) == NULL ) {
						honk();
						continue;
					}
				}
				
				// display info on the current file
				i = (( lListFlags & LIST_STDIN ) ? 5 : 10 );
				if (( fFSType = ifs_type( LFile.szName )) != FAT )
					i = 11;
				wn = wOpen( 2, 1, i, 77, nInverse, gpInternalName, NULL );
				
				wn->nAttrib = nNormal;
				wClear();
				i = 0;
				
				if ( lListFlags & LIST_STDIN )
					wWriteStrAtt( 0, 1, nNormal, LIST_INFO_PIPE );
				
				else {
					
					szDescription[0] = _TEXT('\0');
					process_descriptions( LFile.szName, szDescription, DESCRIPTION_READ );
					
					lpszText = lpszArg = (TCHAR _far *)AllocMem( &uSize );

					strcpy(szBuf, FormatDate( dir.fd.file_date.months, dir.fd.file_date.days, dir.fd.file_date.years + 80, 0 ));
					
					if (fFSType != FAT) {
						FileTimeToDOSTime( &(dir.ftLastAccessTime), &( laDir.ft.wr_time), &( laDir.fd.wr_date) );
						FileTimeToDOSTime( &(dir.ftCreationTime), &(crDir.ft.wr_time), &(crDir.fd.wr_date) );
						strcpy( szLine, FormatDate( laDir.fd.file_date.months, laDir.fd.file_date.days, laDir.fd.file_date.years + 80, 0 ));
						sprintf_far( lpszText, LIST_INFO_LFN,
							LFile.szName, szDescription, dir.ulSize,
							szBuf,
							dir.ft.file_time.hours, gaCountryInfo.szTimeSeparator[0],dir.ft.file_time.minutes,
							szLine,
							laDir.ft.file_time.hours, gaCountryInfo.szTimeSeparator[0], laDir.ft.file_time.minutes,
							FormatDate( crDir.fd.file_date.months, crDir.fd.file_date.days, crDir.fd.file_date.years + 80, 0 ),
							crDir.ft.file_time.hours, gaCountryInfo.szTimeSeparator[0], crDir.ft.file_time.minutes);
					} else {
						
						sprintf_far( lpszText, LIST_INFO_FAT,
							LFile.szName, szDescription, dir.ulSize,
							szBuf, dir.ft.file_time.hours, 
							gaCountryInfo.szTimeSeparator[0],dir.ft.file_time.minutes );
					}

					// print the text
					for ( ; ( *lpszArg != _TEXT('\0') ); i++ ) {
						sscanf_far( lpszArg, _TEXT("%[^\n]%*c%n"), szHeader, &uSize );

						// allow for long filenames ...
						if (( i == 0 ) && ( strlen( szHeader ) > 73 )) {
							c = szHeader[73];
							szHeader[73] = _TEXT('\0');
							wWriteStrAtt( i++, 1, nNormal, szHeader );
							szHeader[73] = (TCHAR)c;
							wWriteStrAtt( i, 15, nNormal, szHeader+73 );
							fSFN = 0;
						} else

							wWriteStrAtt( i, 1, nNormal, szHeader );
						lpszArg += uSize;
					}
					
					FreeMem( lpszText );
				}
				
				wWriteListStr( i+fSFN, 1, wn, PAUSE_PROMPT );
				GetKeystroke( EDIT_NO_ECHO | EDIT_BIOS_KEY );
				
				wRemove( wn );
				
				// enable ^C / ^BREAK handling
				EnableSignals();
				
				continue;
			}
			
		case LIST_GOTO_CHAR:
			
			// goto the specified line / hex offset
			
			// disable ^C / ^BREAK handling
			HoldSignals();
			
			wn = wOpen( 2, 5, 4, strlen( LIST_GOTO_OFFSET ) + 20, nInverse, LIST_GOTO_TITLE, NULL );
			wn->nAttrib = nNormal;
			wClear();
			
			wWriteListStr( 0, 1, wn, (( lListFlags & LIST_HEX) ? LIST_GOTO_OFFSET : LIST_GOTO));
			i = egets( szLine, 10, (EDIT_DIALOG | EDIT_BIOS_KEY | EDIT_NO_CRLF));
			wRemove( wn );
			
			// enable ^C / ^BREAK handling
			EnableSignals();
			
			if ( i == 0 )
				break;
			list_wait( LIST_WAIT );
			
			// if in hex mode, jump to offset 
			if ( lListFlags & LIST_HEX ) {
				strupr( szLine );
				sscanf( szLine, _TEXT("%lx"), &lRow );
				lRow = lRow / 0x10;
			} else if ( sscanf( szLine, FMT_LONG, &lRow ) == 0 )
				continue;
			
			lRow -= gpIniptr->ListRowStart;
			if ( lRow >= 0 ) {
				LFile.lViewPtr = MoveViewPtr( 0L, &lRow );
				LFile.lCurrentLine = lRow;
			} else {
				LFile.lViewPtr += MoveViewPtr( LFile.lViewPtr, &lRow );
				LFile.lCurrentLine += lRow;
			}
			break;
			
		case LIST_HIBIT_CHAR:
			
			// toggle high bit filter
			lListFlags ^= LIST_HIBIT;
			break;
			
		case LIST_WRAP_CHAR:
			
			// toggle line wrap
			lListFlags ^= LIST_WRAP;
			nRightMargin = (( lListFlags & LIST_WRAP ) ? GetScrCols() : MAXLISTLINE );
			
			// recalculate current line
			list_wait( LIST_WAIT );
			
			// get start of line
			LFile.nListHorizOffset = 0;
			
			// line number probably changed, so recompute everything
			LFile.lCurrentLine = ComputeLines( 0L, LFile.lViewPtr );
			LFile.lViewPtr = MoveViewPtr( 0L, &(LFile.lCurrentLine ));
			break;
			
		case LIST_HEX_CHAR:
			
			// toggle hex display
			lListFlags ^= LIST_HEX;
			
			// if hex, reset to previous 16-byte
			//	 boundary
			if ( lListFlags & LIST_HEX ) {

				LFile.lViewPtr -= ( LFile.lViewPtr % 16 );
			} else {
				// if not hex, reset to start of line
				ListMoveLine( 1 );
				ListMoveLine( -1 );
			}
			
			// recalculate current line
			list_wait( LIST_WAIT );
			LFile.lCurrentLine = ComputeLines( 0L, LFile.lViewPtr );
			break;
			
		case LIST_FIND_CHAR:
		case LIST_FIND_CHAR_REVERSE:
			// find first matching string
			bListSkipLine = 0;
			//lint -fallthrough
			
		case LIST_FIND_NEXT_CHAR:
		case LIST_FIND_NEXT_CHAR_REVERSE:
			// find next matching string
			
			if (( c == LIST_FIND_CHAR ) || ( c == LIST_FIND_CHAR_REVERSE )) {
				
				// disable ^C / ^BREAK handling
				HoldSignals();
				
				fSearchFlags = 0;
				wn = wOpen( 2, 1, 4, 75, nInverse, (( c == LIST_FIND_NEXT_CHAR_REVERSE ) ? LIST_FIND_TITLE_REVERSE : LIST_FIND_TITLE ), NULL );
				wn->nAttrib = nNormal;
				wClear();
				
				if ( lListFlags & LIST_HEX ) {
					wWriteListStr( 0, 1, wn, LIST_FIND_HEX );
					if ( GetKeystroke( EDIT_ECHO | EDIT_BIOS_KEY | EDIT_UC_SHIFT ) == YES_CHAR )
						fSearchFlags |= FFIND_HEX_SEARCH;
					wClear();
				}
				
				wWriteListStr( 0, 1, wn, LIST_FIND );
				egets( szListFindWhat, 64, (EDIT_DIALOG | EDIT_BIOS_KEY | EDIT_NO_CRLF));
				wRemove( wn );
				
				// enable ^C / ^BREAK handling
				EnableSignals();
				
			} else {
FindNext:
			// a "Next" has to be from current position
			fSearchFlags &= ~FFIND_TOPSEARCH;
			}
			
			if ( szListFindWhat[0] == _TEXT('\0') )
				continue;
			
			sprintf( szDescription, LIST_FIND_WAIT, szListFindWhat );
			list_wait( szDescription );
			
			// save start position
			lTemp = LFile.lViewPtr;
			lRow = LFile.lCurrentLine;
			
			if (( c == LIST_FIND_CHAR_REVERSE ) || ( c == LIST_FIND_NEXT_CHAR_REVERSE )) {
				// start on the previous line
				fSearchFlags |= FFIND_REVERSE_SEARCH;
			} else {
				fSearchFlags &= ~FFIND_REVERSE_SEARCH;
				// skip the first line (except on /T"xxx")
				if ( bListSkipLine )
					ListMoveLine( 1 );
			}
			
			bListSkipLine = 1;
			if ( SearchFile( fSearchFlags ) != 1 ) {
				ListSetCurrent( lTemp );
				LFile.lViewPtr = lTemp;
				LFile.lCurrentLine = lRow;
			} else
				LFile.fDisplaySearch = (( fSearchFlags & FFIND_CHECK_CASE ) ? 2 : 1 );
			
			break;
			
		case LIST_PRINT_CHAR:
			
			// print the file
			ListPrintFile();
			continue;
			
		case LIST_CONTINUE_CHAR:
		case CTL_PgDn:
			return 0;
			
		case LIST_PREVIOUS_CHAR:
		case CTL_PgUp:
			// previous file
			if ( nCurrent > 0 ) {
				nCurrent--;
				return 0;
			}
			//lint -fallthrough
			
		default:
bad_key:
			honk();
			continue;
		}
		
		// rewrite the display
		ListUpdateScreen();
	}
	
	return 0;
}