linux c 获取终端光标的坐标

4 篇文章 0 订阅

参考资料

http://www.linuxquestions.org/questions/programming-9/get-cursor-position-in-c-947833/

#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
#include <errno.h>

#define   RD_EOF   -1
#define   RD_EIO   -2

static inline int rd(const int fd)
{
    unsigned char   buffer[4];
    ssize_t         n;

    while (1) {

        n = read(fd, buffer, 1);
        if (n > (ssize_t)0)
            return buffer[0];

        else
        if (n == (ssize_t)0)
            return RD_EOF;

        else
        if (n != (ssize_t)-1)
            return RD_EIO;

        else
        if (errno != EINTR && errno != EAGAIN && errno != EWOULDBLOCK)
            return RD_EIO;
    }

   return 0;
}

static inline int wr(const int fd, const char *const data, const size_t bytes)
{
    const char       *head = data;
    const char *const tail = data + bytes;
    ssize_t           n;

    while (head < tail) {

        n = write(fd, head, (size_t)(tail - head));
        if (n > (ssize_t)0)
            head += n;

        else
        if (n != (ssize_t)-1)
            return EIO;

        else
        if (errno != EINTR && errno != EAGAIN && errno != EWOULDBLOCK)
            return errno;
    }

    return 0;
}

/* Return a new file descriptor to the current TTY.
*/
int current_tty(void)
{
    const char *dev;
    int         fd;

    dev = ttyname(STDIN_FILENO);
    if (!dev)
        dev = ttyname(STDOUT_FILENO);
    if (!dev)
        dev = ttyname(STDERR_FILENO);
    if (!dev) {
        errno = ENOTTY;
        return -1;
    }

    do {
        fd = open(dev, O_RDWR | O_NOCTTY);
    } while (fd == -1 && errno == EINTR);
    if (fd == -1)
        return -1;

    return fd;
}

/* As the tty for current cursor position.
 * This function returns 0 if success, errno code otherwise.
 * Actual errno will be unchanged.
*/
int cursor_position(const int tty, int *const rowptr, int *const colptr)
{
    struct termios  saved, temporary;
    int             retval, result, rows, cols, saved_errno;

    /* Bad tty? */
    if (tty == -1)
        return ENOTTY;

    saved_errno = errno;

    /* Save current terminal settings. */
    do {
        result = tcgetattr(tty, &saved);
    } while (result == -1 && errno == EINTR);
    if (result == -1) {
        retval = errno;
        errno = saved_errno;
        return retval;
    }

    /* Get current terminal settings for basis, too. */
    do {
        result = tcgetattr(tty, &temporary);
    } while (result == -1 && errno == EINTR);
    if (result == -1) {
        retval = errno;
        errno = saved_errno;
        return retval;
    }

    /* Disable ICANON, ECHO, and CREAD. */
    temporary.c_lflag &= ~ICANON;
    temporary.c_lflag &= ~ECHO;
    temporary.c_cflag &= ~CREAD;

    /* This loop is only executed once. When broken out,
     * the terminal settings will be restored, and the function
     * will return retval to caller. It's better than goto.
    */
    do {

        /* Set modified settings. */
        do {
            result = tcsetattr(tty, TCSANOW, &temporary);
        } while (result == -1 && errno == EINTR);
        if (result == -1) {
            retval = errno;
            break;
        }

        /* Request cursor coordinates from the terminal. */
        retval = wr(tty, "\033[6n", 4);
        if (retval)
            break;

        /* Assume coordinate reponse parsing fails. */
        retval = EIO;

        /* Expect an ESC. */
        result = rd(tty);
        if (result != 27)
            break;

        /* Expect [ after the ESC. */
        result = rd(tty);
        if (result != '[')
            break;

        /* Parse rows. */
        rows = 0;
        result = rd(tty);
        while (result >= '0' && result <= '9') {
            rows = 10 * rows + result - '0';
            result = rd(tty);
        }

        if (result != ';')
            break;

        /* Parse cols. */
        cols = 0;
        result = rd(tty);
        while (result >= '0' && result <= '9') {
            cols = 10 * cols + result - '0';
            result = rd(tty);
        }

        if (result != 'R')
            break;

        /* Success! */

        if (rowptr)
            *rowptr = rows;

        if (colptr)
            *colptr = cols;

        retval = 0;

    } while (0);

    /* Restore saved terminal settings. */
    do {
        result = tcsetattr(tty, TCSANOW, &saved);
    } while (result == -1 && errno == EINTR);
    if (result == -1 && !retval)
        retval = errno;

    /* Done. */
    return retval;
}

