rthornton128 / goncurses

NCurses Library for Go
Other
383 stars 51 forks source link

UTF-8 support #47

Closed andrewmed closed 4 years ago

andrewmed commented 5 years ago

Hello

I am not sure if it must work at all I did not find any mention of utf8 support here, both ncurses (since version 5.13) and golang's C.CString support utf8, however.

In my case it is ncurses 6.1.20181013 and I tested C.CString separatelly in a simple C call from go, it prints utf-8

When using utf-8 strings with goncurses I get this output: Све�~@�~E�~C видно в�~A�~Q

The problem seems to be down this call https://github.com/rthornton128/goncurses/blob/52220cf7cbaf747e5285d203b8ecf7cacc025b24/window.go#L391 but I can not track it further.

Does anyone have utf-8 working ?

nbedos commented 5 years ago

I was wondering the same thing and setting the locale as suggested in ncurses(3X) is all that is required to get it to work on my machine.

The library uses the locale which the calling program has initialized. That is normally done with setlocale:

setlocale(LC_ALL, "");

If the locale is not initialized, the library assumes that characters are printable as in ISO-8859-1, to work with certain legacy programs. You should initialize the locale and not rely on specific details of the library when the locale has not been setup.

Here is a modified version of examples/getstr/getstr.go that works with non ASCII characters:

// goncurses - ncurses library for Go.
// Copyright 2011 Rob Thornton. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

/* This example demonstrates reading a string from input, rather than a
 * single character */
package main

import (
    gc "github.com/rthornton128/goncurses"
    "log"
    "github.com/famz/SetLocale"
)

func main() {
    SetLocale.SetLocale(SetLocale.LC_ALL, "")

    stdscr, err := gc.Init()
    if err != nil {
        log.Fatal("init:", err)
    }
    defer gc.End()

    msg := "Enter a string: "
    row, col := stdscr.MaxYX()
    row, col = (row/2)-1, (col-len(msg))/2
    stdscr.MovePrint(row, col, msg)

    /* GetString will only retrieve the specified number of characters. Any
    attempts by the user to enter more characters will elicit an audible
    beep */
    var str string
    str, err = stdscr.GetString(10)
    if err != nil {
        stdscr.MovePrint(row+1, col, "GetString Error:", err)
    } else {
        stdscr.MovePrintf(row+1, col, "You entered: %s", str)
    }

    stdscr.Refresh()
    stdscr.GetChar()
}

Output:

Enter a string: aábdðeé
You entered: aábdðeé
andrewmed commented 5 years ago

@nbedos Thanks for this. I think I tried setting up locale, but in C portion of embedded code, I guess I did it wrong.... Can not check your solution right now, that piece of code was done with other library at the end, but it sure helps others, thanks for sharing!

rthornton128 commented 4 years ago

Closing because it looks like the proposed solution is the correct one.