View difference between Paste ID: 7JJmGRNH and 8GVsfU7b
SHOW: | | - or go back to the newest paste.
1-
-- Word processor written by PaymentOption for ComputerCraft 1.42 --
1+
-- Word processor written by PaymentOption
2
3
-- VARIABLES --
4
bPrinted = false -- Whether or not the document has been printed.
5
tDocument = {}
6
7
bHasPaper = false
8
nPaperCount = 0
9
nPaperWidth, nPaperHeight = 0,0
10
11
bHasInk = false
12
nInkCount = 0
13
14
bHasPrinter = false
15
sPrinterSide = nil
16
17
bFirstPage = false -- Whether or not the first page has been started.
18
-- The wrapped printer.
19
printer = nil
20
21
nScreenWidth, nScreenHeight = term.getSize()
22
nSelection = 1 -- The selection of the print confirmation dialog box.
23
---------------
24
25
-- INITIALIZATION METHODS --
26
-- Returns true and the side the printer exists on if there a printer is found.
27
function checkForPrinter()
28
	local tSides = rs.getSides()
29
	-- Run through all of the possible sides and check for a printer peripheral.
30
	for index, side in ipairs( tSides ) do
31
		-- If a printer is found.
32
		if peripheral.isPresent( side ) and peripheral.getType( side ) == "printer" then
33
			return true, side
34
		end
35
	end
36
	
37
	-- No printer was found.
38
	return false, nil
39
end
40
41
-- Returns the wrapped printer object.
42
function wrapPrinter( side )
43
	return peripheral.wrap( side )
44
end
45
46
-- Returns true and the amount of paper if there is paper; false and nil if there is none.
47
function checkForPaper( side, printerWrap )
48
	if printerWrap.getPaperLevel() > 0 then
49
		return true, printerWrap.getPaperLevel()
50
	else
51
		return false, 0
52
	end
53
end
54
55
-- Returns true and the amount of ink if there is ink; false and nil if there is none.
56
function checkForInk( side, printerWrap )
57
	if printerWrap.getInkLevel() > 0 then
58
		return true, printerWrap.getInkLevel()
59
	else
60
		return false, 0
61
	end
62
end
63
64
-- Returns the width and height of the paper stored.
65
function getPaperDimensions( printerWrap )
66
	return printerWrap.getPageSize()
67
end
68
69
-- Sets up the page to be printed on: clears it and repositions the cursor to (1, 1)
70
function setCursorToPrint( printerWrap )
71
	clearPage() -- Clear the page of any previous data.
72
	printerWrap.setCursorPos( 1, 1 )
73
end
74
75
-- Runs all necessary checks, if they pass then true is returned and all variables are setup.
76
function initializePrinterAndProgram()
77
	local bPrinterExists, sSide = checkForPrinter()
78
	
79
	local bPaper, bInk = false
80
	local nPaper, nInk = 0
81
	
82
	if bPrinterExists then
83
		-- Assign the global printer wrap to the newly found and wrapped peripheral.
84
		printer = wrapPrinter( sSide )
85
		-- Check for paper and ink amounts.
86
		bPaper, nPaper = checkForPaper( sSide, printer )
87
		bInk, nInk = checkForInk( sSide, printer )
88
		
89
		if bPaper and bInk then
90
			-- Assign the global variables to their proper values.
91
			bHasPaper = bPaper
92
			bHasInk = bInk
93
			
94
			nPaperCount = nPaper
95
			nInkCount = nInk
96
			
97
			bFirstPage = printer.newPage() -- Start the first page.
98
			nPaperWidth, nPaperHeight = getPaperDimensions( printer )
99
			setCursorToPrint( printer ) -- Setup the page so it is blank and the cursor is in the upper left hand corner (1, 1).
100
			-- Report a successful printer initialization.
101
			return true
102
		-- There was either no paper, or no ink.
103
		else
104
			-- There was no paper.
105
			if not bPaper then
106
				return false, true -- bHasPaper = false, bHasInk = true
107
			-- There was no ink, but there was paper.
108
			else
109
				return true, false -- bHasPaper = true, bHasInk = false
110
			end
111
		end
112
	-- No printer was found.
113
	else
114
		return false
115
	end
116
end
117
----------------------------
118
119
-- CUSTOM PRINTER METHODS --
120
-- Clears the current page of all textual data.
121
function clearPage()
122
	for nCurrentHeight=1, nPaperHeight do
