@@ -57,32 +57,13 @@ def _update_max_yx(self):
5757 self .maxx = maxx - 1
5858
5959 def _decode (self , ch ):
60- # The text of a chtype cell or input byte, decoded with the window's
61- # encoding. A_CHARTEXT keeps the character byte, dropping the attributes .
60+ # Decode an integer keystroke or byte to text with the window's encoding.
61+ # A_CHARTEXT drops any attribute bits .
6262 return bytes ([ch & curses .A_CHARTEXT ]).decode (self .win .encoding , 'replace' )
6363
64- def _char_at (self , * yx ):
65- # The text of the cell at the given position (default: the cursor).
66- # instr() re-encodes it to the window's encoding; inch() cannot
67- # represent a non-ASCII 8-bit-locale character on a wide build.
68- return self .win .instr (* yx , 1 ).decode (self .win .encoding , 'replace' )
69-
70- def _cell_at (self , * yx ):
71- # The cell at the given position (default: the cursor) as a chtype
72- # addch() can write back with its rendition. inch() mangles a non-ASCII
73- # character on a wide build, so take the byte from instr() and the
74- # attributes from inch().
75- return self .win .instr (* yx , 1 )[0 ] | self .win .inch (* yx ) & curses .A_ATTRIBUTES
76-
77- def _isprint (self , cell ):
78- # Whether a chtype cell holds a printable character; _decode() drops the
79- # attribute bits.
80- return self ._decode (cell ).isprintable ()
81-
8264 def _printable_key (self , ch ):
83- # Whether the integer keystroke is a printable character, not a key
84- # code. 0..255 are character bytes (decoded with the window's encoding);
85- # larger values are function and navigation keys.
65+ # Whether the integer keystroke is a printable character, not a key code:
66+ # 0..255 are character bytes, larger values are function keys.
8667 return ch <= 0xff and self ._decode (ch ).isprintable ()
8768
8869 def _end_of_line (self , y ):
@@ -91,7 +72,8 @@ def _end_of_line(self, y):
9172 self ._update_max_yx ()
9273 last = self .maxx
9374 while True :
94- if self ._char_at (y , last ) != ' ' :
75+ # The text of the cell at (y, last).
76+ if str (self .win .in_wch (y , last )) != ' ' :
9577 last = min (self .maxx , last + 1 )
9678 break
9779 elif last == 0 :
@@ -105,16 +87,22 @@ def _insert_printable_char(self, ch):
10587 backyx = None
10688 while True :
10789 if self .insert_mode :
108- oldch = self ._cell_at ()
90+ # The displaced cell, as a complexchar so addch() can rewrite it
91+ # with its rendition.
92+ oldch = self .win .in_wch ()
10993 if y >= self .maxy and x >= self .maxx :
110- # Use insch() in the lower-right cell: addch() there would move
111- # the cursor out of the window, raising an error and scrolling
112- # a scrollable window. Pass it as text: insch() does not decode
113- # an int byte through the locale on a wide build.
114- self .win .insch (self ._decode (ch ), ch & curses .A_ATTRIBUTES )
94+ # Use insch() in the lower-right cell; addch() there would push
95+ # the cursor out of the window (an error, and it scrolls a
96+ # scrollable window). insch() does not decode an int byte
97+ # through the locale on a wide build, so pass it as text.
98+ if isinstance (ch , int ):
99+ self .win .insch (self ._decode (ch ), ch & curses .A_ATTRIBUTES )
100+ else :
101+ self .win .insch (ch )
115102 break
116103 self .win .addch (ch )
117- if not self .insert_mode or not self ._isprint (oldch ):
104+ # In insert mode keep shifting cells right until a blank one.
105+ if not self .insert_mode or not str (oldch ).isprintable ():
118106 break
119107 ch = oldch
120108 (y , x ) = self .win .getyx ()
@@ -130,9 +118,17 @@ def do_command(self, ch):
130118 self ._update_max_yx ()
131119 (y , x ) = self .win .getyx ()
132120 self .lastcmd = ch
133- if self ._printable_key (ch ):
121+ if isinstance (ch , str ):
122+ # A character from get_wch(); a control character is dispatched
123+ # below by its code point.
124+ if ch .isprintable ():
125+ self ._insert_printable_char (ch )
126+ return 1
127+ ch = ord (ch )
128+ elif self ._printable_key (ch ):
134129 self ._insert_printable_char (ch )
135- elif ch == curses .ascii .SOH : # ^a
130+ return 1
131+ if ch == curses .ascii .SOH : # ^a
136132 self .win .move (y , 0 )
137133 elif ch in (curses .ascii .STX ,curses .KEY_LEFT ,
138134 curses .ascii .BS ,
@@ -204,15 +200,20 @@ def gather(self):
204200 for x in range (self .maxx + 1 ):
205201 if self .stripspaces and x > stop :
206202 break
207- result = result + self ._char_at (y , x )
203+ result = result + str ( self .win . in_wch (y , x ) )
208204 if self .maxy > 0 :
209205 result = result + "\n "
210206 return result
211207
212208 def edit (self , validate = None ):
213209 "Edit in the widget window and collect the results."
214210 while 1 :
215- ch = self .win .getch ()
211+ ch = self .win .get_wch ()
212+ # Represent an ASCII keystroke by its code point, the way getch()
213+ # always has, so that existing validators and the command dispatch
214+ # keep working; only non-ASCII characters are passed as strings.
215+ if isinstance (ch , str ) and ch .isascii ():
216+ ch = ord (ch )
216217 if validate :
217218 ch = validate (ch )
218219 if not ch :
0 commit comments