Rot13 app - How to tidy up code? I made a program that lets the user input text into a text box.
The user can choose a number to rotate each alphabetical character by that number,
and the output box will diplay the converted text.
Here is how it runs:

Among the code is
#            if event.key == pygame.K_RETURN:
#                print('\n'.join([''.join(row) for row in rot_box.text])+'\n--------------------')

If you remove the hashtags, the converted text will be printed whenever you press Enter.
Here is my entire code:
import pygame
pygame.font.init()

wn = pygame.display.set_mode((600, 600))
font = pygame.font.Font(None, 32)

class TextBox():
    def __init__(self, x, y, w, h, title='Text Box', color=(0, 0, 0), default=''):
        self.input_box = pygame.Rect(x, y, w, h)
        self.w = w
        self.h = h
        self.color_inactive = color
        self.color_active = pygame.Color('purple')
        self.color = self.color_inactive
        self.default = default
        self.text = ['']
        self.active = False
        self.title = title

    def draw(self):
        title = font.render(self.title, True, self.color)
        wn.blit(title, (self.input_box.x+5, self.input_box.y-self.h))
        txts = [font.render(''.join(t), True, self.color) for t in self.text]
        width = max(self.w, max(txts, key=lambda x:x.get_width()).get_width()+10)
        height = self.h * len(txts)
        self.input_box.w = width
        self.input_box.h = height
        if len(txts) == 1 and txts[0].get_width() == 1:
            wn.blit(font.render(self.default, True, self.color), (self.input_box.x+5, self.input_box.y+5))
        else:
            for i, txt in enumerate(txts):
                wn.blit(txt, (self.input_box.x+5, self.input_box.y+5+i*self.h))
        pygame.draw.rect(wn, self.color, self.input_box, 2)

    def check_status(self, pos):
        if self.input_box.collidepoint(pos):
            self.active = not self.active
        else:
            self.active = False
        self.color = self.color_active if self.active else self.color_inactive

    def type(self, event):
        if self.active:
            if event.key == pygame.K_RETURN:
                self.text.append('')
            elif event.key == pygame.K_BACKSPACE:
                if self.text[-1]:
                    self.text[-1] = self.text[-1][:-1]
                else:
                    if len(self.text) &gt; 1:
                        self.text = self.text[:-1]
            else:
                self.text[-1] += event.unicode

def rot(alp, num):
    while num &gt;= 26:
        num -= 26
    if alp in 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ':
        n = ord(alp) + num
        if n &gt; 122 or 97 &gt; n &gt; 90:
            n -= 26
        alp = chr(n)
    return alp


box = TextBox(110, 60, 140, 32, 'Input Text')
rot_num = TextBox(10, 60, 50, 32, 'Rot', default='0')
rot_box = TextBox(110, 300, 140, 32, 'Output Text')

while True:
    rt = int(rot_num.text[0]) if rot_num.text[0] else 0
    rot_box.text = [[rot(char, rt) for char in row] for row in box.text]
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
        if event.type == pygame.MOUSEBUTTONDOWN:
            box.check_status(event.pos)
            rot_num.check_status(event.pos)
        if event.type == pygame.KEYDOWN:
            box.type(event)
            if (event.unicode.isdigit() or event.key == pygame.K_BACKSPACE) and len(rot_num.text[0]) &lt; 6 or event.key == pygame.K_BACKSPACE:
                rot_num.type(event)
#            if event.key == pygame.K_RETURN:
#                print('\n'.join([''.join(row) for row in rot_box.text])+'\n--------------------')
                
    wn.fill((255, 255, 200))
    box.draw()
    rot_num.draw()
    rot_box.draw()
    pygame.display.flip()

Can you show me how to clean up my messy code?
Can also you point me at the parts of my code that should've been in a class or function, and the parts that shouldn't have been?
Your ROT algorithm is slightly wrong. The real ROT returns The alphabet rotated in the corresponding case. But in yours, even if you give Uppercase(TUVWXYZ), it returns lowercase for large rotations. That is not exact ROT.
This can be seen from this screenshot 
This may be helpful:  https://www.geeksforgeeks.org/rot13-cipher/. Here instead of chr() and ord() Dictionaries are used which is very efficient and less error prone.