123
		printer.setCursorPos( 1, nCurrentHeight )
124
		printer.write( string.rep( " ", nPaperWidth ) )
125
	end
126
end
127
128
-- Prints the page with the specified title and string.
129
function printPage( sTitle, tPage )
130
	printer.setPageTitle( sTitle )
131
	
132
	for nHeight=1, #tPage do
133
		printer.setCursorPos( 1, nHeight )
134
		printer.write( tPage[nHeight] )
135
	end
136
	
137
	if printer.endPage() then
138
		return true
139
	else
140
		return false
141
	end
142
end
143
----------------------------
144
145
-- TERMINAL ROUTINES (COMPUTER SPECIFIC METHODS) --
146
function clearScreen()
147
	term.clear()
148
	term.setCursorPos( 1, 1 )
149
end
150
151
-- Prints a string to the very center of the screen on the specified line.
152
function printCentered( nHeight, sString )
153
	term.setCursorPos( nScreenWidth/2 - string.len( sString )/2, nHeight )
154
	write( sString )
155
end
156
157
-- Prints a string to the very right of the screen on the specified line.
158
function printRight( nHeight, sString )
159
	term.setCursorPos( nScreenWidth - string.len( sString ), nHeight )
160
	write( sString )
161
end
162
163
-- Draws a box with a width of nBoxWidth.
164
function drawBox( nBoxWidth )
165
	printCentered( 4, "+" .. string.rep( "-", nBoxWidth ) .. "+" )
166
	for nHeight = 5, 12 do
167
		printCentered( nHeight, "|" .. string.rep( " ", nBoxWidth ) .. "|" )
168
	end
169
	printCentered( 13, "+" .. string.rep( "-", nBoxWidth ) .. "+" )
170
end
171
172
-- Handles the key presses thrown when we're getting print confirmation.
173
function handleKeyPress( nKey )
174
	-- If the right key is pressed and the current selection is 'YES'.
175
	if nKey == 205 and nSelection == 1 then
176
		nSelection = 2
177
	-- If the left key is pressed and the current selection is 'NO'.
178
	elseif nKey == 203 and nSelection == 2 then
179
		nSelection = 1
180
	-- If the enter key is pressed.
181
	elseif nKey == 28 then
182
		-- If the user wants to print then print the prompt the user for a tile to the document.
183
		if nSelection == 1 then
184
			local sPageTitle = getPageTitle()
185
			if printPage( sPageTitle, tDocument ) then
186
				-- End the program.
187
				clearScreen()
188
				print( os.version() )
189
				bPrinted = true
190
			else
191
				clearScreen()
192
				print( os.version() )
193
				error( "Printing error!" )
194
			end
195
		-- If the user does not want to print the re-edit the document.
196
		elseif nSelection == 2 then
197
			tDocument = readLines( tDocument )
198
			getConfirmation()
199
		end
200
	end
201
end
202
203
-- Reads a fixed amount of characters without ruining a GUI that may be printed on the same line.
204
function limitRead( nLength, cReplaceChar )
205
	term.setCursorBlink( true )
206
	
207
	nLength = nLength or -1 -- -1 is unlimited
208
	sReturnString = ""
209
	
210
	xPos, yPos = term.getCursorPos()
211
	
212
	while true do
213
		event, char = os.pullEvent()
214
		
215
		if nLength ~= -1 and string.len( sReturnString ) >= nLength then term.setCursorBlink( false ); return sReturnString end -- Length check
216
		
217
		if event == "char" then sReturnString = sReturnString .. char
218
		elseif event == "key" and char == 28 then term.setCursorBlink( false ); return sReturnString -- Enter
219
		elseif event == "key" and char == 14 then -- Backspace
220
			term.setCursorPos( xPos, yPos )
221
			term.write( string.rep( " ", string.len( sReturnString ) ) )
222
			sReturnString = string.sub( sReturnString, 1, string.len( sReturnString )-1 )
223
			term.setCursorPos( xPos, yPos )
224
			
225
			if not cReplaceChar then term.write( sReturnString )
226
			else term.write( string.rep( cReplaceChar, string.len( sReturnString ) ) ) end
227
		end
228
		
229
		term.setCursorPos( xPos, yPos )
230
		term.write( string.rep( " ", string.len( sReturnString ) ) )