int main(void)
{
    int         fd, row, col;
    char        buffer[64];
    char *const tail = buffer + sizeof(buffer);
    char       *head = buffer + sizeof(buffer);

    fd = current_tty();
    if (fd == -1)
        return 1;

    row = 0;
    col = 0;
    if (cursor_position(fd, &row, &col))
        return 2;

    if (row < 1 || col < 1)
        return 3;

    /* Construct response "(row, col) " from right to left,
     * then output it to standard error, and exit.
    */

    *(--head) = ' ';
    *(--head) = ')';

    {   unsigned int    u = col;
        do {
            *(--head) = '0' + (u % 10U);
            u /= 10U;
        } while (u);
    }

    *(--head) = ' ';
    *(--head) = ',';

    {   unsigned int    u = row;
        do {
            *(--head) = '0' + (u % 10U);
            u /= 10U;
        } while (u);
    }

    *(--head) = '(';

    if (wr(STDERR_FILENO, head, (size_t)(tail - head)))
        return 4;

    return 0;
}

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Linux获取第三方应用程序的文本框光标位置,需要先了解 Linux 下的 X Window 系统。X Window 是 Linux 下的图形用户界面的基础,它可以通过程序接口 Xlib 来控制和获取窗口的信息。 通过 Xlib,我们可以获取窗口的 ID,然后使用 X Window 事件来监听该窗口的操作,比如鼠标点击、鼠标移动、键盘输入等。而获取文本框光标位置,就需要监听键盘事件,然后判断光标是否在文本框中,并获取光标位置。 具体实现可以借助 GTK 或 Qt 等 GUI 库,它们提供了更高层次的接口,方便我们操作窗口和控件。例如,使用 GTK 可以通过以下代获取当前激活窗口的文本框光标位置: ```c #include <gtk/gtk.h> // 回调函数,用于监听键盘事件 gboolean on_key_press (GtkWidget *widget, GdkEventKey *event, gpointer data) { // 获取当前激活窗口 GdkWindow *window = gtk_widget_get_window (gtk_window_get_focus (GTK_WINDOW (gtk_window_new (GTK_WINDOW_TOPLEVEL)))); // 获取鼠标位置,转换为窗口内的坐标系 gint x, y; gdk_window_get_device_position (window, event->device, &x, &y, NULL); gdk_window_get_origin (window, &x, &y); gdk_window_get_device_position (window, event->device, &x, &y, NULL); // 获取当前窗口内的控件,判断光标是否在文本框中 GtkWidget *widget_at_point = gtk_widget_get_ancestor (gtk_window_get_focus (GTK_WINDOW (gtk_window_new (GTK_WINDOW_TOPLEVEL))), GTK_TYPE_ENTRY); if (widget_at_point != NULL && GTK_IS_ENTRY (widget_at_point)) { gint start, end; gtk_editable_get_selection_bounds (GTK_EDITABLE (widget_at_point), &start, &end); GtkEntryBuffer *buffer = gtk_entry_get_buffer (GTK_ENTRY (widget_at_point)); gint cursor_position = gtk_entry_buffer_get_cursor_position (buffer); if (start <= cursor_position && cursor_position <= end) { // 光标在文本框中,返回光标位置 g_print ("The cursor position in the text box is %d\n", cursor_position); } } return FALSE; } int main (int argc, char *argv[]) { GtkWidget *window; gtk_init (&argc, &argv); window = gtk_window_new (GTK_WINDOW_TOPLEVEL); g_signal_connect (G_OBJECT (window), "key-press-event", G_CALLBACK (on_key_press), NULL); gtk_widget_show_all (window); gtk_main (); return 0; } ``` 以上代使用 GTK 构建了一个窗口,并监听了窗口的键盘事件。当用户按下任意键时,会获取当前激活窗口的 ID,并通过 gdk_window_get_device_position() 函数获取鼠标位置,然后判断光标是否在文本框中。如果光标在文本框中,就获取文本框的光标位置,并输出到终端上。 当然,以上代只是一种实现方式,如果你使用的是其他 GUI 库,可能需要使用不同的 API。不过基本思路都是类似的,需要监听键盘事件,并通过窗口 ID、鼠标位置和控件类型来判断光标位置
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

utopia54

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值