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() |