#!/usr/bin/env python """ TkInter Block ASCII (codepage 437 aka PC Dos aka ASCII art) file viewer using internal bitmap fonts Author: Evan Eveland """ # TO DO: #Image data infoImage = '''R0lGODlhHgAVAOfrAAABAAACAAIFAQQHAg4TFQ8UFhscGjU5Ozc7PTo+QDlAR0dMcExTWk9UVk1V XFFWWE9TeEtVfkxWf1RVdE1XgFBYdU9YglFahFFdgVNchlRdh1ZfiVdgilZihltghVxhhlRkjVFk mVhkiFxkgl5iiF9jiVpol11pjVtpmWdrbl5qjmxua2FtkVtuo1twn2BwmV5zoll1qGByp2l1mWp2 mmh1pWx4nGV6qW15nXB4pG97n2h9rHB8oG9+nHB/nXGAnm9/qWuAsGyBsXGBq22CsnmAoHWBpnuC on6FjXyDo3GGtnqJj3CIsX6FpXeHsoaIhYKJkXSJuXeKroCHp3+OrXyPs4GNsoWMrX6OuX6RtYCQ u4OSsYiTrImUrYaVtIOWu4iYxJKaooebv4icwJKau5CbwZKdt4ufw5Wdvp6jpZSkw5inxqSprKmn q56qxKGsxqW1yKy0yaq10LO+2bXA27vAz7nB1rzE2bzI1rvK3rbO4L3M4MbK2r/P4sLS5rDZ9cHV 4srS28fT4bvX77Xa8MjU4rbb8c7S4sTY5M/T477a8tDU5MvX5dHV5bre9Lvf9b/f79DZ4c7a6Mvb 7sPf99TZ6dPb5Mff8cTg+Mjg8sXh+cnh89Le7Nbe58ri9NPf7cfj+8vj9c/j78zk9tni6tHl8c7m +crn/9Lm8uDh69jk89vk7NPn9OLi7dTo9dDp+9rn9dLq/N/n8NPr/dzo9t3p99vr8uDp8enm6+Tp 7Njt+eHq8ufo8t/r+eLr893u9OPs9OTt9e3r7+Xu993x/uDx+Ozs9+fv+Ojw+evw8+Pz+u7v+ezx 9O3y9erz++7z9uv0/On29+z1/e/19/D2+Ov5+en6//L3+ez6+/P4++77/PT5/O/8/fr3/PX6/fv4 /fb7/vn7+Pr8+fL///f9//37//v9+vj+//n///z/+/7//P////////////////////////////// /////////////////////////////////////////////////////yH5BAEKAP8ALAAAAAAeABUA AAj+AP8JHEgQDBYlQWK0kLGDiBMtBCNK/CdEyRk7lXgJE6cu3DJcleaUAVJjIsEoahp1O3dO3bly 5siF8+Ztm7dy1xKhyTHxxppc5dSpg3nOHDhv4bpRe/asmTNo2bKpImOCIBE6vFgGPScOZrduaQCk CPYrGLBfyIopuyUHhUAxX1YJnavuW7Zu4aYBSJPr1i1ZtGrpgkVMWqUrNJyMaZStnNYATwwEYJMN gGVfhxAASBColKhRsVTxAQIjCzO65wKkSMYmwLRuAJzxagDlExIGnihBUjSqlw4TVrbRLQdAWFIA zJYFOOaLACdWiAh80gTpz6hgRlxQETb3HDgA4YT+MQvwbFqAYLkArLIlCkCoTI4UheplY4iXQ9c6 hvsGwNu1ZwEs8wwAzDlHCyMEbHIJIZRMwgcO/3hBRSp14RXAV90EkM0yAABjzANhiLIEA5r8MUgs fjRRgkAvxJGLOttso+E1GU4zXi69BHIAAAroQYkij0zyRgYEcWAGL+AkFc41zUzTVDC6uPLZKY88 Ysosk1whwURFpDJTNtUoo0wxv/ziSiyjjDJLL8TcMYUIC5jUAx/NpKMNN83kEow00jxjCyd4xPED CRZAYJJAPeARjTjZ1PGDByBYIEEEGmywwQcVHEoQDpFsE0kXM2gqqkBTdAHHDxiIMKqoHYhQwooH q8Yqq6YBAQA7 ''' # ----------------------------------------------------------------------------- # -- Imports # ----------------------------------------------------------------------------- from Tkinter import * from tkFileDialog import * from tkMessageBox import * from tkColorChooser import * import sys, os, string, time, copy # ----------------------------------------------------------------------------- # -- Util Fxns # ----------------------------------------------------------------------------- def getInverse(color): hexColor = color.lstrip('#') hexInverse = hex(int(hexColor,16) ^ 0xffffff).lstrip('0x').zfill(6) retVal = '#' + hexInverse return retVal class bmpFont: def __init__(self): self.fontWidth = 0 self.fontHeight = 0 self.glyphs = [] self.fillFont() return def chgColor(self, color, sColor=None): for g in self.glyphs: g.config(foreground=color) # now change color of special chars if provided if sColor != None: for n in range(32)+range(127,256): self.glyphs[n].config(foreground=sColor) return def chgBackColor(self, color): for g in self.glyphs: g.config(background=color) return def fillFont(self): """ Populate our glyphs creating bitmap images on the fly from the Photoimage passed in imgData. imgData needs to be a base64 string of a gif. The .gif image needs to be a 16x16 grid in ASCII order starting at 0. No padding between glyphs, so glyph width is imgData width / 16. Glyph height is imgData height / 16. White is transparent, any other is pixel data. """ self.glyphs = [] tmpPic = PhotoImage(data=self.fontData() ) glyphWidth = tmpPic.width() / 16 glyphHeight = tmpPic.height() / 16 yOffset = 0 for row in range(16): xOffset = 0 for col in range(16): #print str(row) + "x"+ str(col) tmpBmp = self.chopPic(tmpPic, xOffset, yOffset, glyphWidth, glyphHeight) self.glyphs.append(tmpBmp) xOffset = xOffset + glyphWidth yOffset = yOffset + glyphHeight self.fontWidth = glyphWidth self.fontHeight = glyphHeight return def chopPic(self, pImg, x0,y0,w,h): """ Given a TkInter photoimage pImg, x,y,w,h as ints, return a string representation of a Tkinter bitmapImage created from the data in pImg from (x,y) to (x+w, y+h) that has dimension w,h. NOTE: pImg must use white (255, 255, 255) for transparent, any other for foreground color. """ # first add the first bits... lcX11Data = """ #define im_width """ lcX11Data = lcX11Data + str(w) + """ #define im_height """ lcX11Data = lcX11Data + str(h) + """ static char im_bits[] = { """ # now add the actual data in hex strings lnCounter = 0 for y in range(h): # Now read across the row for bytes in range(0,w,8): lcBinStr = '' if bytes + 8 > w: xEnd = w else: xEnd = bytes + 8 for x in range(xEnd-1, bytes-1,-1): if pImg.get(x0 + x, y0 + y ) == '255 255 255': lcBinStr = lcBinStr + '0' else: lcBinStr = lcBinStr + '1' lcHexStr = str(hex(int(lcBinStr,2))) lcX11Data = lcX11Data + lcHexStr lcX11Data = lcX11Data + """,""" lnCounter = lnCounter + 1 # Add the last chunk lcX11Data = lcX11Data + """ }; """ # create a bitmap image using the data lcRetVal = BitmapImage(data= lcX11Data) #print lcX11Data return lcRetVal def fontData(self): return '''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 OixLkz8N6gAUAAA7''' # ----------------------------------------------------------------------------- # -- statBar Class # -- class statBar(Frame): def __init__(self, master): Frame.__init__(self, master) self.fNameTxt = Label(self, bd=1, anchor=W) self.fNameTxt.pack(side=LEFT, fill=X) self.rightFrame = Frame(self) self.rightFrame.pack(side=RIGHT) self.fDateTxt = Label(self.rightFrame, bd=1, relief=SUNKEN) self.fDateTxt.grid(column=1,row=1,padx=1,ipadx=2) self.fSizeTxt = Label(self.rightFrame, bd=1, relief=SUNKEN) self.fSizeTxt.grid(column=2,row=1,padx=1,ipadx=2) self.fDimsTxt = Label(self.rightFrame, bd=1, relief=SUNKEN) self.fDimsTxt.grid(column=3,row=1,padx=1,ipadx=2) return def setName(self, nStr): self.fNameTxt.config(text=nStr) self.fNameTxt.update_idletasks() return def clearName(self): self.setName("") return def setDate(self, dStr): self.fDateTxt.config(text=dStr) self.fDateTxt.update_idletasks() return def clearDate(self): self.setDate(" ") return def setSize(self, s): sStr = self.addCommas(s) self.sizeLen = len(sStr) if self.sizeLen == 0: sStr = " " self.fSizeTxt.config(text=sStr) self.fSizeTxt.update_idletasks() return def clearSize(self): self.setSize(" ") return def setDims(self, dims): if dims == None: dimStr = " " else: dimStr = str(dims[0]) + "x" + str(dims[1]) self.fDimsTxt.config(text=dimStr) self.fDimsTxt.update_idletasks() return def clearDims(self): self.setDims(None) return def addCommas(self, s): lcRetVal = '' if s != None: if type(s) != 'str': s = str(s) s= s.strip() count = 0 for i in range(len(s), 0, -1): count += 1 lcRetVal = lcRetVal + s[i - 1] if count % 3 == 0: lcRetVal = lcRetVal + "," return lcRetVal[::-1] def updateSize(self, formWidth): return # ----------------------------------------------------------------------------- # -- tkNFO Class # -- class tkNFO(Frame): def __init__(self, master=None): Frame.__init__(self, master) self.textArray = [] self.canvasArray = [] self.bFont=bmpFont() self.rows = 0 self.cols = 0 self.fName = '' # now define some of the user prefs self.stripEOL = True self.foreColor = '#000000' self.backColor = '#FFFFFF' self.specialColor = '#DDDDDD' self.currDir = os.getcwd() # set up the grid layout mgr self.grid(sticky=N+S+E+W) self.rowconfigure(0, weight=1) self.columnconfigure(0, weight=1) top=self.winfo_toplevel() top.rowconfigure(0, weight=1) top.columnconfigure(0, weight=1) self.createWidgets() self.readPref() return def createWidgets(self): self.addMenu() # -- Read the bitmapped font into an array self.createFonts() # -- add a frame to hold the textbox and it's scrollbars self.textBoxFrame = Frame(self, bd=2, relief=SUNKEN) self.textBoxFrame.rowconfigure(0, weight=1) self.textBoxFrame.columnconfigure(0, weight=1) # -- add a scrollbars for the textbox self.xScrollbar = Scrollbar(self.textBoxFrame,orient=HORIZONTAL) self.yScrollbar = Scrollbar(self.textBoxFrame,orient=VERTICAL) self.xScrollbar.grid(row=1, column=0, sticky=E+W) self.yScrollbar.grid(row=0, column=1, sticky=N+S) # -- Now add the canvas self.textBox = Canvas(self.textBoxFrame) self.textBox.grid(row=0, column=0, sticky=N+S+E+W) # -- bind the textbox to the scrollbar self.yScrollbar.config(command=self.textBox.yview) self.xScrollbar.config(command=self.textBox.xview) self.textBox.config(yscrollcommand=self.yScrollbar.set) self.textBox.config(xscrollcommand=self.xScrollbar.set) self.textBox.config(background=self.backColor) # -- bind mouse events self.textBox.bind ( "", self.doCanvasClick) self.textBox.bind ( "", lambda event: event.widget.yview_scroll(-1, UNITS)) self.textBox.bind ( "", lambda event: event.widget.yview_scroll(1, UNITS)) # the following is used for windows... however it seems to crash currently # fix detailed available at: # http://jira.python.atlassian.com/browse/PY-4740 # uncomment at your own risk! self.textBox.bind ( "",self.doWheelWin ) self.textBoxFrame.pack(side=TOP,fill=BOTH) # -- add a statusbar at the bottom self.sBar = statBar(self) self.sBar.pack(side=BOTTOM, fill=X) self.updStatBar() self.textBox.focus_set() return def addMenu(self): self.menu = Menu(self) self.master.config(menu=self.menu) self.fileMenu = Menu(self.menu) self.menu.add_cascade(label="File", menu=self.fileMenu) self.fileMenu.add_command(label="Open", command=self.doOpen) self.fileMenu.add_command(label="Close", command=self.doClose) self.fileMenu.add_separator() self.fileMenu.add_command(label="Exit", command=self.quit ) self.editMenu = Menu(self.menu) self.menu.add_cascade(label="Edit", menu=self.editMenu) #self.editMenu.add_command(label="Copy", command=self.doCopy) #self.editMenu.add_command(label="Select All", command=self.doSelAll) #self.editMenu.add_separator() self.editMenu.add_command(label="Change Text Color", command=self.doForeground) self.editMenu.add_command(label="Change Background Color", command=self.doBackground) self.editMenu.add_command(label="Change Special Text Color", command=self.doSpecialColor) self.helpMenu = Menu (self.menu) self.menu.add_cascade(label="Help", menu=self.helpMenu) self.helpMenu.add_command(label="About", command=self.doAbout) return def doWheelWin(self, event): if event.delta > 0: event.widget.yview_scroll(-1, UNITS) else: event.widget.yview_scroll(1, UNITS) return def doCanvasClick(self, event): x = self.textBox.canvasx(event.x) y = self.textBox.canvasx(event.y) return def createFonts(self): self.bFont.fillFont() self.bFont.chgColor(self.foreColor, self.specialColor) return def doOpen(self): lcFileName = askopenfilename(title="Open File", filetypes=[('Nfo files','*.nfo *.diz'),('All Files','*.*')], initialdir=self.currDir) if lcFileName != None and lcFileName.strip() != "": self.currDir = os.path.split(lcFileName)[0] self.writePref() self.loadFile(lcFileName) return def doClose(self): self.clearCanvas() self.textArray = [] self.canvasArray = [] self.rows = 0 self.cols = 0 self.fName = '' self.resizeText() self.updStatBar() return def doForeground(self): fColor = askcolor(self.foreColor)[1] if fColor != None: if self.foreColor != fColor.__str__(): self.foreColor = fColor.__str__() self.bFont.chgColor(self.foreColor,self.specialColor) self.writePref() return def doBackground(self): bColor = askcolor(self.backColor)[1] if bColor != None: if self.backColor != bColor.__str__(): self.backColor = bColor.__str__() self.textBox.config(background = self.backColor) self.writePref() return def doSpecialColor(self): sColor = askcolor(self.specialColor)[1] if sColor != None: if self.specialColor != sColor.__str__(): self.specialColor = sColor.__str__() self.bFont.chgColor(self.foreColor,self.specialColor) self.writePref() return def writePref(self): homeDir = os.path.expanduser('~') configFile = os.path.join(homeDir , '.tkNfo') if os.path.isfile(configFile): os.remove(configFile) print self.currDir saveout = sys.stdout fout = open(configFile, 'w') sys.stdout = fout print 'backColor=' + self.backColor print 'foreColor=' + self.foreColor print 'specialColor=' + self.specialColor print 'lastDir=' + self.currDir sys.stdout = saveout fout.close() return def readPref(self): homeDir = os.path.expanduser('~') configFile = os.path.join(homeDir , '.tkNfo') if os.path.exists(configFile ): for line in open(configFile , 'r'): line = line.strip() try: var , value = line.split('=') if (var.strip() == 'backColor'): if self.backColor != value: self.backColor = value self.textBox.config(background = self.backColor) elif (var.strip() == 'foreColor'): if self.foreColor != value: self.foreColor = value self.bFont.chgColor(self.foreColor,self.specialColor) elif (var.strip() == 'specialColor'): if self.specialColor != value: self.specialColor = value self.bFont.chgColor(self.foreColor,self.specialColor) elif (var.strip() == 'lastDir'): if self.currDir != value: self.currDir = value except Exception: print line return def doAbout(self): result = nfoAbout(self) return def doSelAll(self): return def doCopy(self): return def loadFile(self, fileName): try: cols = 0 rows = 0 tmpArray = [] for line in open(fileName, 'r'): #drop those pesky eol chars if self.stripEOL == True: line = line.rstrip() col = [] itr = 0 for chr in line: col.append(ord(chr)) itr = itr + 1 if (itr > cols): cols = itr tmpArray.append(col) rows = rows + 1 self.textArray = tmpArray self.rows = rows self.cols = cols self.fName = fileName except IOError, (errno, message): raise SystemExit(message) self.resizeText() self.clearCanvas() self.renderText() return def updStatBar(self): if os.path.exists(self.fName): self.sBar.setName(os.path.abspath(self.fName) ) self.sBar.setDate(time.ctime(os.stat(self.fName).st_mtime) ) self.sBar.setSize(os.stat(self.fName).st_size) self.sBar.setDims( (self.cols,self.rows) ) else: self.sBar.clearName() self.sBar.clearDate() self.sBar.clearSize() self.sBar.clearDims() self.sBar.updateSize(self.cols) return def resizeText(self): colWidth = self.bFont.fontWidth rowHeight = self.bFont.fontHeight width = (self.cols + 1) * colWidth height = (self.rows + 1) * rowHeight # limit canvas to 80% of full screen res, min of 300x200 self.textBox.config(scrollregion=(0,0,width,height) ) if (width > (self.winfo_screenwidth() * 0.8 ) ): width = self.winfo_screenwidth() * 0.8 elif (width < 300): width = 300 if (height > (self.winfo_screenheight() * 0.8 ) ): height = self.winfo_screenheight() * 0.8 elif (height < 200): height = 200 self.textBox.config(width=width) self.textBox.config(height=height) return def clearCanvas(self): for rows in self.canvasArray: for cols in rows: self.textBox.delete(cols) return def renderText(self): fontWidth = self.bFont.fontWidth fontHeight = self.bFont.fontHeight yOffset = fontHeight tmpArray = [] for row in self.textArray: tmpCol = [] xOffset = fontWidth for col in row: i = self.textBox.create_image(xOffset,yOffset, image=self.bFont.glyphs[col]) tmpCol.append(i) xOffset = xOffset + fontWidth tmpArray.append(tmpCol) yOffset = yOffset + fontHeight self.canvasArray = tmpArray self.updStatBar() return # ----------------------------------------------------------------------------- # -- nfoAbout class # -- class nfoAbout(Toplevel): def __init__(self, parent, title = None): Toplevel.__init__(self,parent) self.transient(parent) if title: self.title(title) self.parent = parent self.result = None body = Frame(self) self.createWidgets() self.update_idletasks() self.protocol("WM_DELETE_WINDOW", self.cancel) startx = parent.winfo_rootx()+int(parent.winfo_width() / 2)-int(self.winfo_width() / 2) starty = parent.winfo_rooty()+int(parent.winfo_height() / 2)-int(self.winfo_height() / 2) self.geometry("+%d+%d" % (startx,starty) ) self.resizable(0, 0) self.wait_window(self) return def createWidgets(self): box = Frame(self) self.infoPic = PhotoImage(data=infoImage ) nfoButton = Label(box, image=self.infoPic, height=30, width=30) nfoLabel = Label(box, text="tkNFO") nfoDesc = Label(box, text="a simple .nfo viewer") nfoAuthor = Label(box, text="Evan Eveland, 2006") okButton = Button(box, text="OK", width=15, command=self.cancel) nfoButton.grid(row=0,column=0,rowspan=3, padx=5,pady=5, sticky=N+W) nfoLabel.grid(row=0,column=1, sticky=W,padx=5) nfoDesc.grid(row=1, column=1, sticky=W, padx=5) nfoAuthor.grid(row=2, column=0, columnspan=2, pady=5, sticky=W) okButton.grid(row=3, column=0, columnspan=2,padx=2,pady=5, sticky=S) box.pack() box.focus_set() return def cancel(self, event=None): # put focus back to the parent window self.parent.focus_set() self.destroy() return #---------------------------------------------- if __name__ == '__main__': params = len(sys.argv) if params > 1: lcFilename = sys.argv[1] if os.path.exists(lcFilename) == False : raise SystemExit("File not Found") else: lcFilename = '' app = tkNFO() if lcFilename <> '': app.loadFile(lcFilename) app.master.title("tkNFO") app.master.resizable(0, 0) app.mainloop()