private static LinkedList<Diff> diff_lineMode(String text1, String text2, long deadline)
	{
		// Scan the text on a line-by-line basis first.
		final LinesToCharsResult b = diff_linesToChars(text1, text2);
		text1 = b.chars1;
		text2 = b.chars2;
		final List<String> linearray = b.lineArray;

		final LinkedList<Diff> diffs = diff_main(text1, text2, false, deadline);

		// Convert the diff back to original text.
		diff_charsToLines(diffs, linearray);
		// Eliminate freak matches (e.g. blank lines)
		diff_cleanupSemantic(diffs);

		// Rediff any replacement blocks, this time character-by-character.
		// Add a dummy entry at the end.
		diffs.add(new Diff(DiffOperation.EQUAL, ""));
		int count_delete = 0;
		int count_insert = 0;
		String text_delete = "";
		String text_insert = "";
		final ListIterator<Diff> pointer = diffs.listIterator();
		Diff thisDiff = pointer.next();
		while (thisDiff != null)
		{
			switch (thisDiff.operation)
			{
			case INSERT:
				count_insert++;
				text_insert += thisDiff.text;
				break;
			case DELETE:
				count_delete++;
				text_delete += thisDiff.text;
				break;
			case EQUAL:
				// Upon reaching an equality, check for prior redundancies.
				if (count_delete >= 1 && count_insert >= 1)
				{
					// Delete the offending records and add the merged ones.
					pointer.previous();
					for (int j = 0; j < count_delete + count_insert; j++)
					{
						pointer.previous();
						pointer.remove();
					}
					for (final Diff newDiff : diff_main(text_delete, text_insert, false, deadline))
					{
						pointer.add(newDiff);
					}
				}
				count_insert = 0;
				count_delete = 0;
				text_delete = "";
				text_insert = "";
				break;
			}
			thisDiff = pointer.hasNext() ? pointer.next() : null;
		}
		diffs.removeLast();	// Remove the dummy entry at the end.

		return diffs;
	}