1ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh# changes by dscherer@cmu.edu 2ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh# - IOBinding.open() replaces the current window with the opened file, 3ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh# if the current window is both unmodified and unnamed 4ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh# - IOBinding.loadfile() interprets Windows, UNIX, and Macintosh 5ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh# end-of-line conventions, instead of relying on the standard library, 6ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh# which will only understand the local convention. 7ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 8ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehimport os 9ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehimport types 10ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehimport pipes 11ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehimport sys 12ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehimport codecs 13ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehimport tempfile 14ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehimport tkFileDialog 15ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehimport tkMessageBox 16ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehimport re 17ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehfrom Tkinter import * 18ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehfrom SimpleDialog import SimpleDialog 19ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 20ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehfrom idlelib.configHandler import idleConf 21ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 22ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehtry: 23ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh from codecs import BOM_UTF8 24ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehexcept ImportError: 25ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # only available since Python 2.3 26ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh BOM_UTF8 = '\xef\xbb\xbf' 27ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 28ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh# Try setting the locale, so that we can find out 29ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh# what encoding to use 30ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehtry: 31ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh import locale 32ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh locale.setlocale(locale.LC_CTYPE, "") 33ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehexcept (ImportError, locale.Error): 34ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh pass 35ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 36ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh# Encoding for file names 37ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehfilesystemencoding = sys.getfilesystemencoding() 38ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 39ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehencoding = "ascii" 40ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehif sys.platform == 'win32': 41ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # On Windows, we could use "mbcs". However, to give the user 42ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # a portable encoding name, we need to find the code page 43ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh try: 44ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh encoding = locale.getdefaultlocale()[1] 45ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh codecs.lookup(encoding) 46ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh except LookupError: 47ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh pass 48ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehelse: 49ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh try: 50ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Different things can fail here: the locale module may not be 51ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # loaded, it may not offer nl_langinfo, or CODESET, or the 52ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # resulting codeset may be unknown to Python. We ignore all 53ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # these problems, falling back to ASCII 54ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh encoding = locale.nl_langinfo(locale.CODESET) 55ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if encoding is None or encoding is '': 56ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # situation occurs on Mac OS X 57ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh encoding = 'ascii' 58ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh codecs.lookup(encoding) 59ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh except (NameError, AttributeError, LookupError): 60ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Try getdefaultlocale well: it parses environment variables, 61ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # which may give a clue. Unfortunately, getdefaultlocale has 62ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # bugs that can cause ValueError. 63ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh try: 64ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh encoding = locale.getdefaultlocale()[1] 65ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if encoding is None or encoding is '': 66ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # situation occurs on Mac OS X 67ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh encoding = 'ascii' 68ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh codecs.lookup(encoding) 69ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh except (ValueError, LookupError): 70ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh pass 71ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 72ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehencoding = encoding.lower() 73ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 74ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehcoding_re = re.compile("coding[:=]\s*([-\w_.]+)") 75ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 76ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehclass EncodingMessage(SimpleDialog): 77ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh "Inform user that an encoding declaration is needed." 78ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def __init__(self, master, enc): 79ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.should_edit = False 80ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 81ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.root = top = Toplevel(master) 82ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh top.bind("<Return>", self.return_event) 83ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh top.bind("<Escape>", self.do_ok) 84ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh top.protocol("WM_DELETE_WINDOW", self.wm_delete_window) 85ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh top.wm_title("I/O Warning") 86ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh top.wm_iconname("I/O Warning") 87ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.top = top 88ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 89ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh l1 = Label(top, 90ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text="Non-ASCII found, yet no encoding declared. Add a line like") 91ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh l1.pack(side=TOP, anchor=W) 92ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh l2 = Entry(top, font="courier") 93ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh l2.insert(0, "# -*- coding: %s -*-" % enc) 94ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # For some reason, the text is not selectable anymore if the 95ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # widget is disabled. 96ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # l2['state'] = DISABLED 97ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh l2.pack(side=TOP, anchor = W, fill=X) 98ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh l3 = Label(top, text="to your file\n" 99ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh "Choose OK to save this file as %s\n" 100ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh "Edit your general options to silence this warning" % enc) 101ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh l3.pack(side=TOP, anchor = W) 102ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 103ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh buttons = Frame(top) 104ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh buttons.pack(side=TOP, fill=X) 105ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Both return and cancel mean the same thing: do nothing 106ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.default = self.cancel = 0 107ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh b1 = Button(buttons, text="Ok", default="active", 108ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh command=self.do_ok) 109ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh b1.pack(side=LEFT, fill=BOTH, expand=1) 110ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh b2 = Button(buttons, text="Edit my file", 111ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh command=self.do_edit) 112ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh b2.pack(side=LEFT, fill=BOTH, expand=1) 113ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 114ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self._set_transient(master) 115ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 116ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def do_ok(self): 117ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.done(0) 118ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 119ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def do_edit(self): 120ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.done(1) 121ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 122ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehdef coding_spec(str): 123ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh """Return the encoding declaration according to PEP 263. 124ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 125ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh Raise LookupError if the encoding is declared but unknown. 126ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh """ 127ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Only consider the first two lines 128ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh str = str.split("\n")[:2] 129ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh str = "\n".join(str) 130ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 131ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh match = coding_re.search(str) 132ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if not match: 133ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return None 134ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh name = match.group(1) 135ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Check whether the encoding is known 136ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh import codecs 137ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh try: 138ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh codecs.lookup(name) 139ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh except LookupError: 140ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # The standard encoding error does not indicate the encoding 141ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh raise LookupError, "Unknown encoding "+name 142ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return name 143ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 144ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 145ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehclass IOBinding: 146ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 147ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def __init__(self, editwin): 148ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.editwin = editwin 149ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.text = editwin.text 150ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.__id_open = self.text.bind("<<open-window-from-file>>", self.open) 151ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.__id_save = self.text.bind("<<save-window>>", self.save) 152ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.__id_saveas = self.text.bind("<<save-window-as-file>>", 153ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.save_as) 154ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.__id_savecopy = self.text.bind("<<save-copy-of-window-as-file>>", 155ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.save_a_copy) 156ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.fileencoding = None 157ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.__id_print = self.text.bind("<<print-window>>", self.print_window) 158ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 159ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def close(self): 160ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Undo command bindings 161ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.text.unbind("<<open-window-from-file>>", self.__id_open) 162ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.text.unbind("<<save-window>>", self.__id_save) 163ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.text.unbind("<<save-window-as-file>>",self.__id_saveas) 164ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.text.unbind("<<save-copy-of-window-as-file>>", self.__id_savecopy) 165ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.text.unbind("<<print-window>>", self.__id_print) 166ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Break cycles 167ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.editwin = None 168ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.text = None 169ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.filename_change_hook = None 170ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 171ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def get_saved(self): 172ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return self.editwin.get_saved() 173ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 174ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def set_saved(self, flag): 175ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.editwin.set_saved(flag) 176ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 177ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def reset_undo(self): 178ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.editwin.reset_undo() 179ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 180ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh filename_change_hook = None 181ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 182ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def set_filename_change_hook(self, hook): 183ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.filename_change_hook = hook 184ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 185ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh filename = None 186ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh dirname = None 187ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 188ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def set_filename(self, filename): 189ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if filename and os.path.isdir(filename): 190ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.filename = None 191ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.dirname = filename 192ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh else: 193ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.filename = filename 194ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.dirname = None 195ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.set_saved(1) 196ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if self.filename_change_hook: 197ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.filename_change_hook() 198ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 199ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def open(self, event=None, editFile=None): 200ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh flist = self.editwin.flist 201ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Save in case parent window is closed (ie, during askopenfile()). 202ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if flist: 203ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if not editFile: 204ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh filename = self.askopenfile() 205ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh else: 206ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh filename=editFile 207ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if filename: 208ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # If editFile is valid and already open, flist.open will 209ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # shift focus to its existing window. 210ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # If the current window exists and is a fresh unnamed, 211ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # unmodified editor window (not an interpreter shell), 212ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # pass self.loadfile to flist.open so it will load the file 213ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # in the current window (if the file is not already open) 214ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # instead of a new window. 215ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if (self.editwin and 216ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh not getattr(self.editwin, 'interp', None) and 217ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh not self.filename and 218ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.get_saved()): 219ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh flist.open(filename, self.loadfile) 220ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh else: 221ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh flist.open(filename) 222ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh else: 223ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if self.text: 224ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.text.focus_set() 225ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return "break" 226ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 227ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Code for use outside IDLE: 228ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if self.get_saved(): 229ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh reply = self.maybesave() 230ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if reply == "cancel": 231ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.text.focus_set() 232ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return "break" 233ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if not editFile: 234ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh filename = self.askopenfile() 235ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh else: 236ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh filename=editFile 237ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if filename: 238ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.loadfile(filename) 239ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh else: 240ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.text.focus_set() 241ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return "break" 242ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 243ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh eol = r"(\r\n)|\n|\r" # \r\n (Windows), \n (UNIX), or \r (Mac) 244ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh eol_re = re.compile(eol) 245ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh eol_convention = os.linesep # Default 246ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 247ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def loadfile(self, filename): 248ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh try: 249ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # open the file in binary mode so that we can handle 250ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # end-of-line convention ourselves. 251ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh f = open(filename,'rb') 252ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh chars = f.read() 253ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh f.close() 254ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh except IOError, msg: 255ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh tkMessageBox.showerror("I/O Error", str(msg), master=self.text) 256ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return False 257ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 258ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh chars = self.decode(chars) 259ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # We now convert all end-of-lines to '\n's 260ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh firsteol = self.eol_re.search(chars) 261ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if firsteol: 262ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.eol_convention = firsteol.group(0) 263ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if isinstance(self.eol_convention, unicode): 264ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Make sure it is an ASCII string 265ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.eol_convention = self.eol_convention.encode("ascii") 266ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh chars = self.eol_re.sub(r"\n", chars) 267ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 268ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.text.delete("1.0", "end") 269ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.set_filename(None) 270ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.text.insert("1.0", chars) 271ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.reset_undo() 272ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.set_filename(filename) 273ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.text.mark_set("insert", "1.0") 274ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.text.yview("insert") 275ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.updaterecentfileslist(filename) 276ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return True 277ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 278ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def decode(self, chars): 279ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh """Create a Unicode string 280ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 281ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh If that fails, let Tcl try its best 282ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh """ 283ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Check presence of a UTF-8 signature first 284ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if chars.startswith(BOM_UTF8): 285ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh try: 286ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh chars = chars[3:].decode("utf-8") 287ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh except UnicodeError: 288ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # has UTF-8 signature, but fails to decode... 289ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return chars 290ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh else: 291ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Indicates that this file originally had a BOM 292ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.fileencoding = BOM_UTF8 293ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return chars 294ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Next look for coding specification 295ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh try: 296ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh enc = coding_spec(chars) 297ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh except LookupError, name: 298ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh tkMessageBox.showerror( 299ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh title="Error loading the file", 300ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh message="The encoding '%s' is not known to this Python "\ 301ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh "installation. The file may not display correctly" % name, 302ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh master = self.text) 303ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh enc = None 304ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if enc: 305ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh try: 306ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return unicode(chars, enc) 307ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh except UnicodeError: 308ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh pass 309ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # If it is ASCII, we need not to record anything 310ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh try: 311ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return unicode(chars, 'ascii') 312ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh except UnicodeError: 313ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh pass 314ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Finally, try the locale's encoding. This is deprecated; 315ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # the user should declare a non-ASCII encoding 316ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh try: 317ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh chars = unicode(chars, encoding) 318ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.fileencoding = encoding 319ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh except UnicodeError: 320ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh pass 321ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return chars 322ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 323ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def maybesave(self): 324ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if self.get_saved(): 325ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return "yes" 326ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh message = "Do you want to save %s before closing?" % ( 327ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.filename or "this untitled document") 328ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh confirm = tkMessageBox.askyesnocancel( 329ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh title="Save On Close", 330ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh message=message, 331ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh default=tkMessageBox.YES, 332ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh master=self.text) 333ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if confirm: 334ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh reply = "yes" 335ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.save(None) 336ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if not self.get_saved(): 337ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh reply = "cancel" 338ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh elif confirm is None: 339ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh reply = "cancel" 340ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh else: 341ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh reply = "no" 342ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.text.focus_set() 343ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return reply 344ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 345ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def save(self, event): 346ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if not self.filename: 347ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.save_as(event) 348ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh else: 349ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if self.writefile(self.filename): 350ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.set_saved(True) 351ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh try: 352ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.editwin.store_file_breaks() 353ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh except AttributeError: # may be a PyShell 354ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh pass 355ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.text.focus_set() 356ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return "break" 357ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 358ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def save_as(self, event): 359ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh filename = self.asksavefile() 360ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if filename: 361ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if self.writefile(filename): 362ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.set_filename(filename) 363ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.set_saved(1) 364ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh try: 365ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.editwin.store_file_breaks() 366ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh except AttributeError: 367ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh pass 368ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.text.focus_set() 369ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.updaterecentfileslist(filename) 370ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return "break" 371ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 372ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def save_a_copy(self, event): 373ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh filename = self.asksavefile() 374ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if filename: 375ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.writefile(filename) 376ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.text.focus_set() 377ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.updaterecentfileslist(filename) 378ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return "break" 379ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 380ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def writefile(self, filename): 381ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.fixlastline() 382ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh chars = self.encode(self.text.get("1.0", "end-1c")) 383ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if self.eol_convention != "\n": 384ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh chars = chars.replace("\n", self.eol_convention) 385ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh try: 386ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh f = open(filename, "wb") 387ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh f.write(chars) 388ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh f.flush() 389ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh f.close() 390ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return True 391ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh except IOError, msg: 392ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh tkMessageBox.showerror("I/O Error", str(msg), 393ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh master=self.text) 394ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return False 395ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 396ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def encode(self, chars): 397ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if isinstance(chars, types.StringType): 398ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # This is either plain ASCII, or Tk was returning mixed-encoding 399ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # text to us. Don't try to guess further. 400ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return chars 401ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # See whether there is anything non-ASCII in it. 402ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # If not, no need to figure out the encoding. 403ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh try: 404ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return chars.encode('ascii') 405ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh except UnicodeError: 406ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh pass 407ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # If there is an encoding declared, try this first. 408ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh try: 409ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh enc = coding_spec(chars) 410ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh failed = None 411ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh except LookupError, msg: 412ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh failed = msg 413ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh enc = None 414ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if enc: 415ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh try: 416ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return chars.encode(enc) 417ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh except UnicodeError: 418ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh failed = "Invalid encoding '%s'" % enc 419ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if failed: 420ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh tkMessageBox.showerror( 421ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh "I/O Error", 422ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh "%s. Saving as UTF-8" % failed, 423ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh master = self.text) 424ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # If there was a UTF-8 signature, use that. This should not fail 425ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if self.fileencoding == BOM_UTF8 or failed: 426ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return BOM_UTF8 + chars.encode("utf-8") 427ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Try the original file encoding next, if any 428ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if self.fileencoding: 429ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh try: 430ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return chars.encode(self.fileencoding) 431ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh except UnicodeError: 432ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh tkMessageBox.showerror( 433ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh "I/O Error", 434ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh "Cannot save this as '%s' anymore. Saving as UTF-8" \ 435ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh % self.fileencoding, 436ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh master = self.text) 437ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return BOM_UTF8 + chars.encode("utf-8") 438ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Nothing was declared, and we had not determined an encoding 439ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # on loading. Recommend an encoding line. 440ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh config_encoding = idleConf.GetOption("main","EditorWindow", 441ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh "encoding") 442ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if config_encoding == 'utf-8': 443ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # User has requested that we save files as UTF-8 444ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return BOM_UTF8 + chars.encode("utf-8") 445ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh ask_user = True 446ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh try: 447ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh chars = chars.encode(encoding) 448ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh enc = encoding 449ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if config_encoding == 'locale': 450ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh ask_user = False 451ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh except UnicodeError: 452ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh chars = BOM_UTF8 + chars.encode("utf-8") 453ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh enc = "utf-8" 454ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if not ask_user: 455ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return chars 456ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh dialog = EncodingMessage(self.editwin.top, enc) 457ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh dialog.go() 458ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if dialog.num == 1: 459ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # User asked us to edit the file 460ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh encline = "# -*- coding: %s -*-\n" % enc 461ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh firstline = self.text.get("1.0", "2.0") 462ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if firstline.startswith("#!"): 463ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Insert encoding after #! line 464ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.text.insert("2.0", encline) 465ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh else: 466ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.text.insert("1.0", encline) 467ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return self.encode(self.text.get("1.0", "end-1c")) 468ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return chars 469ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 470ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def fixlastline(self): 471ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh c = self.text.get("end-2c") 472ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if c != '\n': 473ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.text.insert("end-1c", "\n") 474ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 475ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def print_window(self, event): 476ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh confirm = tkMessageBox.askokcancel( 477ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh title="Print", 478ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh message="Print to Default Printer", 479ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh default=tkMessageBox.OK, 480ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh master=self.text) 481ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if not confirm: 482ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.text.focus_set() 483ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return "break" 484ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh tempfilename = None 485ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh saved = self.get_saved() 486ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if saved: 487ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh filename = self.filename 488ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # shell undo is reset after every prompt, looks saved, probably isn't 489ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if not saved or filename is None: 490ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh (tfd, tempfilename) = tempfile.mkstemp(prefix='IDLE_tmp_') 491ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh filename = tempfilename 492ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh os.close(tfd) 493ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if not self.writefile(tempfilename): 494ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh os.unlink(tempfilename) 495ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return "break" 496ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh platform = os.name 497ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh printPlatform = True 498ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if platform == 'posix': #posix platform 499ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh command = idleConf.GetOption('main','General', 500ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 'print-command-posix') 501ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh command = command + " 2>&1" 502ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh elif platform == 'nt': #win32 platform 503ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh command = idleConf.GetOption('main','General','print-command-win') 504ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh else: #no printing for this platform 505ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh printPlatform = False 506ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if printPlatform: #we can try to print for this platform 507ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh command = command % pipes.quote(filename) 508ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh pipe = os.popen(command, "r") 509ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # things can get ugly on NT if there is no printer available. 510ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh output = pipe.read().strip() 511ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh status = pipe.close() 512ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if status: 513ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh output = "Printing failed (exit status 0x%x)\n" % \ 514ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh status + output 515ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if output: 516ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh output = "Printing command: %s\n" % repr(command) + output 517ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh tkMessageBox.showerror("Print status", output, master=self.text) 518ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh else: #no printing for this platform 519ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh message = "Printing is not enabled for this platform: %s" % platform 520ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh tkMessageBox.showinfo("Print status", message, master=self.text) 521ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if tempfilename: 522ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh os.unlink(tempfilename) 523ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return "break" 524ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 525ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh opendialog = None 526ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh savedialog = None 527ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 528ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh filetypes = [ 529ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh ("Python files", "*.py *.pyw", "TEXT"), 530ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh ("Text files", "*.txt", "TEXT"), 531ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh ("All files", "*"), 532ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh ] 533ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 534ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def askopenfile(self): 535ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh dir, base = self.defaultfilename("open") 536ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if not self.opendialog: 537ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.opendialog = tkFileDialog.Open(master=self.text, 538ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh filetypes=self.filetypes) 539ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh filename = self.opendialog.show(initialdir=dir, initialfile=base) 540ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if isinstance(filename, unicode): 541ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh filename = filename.encode(filesystemencoding) 542ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return filename 543ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 544ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def defaultfilename(self, mode="open"): 545ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if self.filename: 546ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return os.path.split(self.filename) 547ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh elif self.dirname: 548ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return self.dirname, "" 549ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh else: 550ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh try: 551ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh pwd = os.getcwd() 552ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh except os.error: 553ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh pwd = "" 554ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return pwd, "" 555ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 556ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def asksavefile(self): 557ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh dir, base = self.defaultfilename("save") 558ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if not self.savedialog: 559ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.savedialog = tkFileDialog.SaveAs(master=self.text, 560ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh filetypes=self.filetypes) 561ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh filename = self.savedialog.show(initialdir=dir, initialfile=base) 562ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if isinstance(filename, unicode): 563ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh filename = filename.encode(filesystemencoding) 564ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return filename 565ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 566ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def updaterecentfileslist(self,filename): 567ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh "Update recent file list on all editor windows" 568ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.editwin.update_recent_files_list(filename) 569ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 570ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehdef test(): 571ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh root = Tk() 572ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh class MyEditWin: 573ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def __init__(self, text): 574ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.text = text 575ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.flist = None 576ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.text.bind("<Control-o>", self.open) 577ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.text.bind("<Control-s>", self.save) 578ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.text.bind("<Alt-s>", self.save_as) 579ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.text.bind("<Alt-z>", self.save_a_copy) 580ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def get_saved(self): return 0 581ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def set_saved(self, flag): pass 582ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def reset_undo(self): pass 583ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def open(self, event): 584ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.text.event_generate("<<open-window-from-file>>") 585ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def save(self, event): 586ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.text.event_generate("<<save-window>>") 587ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def save_as(self, event): 588ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.text.event_generate("<<save-window-as-file>>") 589ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def save_a_copy(self, event): 590ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.text.event_generate("<<save-copy-of-window-as-file>>") 591ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text = Text(root) 592ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text.pack() 593ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh text.focus_set() 594ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh editwin = MyEditWin(text) 595ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh io = IOBinding(editwin) 596ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh root.mainloop() 597ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 598ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehif __name__ == "__main__": 599ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh test() 600