0

The program I'm trying to write prints 'Hello World' into the window.

When Hello World is clicked with the mouse it reads Hello World character by character

The cursor is then moved further down the screen and should display what it has read.

What is actually displayed is garbled text.

Hello world





          ^[[M %!^[[M#%!

It should be:

Hello world





      Hello world

The code is shown below:

I'm only reading the string character by character because I could not find a way to read the whole string.

import curses

# Initialize variables
q = -1
stdscr = curses.initscr()
curses.mousemask(1)
curses.start_color()

# color pair 1 = red text on white background
curses.init_pair(1, curses.COLOR_RED, curses.COLOR_WHITE)
stdscr.bkgd(' ', curses.color_pair(1))
stdscr.addstr( "Hello world", curses.color_pair(1) )

# Move cursor furthur down screen and slightly to the right
stdscr.move(10,10)

while True:
  event = stdscr.getch()
  if event == ord('q'):
    break                    # quit if q is pressed

  if event == curses.KEY_MOUSE:
    _, mx, my, _, _ = curses.getmouse()
    y, x = stdscr.getyx()    # put cursor position in x and y


    # read the line character by character into char array called mystr
    mystr = []
    for i in range(140):
      mystr.append(stdscr.inch(my, i))  # read char into mystr
    stdscr.addstr(y, x, "".join(mystr))   # Try to display char array
                                        # but it's garbled
  stdscr.refresh()
curses.endwin()
Laurence
  • 869
  • 3
  • 12
  • 20

1 Answers1

1

In your example, there are two problems:

  • you did not call the keypad function; unless you turn that on, the events are single bytes, not function keys
  • the inch function is not the only way to get data from the screen, and calling it in a loop like that would raise an exception.

Here is a reworked example (which adds a few features, such as ^L to repaint the screen, and showing the text which was read in a header-line):

import curses

def hello_world():
  stdscr.erase()
  stdscr.addstr(curses.LINES / 2,
                curses.COLS / 2 - 5,
                "Hello world",
                curses.color_pair(1) )
  
def show_event(event):
  y, x = stdscr.getyx()    # save cursor position
  stdscr.addstr(1,0, "event:" + str(event) + ", KEY=" + curses.keyname(event))
  stdscr.clrtoeol()
  stdscr.move(y, x)

# Initialize variables
q = -1
stdscr = curses.initscr()
stdscr.keypad(1)
curses.mousemask(1)
curses.start_color()

# color pair 1 = red text on white background
curses.init_pair(1, curses.COLOR_RED, curses.COLOR_WHITE)
stdscr.bkgd(' ', curses.color_pair(1))
hello_world()

# Move cursor furthur down screen and slightly to the right
stdscr.move(10,10)

while True:
  event = stdscr.getch()

  if event == 12:
    y, x = stdscr.getyx()    # put cursor position in x and y
    hello_world()
    stdscr.move(y, x)

  if event == ord('q'):
    break                    # quit if q is pressed

  if event == curses.KEY_MOUSE:
    _, mx, my, _, _ = curses.getmouse()

    mystr = stdscr.instr(my, mx) # read remainder of line
    stdscr.addstr(my, mx, "*") # mark where the mouse event occurred
    stdscr.addstr(0, 0, str(my) + "," + str(mx) + " {" + mystr.rstrip() + "}")
    stdscr.clrtoeol()
    stdscr.move(my, mx)

  show_event(event)
  stdscr.refresh()
curses.endwin()
Thomas Dickey
  • 51,086
  • 7
  • 70
  • 105