void
GMMIMEParser::WriteAttachment
	(
	const JString&		data,
	const GMIMEHeader&	header
	)
{
	JString filename = header.GetFileName();
	if (filename.IsEmpty())
		{
		const JError err = JCreateTempFile(itsAttachDir, NULL, &filename);
		if (!err.OK())
			{
			err.ReportIfError();
			return;
			}
		}
	else
		{
		filename = JCombinePathAndName(itsAttachDir, filename);
		}

	AdjustAttachmentName(header, &filename);
	std::ofstream os(filename);
	if (header.GetEncoding() == kBase64Encoding)
		{
		std::istrstream is(data.GetCString(), data.GetLength());
		JDecodeBase64(is, os);
		}
	else
		{
		data.Print(os);
		}
}
JMemoryManager*
JMemoryManager::Instance()
{
	// Guarantees access is only through this function
	static JMemoryManager* manager = NULL;

	if (manager == NULL)
		{
		theConstructingFlag = kJTrue;
		manager = new(__FILE__, __LINE__) JMemoryManager;
		assert(manager != NULL);

		// Create the error printer proxy to do the printing work.
		// Construction of the error printer must take place here, after
		// the manager is fully constructed; the recursive call to Instance
		// is harmless.
		manager->itsErrorPrinter = new(__FILE__, __LINE__) JMMErrorPrinter;
		assert(manager->itsErrorPrinter != NULL);

		const JCharacter* pipeName = getenv("JMM_PIPE");
		if (!JStringEmpty(pipeName))
			{
			manager->itsErrorStream = new(__FILE__, __LINE__) JMMDebugErrorStream;
			assert(manager->itsErrorStream != NULL);
			}

		theConstructingFlag = kJFalse;
		manager->EmptyStacks();

		// do it here since it calls delete as well as new

		if (!JStringEmpty(pipeName))
			{
			manager->ConnectToDebugger(pipeName);
			ACE_Object_Manager::at_exit(NULL, ::JMMHandleACEExit, NULL);

			// If we create the file when we actually need it, it
			// re-constructs JStringManager.

			JString fileName;
			const JError err = JCreateTempFile(&fileName);
			if (err.OK())
				{
				theInternalFlag = kJTrue;

				manager->itsExitStatsFileName = new JString(fileName);
				assert( manager->itsExitStatsFileName != NULL );

				theInternalFlag = kJFalse;
				}
			else
				{
				cerr << "Failed to create exit stats file:" << endl;
				cerr << err.GetMessage() << endl;
				}
			}
		}

	return manager;
}
JBoolean
JConvertToStream
(
    const int		input,
    ifstream*		input2,
    JString*		tempFullName,
    const JBoolean	closeInput
)
{
    JString data;
    if (!JReadAll(input, &data, closeInput))
    {
        return kJFalse;
    }

    if (!(JCreateTempFile(tempFullName)).OK())
    {
        return kJFalse;
    }

    ofstream output(*tempFullName);
    data.Print(output);
    output.close();

    input2->open(*tempFullName);
    return JI2B(input2->good());
}
Exemplo n.º 4
0
JError
JUncompressFile
	(
	const JCharacter*	origFileName,
	JString*			newFileName,
	const JCharacter*	dirName,
	JProcess**			process
	)
{
	// generate a file name if one is not provided

	if (newFileName->IsEmpty())
		{
		const JError err = JCreateTempFile(dirName, NULL, newFileName);
		if (!err.OK())
			{
			return err;
			}
		}
	else if (!JStringEmpty(dirName))
		{
		*newFileName = JCombinePathAndName(dirName, *newFileName);
		}

	// construct the command

	JString cmd = "gunzip --to-stdout ";
	cmd += JPrepArgForExec(origFileName);
	cmd += " >| ";
	cmd += JPrepArgForExec(*newFileName);

	cmd = "/bin/sh -c " + JPrepArgForExec(cmd);

	// run the command

	if (process != NULL)
		{
		return JProcess::Create(process, cmd);
		}
	else
		{
		JString errText;
		return JRunProgram(cmd, &errText);
		}
}
void
CBSearchTextDialog::SaveFileForSearch
	(
	const JString&		fullName,
	JPtrArray<JString>*	fileList,
	JPtrArray<JString>*	nameList
	)
	const
{
	JBoolean exists;
	const JIndex index =
		nameList->GetInsertionSortIndex(const_cast<JString*>(&fullName), &exists);
	if (!exists)
		{
		JString* file = jnew JString(fullName);
		assert( file != NULL );

		JXFileDocument* doc;
		if ((CBGetDocumentManager())->FileDocumentIsOpen(*file, &doc) &&
			doc->NeedsSave())
			{
			CBTextDocument* textDoc = dynamic_cast<CBTextDocument*>(doc);
			if (textDoc != NULL &&
				(JCreateTempFile(file)).OK())
				{
				std::ofstream output(*file);
				((textDoc->GetTextEditor())->GetText()).Print(output);
				}
			}

		if (!file->IsEmpty())
			{
			JString* name = jnew JString(fullName);
			assert( name != NULL );
			nameList->InsertAtIndex(index, name);

			fileList->InsertAtIndex(index, file);
			}
		else
			{
			jdelete file;
			}
		}
}
Exemplo n.º 6
0
JBoolean
JXImageSelection::GetImage
	(
	JXSelectionManager* selMgr,
	const Atom			selectionName,
	const Time			time,
	JXColormap*			colormap,
	JXImage**			image,
	const JBoolean		allowApproxColors
	)
{
	JXDisplay* display   = colormap->GetDisplay();
	const Atom xpmXAtom  = display->RegisterXAtom(kXPMXAtomName);
	const Atom gifXAtom  = display->RegisterXAtom(kGIFXAtomName);
	const Atom pngXAtom  = display->RegisterXAtom(kPNGXAtomName);
	const Atom jpegXAtom = display->RegisterXAtom(kJPEGXAtomName);

	JArray<Atom> typeList;
	if (selMgr->GetAvailableTypes(selectionName, time, &typeList))
		{
		JBoolean xpm=kJFalse, gif=kJFalse, png=kJFalse, jpeg=kJFalse;

		const JSize count = typeList.GetElementCount();
		for (JIndex i=1; i<=count; i++)
			{
			const Atom type = typeList.GetElement(i);
			xpm  = JI2B( xpm  || type == xpmXAtom  );
			gif  = JI2B( gif  || type == gifXAtom  );
			png  = JI2B( png  || type == pngXAtom  );
			jpeg = JI2B( jpeg || type == jpegXAtom );
			}

		while (xpm || gif || png || jpeg)
			{
			Atom type = None;
			if (png)
				{
				png  = kJFalse;
				type = pngXAtom;
				}
			else if (gif)
				{
				gif  = kJFalse;
				type = gifXAtom;
				}
			else if (xpm)
				{
				xpm  = kJFalse;
				type = xpmXAtom;
				}
			else if (jpeg)		// JPEG is lossy
				{
				jpeg = kJFalse;
				type = jpegXAtom;
				}

			Atom returnType;
			unsigned char* data;
			JSize dataLength;
			JXSelectionManager::DeleteMethod delMethod;
			JString fileName;
			if (selMgr->GetData(selectionName, time, type,
								&returnType, &data, &dataLength, &delMethod) &&
				(JCreateTempFile(&fileName)).OK())
				{
				ofstream output(fileName);
				output.write((char*) data, dataLength);
				output.close();

				selMgr->DeleteData(&data, delMethod);

				const JError err =
					JXImage::CreateFromFile(display, colormap, fileName, image,
											allowApproxColors);
				JRemoveFile(fileName);

				if (err.OK())
					{
					return kJTrue;
					}
				}
			}
		}

	*image = NULL;
	return kJFalse;
}
Exemplo n.º 7
0
JBoolean
JXImageSelection::ConvertData
	(
	const Atom		requestType,
	Atom*			returnType,
	unsigned char**	data,
	JSize*			dataLength,
	JSize*			bitsPerBlock
	)
	const
{
	*data         = NULL;
	*dataLength   = 0;
	*returnType   = None;
	*bitsPerBlock = 8;

	if (itsImage == NULL)
		{
		return kJFalse;
		}

	JString fileName;
	if (!(JCreateTempFile(&fileName)).OK())
		{
		return kJFalse;
		}

	JError err = JUnknownError(1);
	if (requestType == itsXPMXAtom)
		{
		err = itsImage->WriteXPM(fileName);
		}
	else if (requestType == itsGIFXAtom)
		{
		err = itsImage->WriteGIF(fileName, kJFalse);	// if too many colors, use PNG
		}
	else if (requestType == itsPNGXAtom)
		{
		err = itsImage->WritePNG(fileName);
		}
	else if (requestType == itsJPEGXAtom)
		{
		err = itsImage->WriteJPEG(fileName);
		}

	if (err.OK())
		{
		JString imageData;
		JReadFile(fileName, &imageData);
		JRemoveFile(fileName);

		*returnType = requestType;
		*dataLength = imageData.GetLength();
		*data       = new unsigned char[ *dataLength ];
		if (*data != NULL)
			{
			memcpy(*data, imageData.GetCString(), *dataLength);
			return kJTrue;
			}
		}

	JRemoveFile(fileName);
	return kJFalse;
}
void
GenerateForm
	(
	istream&			input,
	const JString&		formName,
	const JString&		tagName,
	const JString&		enclName,
	const JString&		codePath,
	const JString&		stringPath,
	const JString&		codeSuffix,
	const JString&		headerSuffix,
	JPtrArray<JString>*	backupList
	)
{
	const JString codeFileName    = codePath + formName + codeSuffix;
	const JString codeFileBakName = codeFileName + kBackupSuffix;

	const JString headerFileName    = codePath + formName + headerSuffix;
	const JString headerFileBakName = headerFileName + kBackupSuffix;

	if (!JFileExists(codeFileName))
		{
		cerr << codeFileName << " not found" << endl;
		return;
		}
	if (!JFileExists(headerFileName))
		{
		cerr << headerFileName << " not found" << endl;
		return;
		}

	cout << "Generating: " << formName << ", " << tagName << endl;

	const JBoolean shouldBackup = ShouldBackupForm(formName, backupList);

	// copy code file contents before start delimiter

	JString tempCodeFileName;
	JError err = JCreateTempFile(codePath, NULL, &tempCodeFileName);
	if (!err.OK())
		{
		cerr << "Unable to create temporary file in " << codePath << endl;
		cerr << "  (" << err.GetMessage() << ')' << endl;
		return;
		}

	ifstream origCode(codeFileName);
	ofstream outputCode(tempCodeFileName);
	if (!outputCode.good())
		{
		cerr << "Unable to open temporary file in " << codePath << endl;
		remove(tempCodeFileName);
		return;
		}
	if (!CopyBeforeCodeDelimiter(tagName, origCode, outputCode))
		{
		cerr << "No starting delimiter in " << codeFileName << endl;
		outputCode.close();
		remove(tempCodeFileName);
		return;
		}

	// generate code for each object in the form

	JPtrArray<JString> objTypes(JPtrArrayT::kDeleteAll),
					   objNames(JPtrArrayT::kDeleteAll);
	GenerateCode(input, outputCode, stringPath, formName, tagName, enclName,
				 &objTypes, &objNames);

	// copy code file contents after end delimiter

	JBoolean done = CopyAfterCodeDelimiter(tagName, origCode, outputCode);
	origCode.close();
	outputCode.close();

	if (!done)
		{
		cerr << "No ending delimiter in " << codeFileName << endl;
		remove(tempCodeFileName);
		return;
		}
	else if (shouldBackup && rename(codeFileName, codeFileBakName) != 0)
		{
		cerr << "Unable to rename original " << codeFileName << endl;
		remove(tempCodeFileName);
		return;
		}
	JEditVCS(codeFileName);
	rename(tempCodeFileName, codeFileName);

	// copy header file contents before start delimiter

	JString tempHeaderFileName;
	err = JCreateTempFile(codePath, NULL, &tempHeaderFileName);
	if (!err.OK())
		{
		cerr << "Unable to create temporary file in " << codePath << endl;
		cerr << "  (" << err.GetMessage() << ')' << endl;
		return;
		}

	ifstream origHeader(headerFileName);
	ofstream outputHeader(tempHeaderFileName);
	if (!outputHeader.good())
		{
		cerr << "Unable to open temporary file in " << codePath << endl;
		remove(tempHeaderFileName);
		return;
		}
	if (!CopyBeforeCodeDelimiter(tagName, origHeader, outputHeader))
		{
		cerr << "No starting delimiter in " << headerFileName << endl;
		outputHeader.close();
		remove(tempHeaderFileName);
		return;
		}

	// generate instance variable for each object in the form

	GenerateHeader(outputHeader, objTypes, objNames);

	// copy header file contents after end delimiter

	done = CopyAfterCodeDelimiter(tagName, origHeader, outputHeader);
	origHeader.close();
	outputHeader.close();

	if (!done)
		{
		cerr << "No ending delimiter in " << headerFileName << endl;
		remove(tempHeaderFileName);
		return;
		}

	// check if header file actually changed

	JString origHeaderText, newHeaderText;
	JReadFile(headerFileName, &origHeaderText);
	JReadFile(tempHeaderFileName, &newHeaderText);
	if (newHeaderText != origHeaderText)
		{
		if (shouldBackup && rename(headerFileName, headerFileBakName) != 0)
			{
			cerr << "Unable to rename original " << headerFileName << endl;
			remove(tempHeaderFileName);
			return;
			}
		JEditVCS(headerFileName);
		rename(tempHeaderFileName, headerFileName);
		}
	else
		{
		remove(tempHeaderFileName);
		}
}
void
CBFunctionMenu::UpdateMenu()
{
	CBFnMenuUpdater* updater        = CBMGetFnMenuUpdater();
	const JXKeyModifiers& modifiers = GetDisplay()->GetLatestKeyModifiers();

	JBoolean sort = updater->WillSortFnNames();
	if (modifiers.meta())
		{
		sort = !sort;
		}

	JBoolean includeNS = updater->WillIncludeNamespace();
	if (modifiers.shift())
		{
		includeNS = !includeNS;
		}

	const JBoolean pack = updater->WillPackFnNames();

	if (itsNeedsUpdate || sort != itsSortFlag ||
		includeNS != itsIncludeNSFlag || pack != itsPackFlag)
		{
		#if defined CODE_CRUSADER

		assert( itsDoc != NULL );

		JString fileName;
		JBoolean deleteFile = kJFalse;
		if (itsDoc->NeedsSave())
			{
			itsDoc->SafetySave(JXDocumentManager::kTimer);
			if (!itsDoc->GetSafetySaveFileName(&fileName) &&
				(JCreateTempFile(&fileName)).OK())
				{
				// directory may not be writable

				deleteFile = kJTrue;

				// itsDoc can't be CBTextDocument, because Code Medic uses us

				CBTextDocument* textDoc = dynamic_cast<CBTextDocument*>(itsDoc);
				assert( textDoc != NULL );

				std::ofstream output(fileName);
				((textDoc->GetTextEditor())->GetText()).Print(output);
				}
			}
		else
			{
			JBoolean onDisk;
			fileName = itsDoc->GetFullName(&onDisk);
			if (!onDisk)
				{
				fileName.Clear();
				}
			}

		#elif defined CODE_MEDIC

		const JString& fileName = itsFileName;

		#endif

		if (!fileName.IsEmpty())
			{
			itsLang = updater->UpdateMenu(fileName, itsFileType, sort, includeNS, pack,
										  this, itsLineIndexList);
			}
		else
			{
			itsLang = kCBOtherLang;
			this->RemoveAllItems();
			itsLineIndexList->RemoveAll();
			}

		if (IsEmpty())
			{
			SetEmptyMenuItems();
			}

		itsNeedsUpdate    = kJFalse;
		itsSortFlag       = sort;
		itsIncludeNSFlag  = includeNS;
		itsPackFlag       = pack;
		itsCaretItemIndex = 0;				// nothing to remove
		itsTE->DeactivateCurrentUndo();		// force another TextChanged

		#if defined CODE_CRUSADER

		if (deleteFile)
			{
			JRemoveFile(fileName);
			}

		#endif
		}

	// mark caret location

	if (!sort && !itsLineIndexList->IsEmpty())
		{
		if (itsCaretItemIndex > 0)
			{
			ShowSeparatorAfter(itsCaretItemIndex, kJFalse);
			itsCaretItemIndex = 0;
			}

		const JIndex lineIndex =
			itsTE->VisualLineIndexToCRLineIndex(
						itsTE->GetLineForChar(itsTE->GetInsertionIndex()));

		const JSize count = GetItemCount();
		assert( count == itsLineIndexList->GetElementCount() );

		for (JIndex i=1; i<=count; i++)
			{
			if (itsLineIndexList->GetElement(i) > lineIndex)
				{
				itsCaretItemIndex = i-1;
				if (itsCaretItemIndex > 0)
					{
					ShowSeparatorAfter(itsCaretItemIndex, kJTrue);
					}
				break;
				}
			}
		}
}
Exemplo n.º 10
0
void
JStringManager::Register
	(
	const JCharacter*	signature,
	const JCharacter**	defaultData
	)
{
	JString tempFileName;
	const JError err = JCreateTempFile(&tempFileName);
	if (!err.OK())
		{
		return;
		}

	{
	std::ofstream tempFile(tempFileName);

	JIndex i = 0;
	while (defaultData[i] != NULL)
		{
		tempFile.write(defaultData[i], strlen(defaultData[i]));
		i++;
		}
	}
	MergeFile(tempFileName);
	JRemoveFile(tempFileName);

	if (!JStringEmpty(signature))
		{
		const JCharacter* lang = getenv("LANG");

		JString path[2];
		JGetJDataDirectories(kDataDirName, path, path+1);

		JString name1, name2;
		for (JIndex i=0; i<2; i++)
			{
			if (!path[i].IsEmpty() &&
				(JDirectoryReadable(path[i]) ||
				 JCreateDirectory(path[i]) == kJNoError))
				{
				name1 = JCombinePathAndName(path[i], signature);

				if (lang != NULL)
					{
					name2 = name1;
					name2.AppendCharacter('_');
					name2.Append(lang);

					if (MergeFile(name2))
						{
						break;
						}
					}

				if (MergeFile(name1))
					{
					break;
					}
				}
			}
		}
}
Exemplo n.º 11
0
void
GMMIMEParser::Parse
	(
	std::istream&		input,
	const JIndex	isEnd,
	const JBoolean	nested
	)
{
	GMIMEHeader* header = new GMIMEHeader();
	assert(header != NULL);

	if (input.good())
		{
		ParseMIMEHeader(input, header, nested);

		if (header->GetEncoding() == kBase64Encoding)
			{
			JString filename = header->GetFileName();
			if (filename.IsEmpty())
				{
				const JError err = JCreateTempFile(itsAttachDir, NULL, &filename);
				if (!err.OK())
					{
					itsIsSuccessful	= kJFalse;
					}
				}
			else
				{
				filename = JCombinePathAndName(itsAttachDir, filename);
				}
			if (!filename.IsEmpty())
				{
				AdjustAttachmentName(*header, &filename);
				std::ofstream os(filename);
				JDecodeBase64(input, os);
				}
			}
		else if ((header->GetType() != kMultipartType) &&
				 (!header->GetFileName().IsEmpty()))
			{
			JIndex startI = JTellg(input);
			const JCharacter* c = itsData->GetCString() + startI;
			JString filename	= header->GetFileName();
			if (filename.IsEmpty())
				{
				const JError err = JCreateTempFile(itsAttachDir, NULL, &filename);
				if (!err.OK())
					{
					itsIsSuccessful	= kJFalse;
					}
				}
			else
				{
				filename = JCombinePathAndName(itsAttachDir, filename);
				}
			if (!filename.IsEmpty())
				{
				AdjustAttachmentName(*header, &filename);
				std::ofstream os(filename);
				os.write(c, isEnd - startI);
				}
			}
		else
			{
			// parse message body. may be recursive
			ParseByType(input, *header, isEnd);
			}
		}
	else
		{
		itsIsSuccessful	= kJFalse;
		}

	if (itsTextInfo != NULL)
		{
		itsTextInfo->ForceUpdate();
		}
	if (itsAttachInfo != NULL)
		{
		itsAttachInfo->ForceUpdate();
		}
		
	delete header;
}
Exemplo n.º 12
0
void
GMMIMEParser::ParseMixed
	(
	std::istream&			input,
	const GMIMEHeader&	header
	)
{
	JString boundary	= "-" + header.GetBoundary();
	JString endBoundary = boundary + "--";

	// slurp the initial empty part
	JIndex bstart, bend;
	ReadUntilBoundary(input, boundary, &bstart, &bend);
	JIndex current = JTellg(input);
	JString data;
	data.Read(input, bend - current + 1);

	while (1)
		{
		GMIMEHeader child;
		ParseMIMEHeader(input, &child);

		// when the following function returns true, it has found the
		// last boundary
		data.Clear();
		JBoolean end;
		if (child.GetEncoding() == kBase64Encoding)
			{
			JString filename = child.GetFileName();
			if (filename.IsEmpty())
				{
				JCreateTempFile(itsAttachDir, NULL, &filename);
				}
			else
				{
				filename = JCombinePathAndName(itsAttachDir, filename);
				}
			if (!filename.IsEmpty())
				{
				AdjustAttachmentName(child, &filename);
				std::ofstream os(filename);
				JDecodeBase64(input, os);
				end = ReadUntilBoundary(input, boundary, &bstart, &bend);
	//			JBoolean found;
	//			JString line;
	//			while (line.IsEmpty() && !input.fail())
	//				{
	//				line = JReadLine(input, &found);
	//				}
	//			JString endBoundary = boundary + "--";
	//			if (line.Contains(endBoundary))
	//				{
	//				end = kJTrue;
	//				}
				}
			}
		else if ((child.GetType() != kMultipartType) &&
				 (!child.GetFileName().IsEmpty()))
			{
			JIndex startI = JTellg(input);
			JIndex findex = startI;
			if (itsData->LocateNextSubstring(boundary, &findex))
				{
				const JCharacter* c = itsData->GetCString() + startI;
				JString filename	= child.GetFileName();
				if (filename.IsEmpty())
					{
					JCreateTempFile(itsAttachDir, NULL, &filename);
					}
				else
					{
					filename = JCombinePathAndName(itsAttachDir, filename);
					}
				if (!filename.IsEmpty())
					{
					AdjustAttachmentName(child, &filename);
					std::ofstream os(filename);
					JSeekg(input, findex - 1);
					if (child.GetEncoding() == kQPEncoding)
						{
						JString data	= itsData->GetSubstring(startI, findex - 3);
						ParseQuotedPrintable(&data);
						data.Print(os);
						}
					else
						{
						os.write(c, findex - startI - 3);
						}				
					JBoolean found;
					JString line = JReadLine(input, &found);
					if (line.BeginsWith(endBoundary))
						{
						end = kJTrue;
						}
					}
				}
			}
		else
			{
			end = ReadUntilBoundary(input, boundary, &bstart, &bend);
			ParseByType(input, child, bstart - 1);

			current	= JTellg(input);
			data.Read(input, bend - current + 1);
			}
		if (end)
			{
			break;
			}
		}

	if (itsTextInfo != NULL)
		{
		itsTextInfo->ForceUpdate();
		}
	if (itsAttachInfo != NULL)
		{
		itsAttachInfo->ForceUpdate();
		}
}
JBoolean
JPTPrinter::Print
	(
	const JCharacter*	text,
	ostream&			trueOutput
	)
{
	ostream* dataOutput  = &trueOutput;
	ofstream* tempOutput = NULL;
	JString tempName;
	if (itsPrintReverseOrderFlag)
		{
		if (!(JCreateTempFile(&tempName)).OK())
			{
			return kJFalse;
			}

		tempOutput = new ofstream(tempName);
		assert( tempOutput != NULL );
		if (tempOutput->bad())
			{
			delete tempOutput;
			JRemoveFile(tempName);
			return kJFalse;
			}
		dataOutput = tempOutput;
		}

	const JSize headerLineCount = GetHeaderLineCount();
	const JSize footerLineCount = GetFooterLineCount();
	assert( itsPageHeight > headerLineCount + footerLineCount );

	const JSize lineCountPerPage = itsPageHeight - headerLineCount - footerLineCount;

	JLatentPG pg;
	pg.VariableLengthProcessBeginning("Printing page...", kJTrue, kJFalse);
	JBoolean keepGoing = kJTrue;

	JUnsignedOffset i   = 0;
	JIndex pageIndex    = 0;
	JSize printCount    = 0;
	JSize textLineCount = 0;
	while (keepGoing && text[i] != '\0')
		{
		pageIndex++;
		const JBoolean shouldPrintPage =
			JI2B(itsFirstPageIndex <= pageIndex &&
				 (itsLastPageIndex == 0 || pageIndex <= itsLastPageIndex));

		std::ostringstream bitBucket;
		ostream* output = shouldPrintPage ? dataOutput : (&bitBucket);

		if (shouldPrintPage)
			{
			printCount++;
			if (printCount > 1)
				{
				*output << kPageSeparatorStr;
				}
			}

		if (headerLineCount > 0)
			{
			PrintHeader(*output, pageIndex);
			}

		JSize lineNumberWidth = 0;
		if (itsPrintLineNumberFlag)
			{
			const JString lastLineIndexStr(pageIndex * lineCountPerPage, 0);
			lineNumberWidth = lastLineIndexStr.GetLength();
			}

		JSize lineCount = 0;
		while (lineCount < lineCountPerPage && text[i] != '\0')
			{
			JSize col = 0;

			if (itsPrintLineNumberFlag)
				{
				const JString lineNumberStr(textLineCount+1, 0);
				const JSize spaceCount = lineNumberWidth - lineNumberStr.GetLength();
				for (JIndex j=1; j<=spaceCount; j++)
					{
					*output << ' ';
					}
				lineNumberStr.Print(*output);
				*output << kLineNumberMarginStr;

				col += lineNumberWidth + kLineNumberMarginWidth;
				}

			if (col >= itsPageWidth)	// insures progress, even in ludicrous boundary case
				{
				col = itsPageWidth - 1;
				}

			while (col < itsPageWidth && text[i] != '\n' && text[i] != '\0')
				{
				if (text[i] == '\t')
					{
					const JSize spaceCount = itsTabWidth - (col % itsTabWidth);
					for (JIndex j=1; j<=spaceCount; j++)
						{
						*output << ' ';
						}
					col += spaceCount;
					}
				else if (text[i] == kJFormFeedKey)
					{
					*output << ' ';
					col++;
					}
				else
					{
					*output << text[i];
					col++;
					}
				i++;
				}

			*output << '\n';
			if (text[i] == '\n')
				{
				i++;
				}

			lineCount++;
			textLineCount++;
			}

		if (footerLineCount > 0)
			{
			while (lineCount < lineCountPerPage)
				{
				*output << '\n';
				lineCount++;
				}

			PrintFooter(*output, pageIndex);
			}

		keepGoing = pg.IncrementProgress();
		}

	pg.ProcessFinished();

	if (itsPrintReverseOrderFlag)
		{
		delete tempOutput;
		if (keepGoing)
			{
			JString text;
			JReadFile(tempName, &text);
			InvertPageOrder(text, trueOutput);
			}
		JRemoveFile(tempName);
		}

	return keepGoing;
}