231
		term.setCursorPos( xPos, yPos )
232
		if not cReplaceChar then term.write( sReturnString )
233
		else term.write( string.rep( cReplaceChar, string.len( sReturnString ) ) ) end
234
	end
235
end
236
237
-- Takes a line and checks if a word has not finished. If it hasn't
238
-- then it returns the table of lines with the corrected new line.
239
--[[function fixTruncation( tLines )
240
	-- Remove the \n chracter.
241
	sLine = sLine:sub( 1, string.len( sLine ) - 1 )
242
	-- Check if the line has not finished.
243
	if tLines[#tLines]:sub( 1, 2 ) ~= " " then
244
		for  in string.gfind(  )
245
		tLines[#tLines - 1] = tLines[#tLines - 1]:sub( 1,  )
246
	end
247
end--]]
248
249
-- TODO: Remove the truncation effect when jumping lines.
250
-- Reads multiple lines as one string.
251
function readLines( tLines )
252
	term.setCursorBlink( true )
253
	
254
	local bExistingDocument = nil
255
	if tLines then
256
		bExistingDocument = true
257
	else
258
		bExistingDocument = true
259
	end
260
	
261
	local tLines = tLines or {}
262
	local nLineWidthCap = nPaperWidth
263
	local nLineCap = nScreenHeight
264
	
265
	-- Initialize the lines.
266
	if #tLines == 0 then
267
		for nLine = 1, nLineCap do
268
			tLines[nLine] = ""
269
		end
270
	end
271
	
272
	local nReturnKey = 207 -- 'End'
273
	
274
	local nCursorPosX = 1
275
	local nCurrentLine = 1
276
	local nCurrentLineLength = 0
277
	
278
	-- Draws the paper border so people know where the page ends.
279
	local function drawBorder()
280
		for nHeight = 1, nScreenHeight do
281
			term.setCursorPos( 12, nHeight )
282
			term.write( "|" )
283
			
284
			term.setCursorPos( 12 + nPaperWidth + 1, nHeight )
285
			term.write( "|" )
286
		end
287
		
288
		term.setCursorPos( 1, nScreenHeight )
289
		term.write( "'END' menu" )
290
		printRight( nScreenHeight, "Ln " .. nCurrentLine .. " of ".. nScreenHeight )
291
	end
292
	
293
	clearScreen()
294
	drawBorder()
295
	if bExistingDocument then
296
		for nHeight=1, #tLines do
297
			term.setCursorPos( 13, nHeight )
298
			term.write( tLines[nHeight] )
299
		end
300
	end
301
	while nCurrentLine < nLineCap do
302
		term.setCursorPos( 13 + nCursorPosX - 1, nCurrentLine )
303
		local sEvent, cChar = os.pullEvent()
304
		
305
		if sEvent == "char" then
306
			if tLines[nCurrentLine]:len() + 1 < nLineWidthCap then
307
				tLines[nCurrentLine] = tLines[nCurrentLine]:sub( 1, nCursorPosX - 1 ) .. cChar .. tLines[nCurrentLine]:sub( nCursorPosX, tLines[nCurrentLine]:len() )
308
				nCursorPosX = nCursorPosX + 1
309
			else
310
				if nCurrentLine + 1 <= nLineCap then
311
					tLines[nCurrentLine] = tLines[nCurrentLine] .. cChar
312
					nCurrentLine = nCurrentLine+1
313
					nCursorPosX = 1
314
				else
315
					term.setCursorBlink( false )
316
					return tLines
317
				end
318
			end
319
		elseif sEvent == "key" then
320
			if cChar == 14 then
321
				if nCursorPosX - 1 > 0 then
322
					tLines[nCurrentLine] = tLines[nCurrentLine]:sub( 1, nCursorPosX - 2 ) .. tLines[nCurrentLine]:sub( nCursorPosX, tLines[nCurrentLine]:len() )
323
					nCursorPosX = nCursorPosX - 1
324
				else
325
					if nCurrentLine > 1 then
326
						nCurrentLine = nCurrentLine - 1
327
						if tLines[nCurrentLine]:len() == nLineWidthCap then
328
							tLines[nCurrentLine] = tLines[nCurrentLine]:sub( 1, tLines[nCurrentLine]:len() - 1 )
329
						end
330
						nCursorPosX = tLines[nCurrentLine]:len() + 1
331
					end
332
				end
333
			elseif cChar == 28 then
334
				if nCurrentLine + 1 <= nLineCap then
335
					nCurrentLine = nCurrentLine+1
336
					nCursorPosX = 1
337
				else
338
					term.setCursorBlink( false )
339
					return tLines
340
				end
341
			elseif cChar == 203 then
342
				if nCursorPosX - 1 > 1 then
343
					nCursorPosX = nCursorPosX - 1
344
				end
345
			elseif cChar == 205 then
346
				if nCursorPosX + 1 < tLines[nCurrentLine]:len() + 2 then
347
					nCursorPosX = nCursorPosX + 1
348
				end
349
			elseif cChar == 200 then
350
				if nCurrentLine - 1 > 0 then
351
					nCurrentLine = nCurrentLine - 1
352
					if tLines[nCurrentLine]:len() < nCursorPosX then
353
						if tLines[nCurrentLine]:len() > 0 then
354
							nCursorPosX = tLines[nCurrentLine]:len()
355
						else
356
							nCursorPosX = 1
357
						end
358
					end
359
				end
360
			elseif cChar == 208 then
361
				if nCurrentLine + 1 < #tLines then
362
					nCurrentLine = nCurrentLine + 1
363
					if tLines[nCurrentLine]:len() < nCursorPosX then
364
						if tLines[nCurrentLine]:len() > 0 then
365
							nCursorPosX = tLines[nCurrentLine]:len()
366
						else
367
							nCursorPosX = 1
368
						end
369
					end
370
				end
371
			elseif cChar == 15 then
372
				if tLines[nCurrentLine]:len() + 3 > nLineWidthCap then
373
					local nSpaceLeft = nLineWidthCap - tLines[nCurrentLine]:len()
374
					if nSpaceLeft > 0 then
375
						tLines[nCurrentLine] = tLines[nCurrentLine] .. string.rep( " ", nSpaceLeft )
376
					end
377
					
378
					nCurrentLine = nCurrentLine + 1
379
					nCursorPosX = 1
380
				else
381
					tLines[nCurrentLine] = tLines[nCurrentLine] .. "   "
382
					nCursorPosX = nCursorPosX + 3
383
				end
384
			elseif cChar == nReturnKey then
385
				term.setCursorBlink( false )
386
				return tLines
387
			end
388
		end
389
		
390
		clearScreen()
391
		drawBorder()
392
		for nHeight=1, #tLines do
393
			term.setCursorPos( 13, nHeight )
394
			term.write( tLines[nHeight] )
395
		end
396
	end
397
	
398
	term.setCursorBlink( false )
399
	return tLines
400
end
401
---------------------------------------------------
402
403
-- SCREENS --
404
-- This method gets whether or not the user wants to print the document typed. (used in drawAndGetPrintConfirmationScreen)
405
function getConfirmation()
406
	local function drawSelections()
407
		if nSelection == 1 then
408
			printCentered( 9, "[YES] NO " )
409
		elseif nSelection == 2 then
410
			printCentered( 9, " YES [NO]" )
411
		end
412
	end
413
	
414
	-- Draw the confirmation options.
415
	drawBox( 20 )
416
	printCentered( 6, "PRINT?" )
417
	
418
	-- Get a 'YES' or 'NO' from the user with a simple menu.
419
	while not bPrinted do
420
		drawSelections()
421
		local sEvent, nKey = os.pullEvent( "key" )
422
		
423
		if nKey == 28 or nKey == 205 or nKey == 203 then
424
			handleKeyPress( nKey )
425
		end
426
	end
427
	
428
	return true
429
end
430
431
-- Gets the title for the page to be printed.
432
function getPageTitle()
433
	drawBox( 20 )
434
	printCentered( 6, "Page Title:" )
435
	term.setCursorPos( nScreenWidth/2 - 9, 9 )
436
		
437
	local sPageTitle = tostring( limitRead( 18 ) )
438
	if not sPageTitle or string.len( sPageTitle ) == 0 then
439
		sPageTitle = "Default_PageTitle"
440
	end
441
	
442
	return sPageTitle
443
end
444
	
445
-- This screen will prompt the user for a yes or no answer.
446
function drawAndGetPrintConfirmationScreen()
447
	getConfirmation()
448
end
449
------------
450
451
initializePrinterAndProgram()
452
tDocument = readLines()
453
drawAndGetPrintConfirmationScreen()