2

我正在用 libX11 编写一个简单的文本用户界面,并且我有一组用于基本库抽象的代码。

问题是当我尝试绘制文本时,标题栏挡住了第一行。所以现在我必须将垂直打印偏移大约 20 个像素。有没有办法确定标题栏的确切大小,以便我可以正确偏移每一行文本?

这是我到目前为止的代码,并且tui_puts是我需要执行此操作的功能:

#include "tui.h"

#include <X11/Xlib.h>
#include <unistd.h>

#include <stdlib.h>
#include <string.h>

struct tui_data {

    Display * display;
    Window id_window;
    GC context_graphics;

    XIM method_input;
    XIC context_input;

    XWindowAttributes spec_window;
    XFontStruct * spec_font;

    size_t offset_y;
    size_t offset_x;
};

int tui_init (struct tui_session * ptr_tui){
    memset (ptr_tui, 0, sizeof (struct tui_session));

    ptr_tui->ptr_data = calloc (sizeof (struct tui_data), 1);
    if (!ptr_tui->ptr_data) return -1;

    ptr_tui->ptr_data->display = XOpenDisplay (0);
    if (!ptr_tui->ptr_data->display) return -1;

    int color_black = BlackPixel(ptr_tui->ptr_data->display, DefaultScreen(ptr_tui->ptr_data->display));
    int color_white = WhitePixel(ptr_tui->ptr_data->display, DefaultScreen(ptr_tui->ptr_data->display));

    ptr_tui->ptr_data->id_window = XCreateSimpleWindow(ptr_tui->ptr_data->display,
                                                       DefaultRootWindow(ptr_tui->ptr_data->display),
                                                       0, 0, 640, 480, 0, color_black, color_black);

    XSelectInput (ptr_tui->ptr_data->display,
                  ptr_tui->ptr_data->id_window,
                  StructureNotifyMask);

    XMapWindow (ptr_tui->ptr_data->display,
                ptr_tui->ptr_data->id_window);

    ptr_tui->ptr_data->context_graphics = XCreateGC(ptr_tui->ptr_data->display,
                                                    ptr_tui->ptr_data->id_window, 0, 0);

    for (;;){
        XEvent e;
        XNextEvent (ptr_tui->ptr_data->display, &e);
        if (e.type == MapNotify) break;
    }

    XSetForeground (ptr_tui->ptr_data->display,
                    ptr_tui->ptr_data->context_graphics,
                    color_white);

    XGetWindowAttributes (ptr_tui->ptr_data->display,
                          ptr_tui->ptr_data->id_window,
                         &ptr_tui->ptr_data->spec_window);

    XSelectInput (ptr_tui->ptr_data->display,
                  ptr_tui->ptr_data->id_window,
                  ExposureMask | KeyPressMask | ResizeRedirectMask);

    ptr_tui->ptr_data->method_input = XOpenIM (ptr_tui->ptr_data->display, 0, 0, 0);

    if (!ptr_tui->ptr_data->method_input){
        return -1;
    }

    ptr_tui->ptr_data->context_input = XCreateIC (ptr_tui->ptr_data->method_input,
                                                  XNInputStyle, XIMPreeditNothing
                                                | XIMStatusNothing, XNClientWindow,
                                                  ptr_tui->ptr_data->id_window, NULL);

    if (!ptr_tui->ptr_data->context_input){
        return -1;
    }

    XSetICFocus (ptr_tui->ptr_data->context_input);

    ptr_tui->ptr_data->spec_font = XLoadQueryFont (ptr_tui->ptr_data->display,
                                                 "-misc-fixed-medium-"
                                                 "r-normal-*-*-120-*-*");

    if (!ptr_tui->ptr_data->spec_font){
        return -1;
    }

    XSetFont (ptr_tui->ptr_data->display,
              ptr_tui->ptr_data->context_graphics,
              ptr_tui->ptr_data->spec_font->fid);

    ptr_tui->max_x = ptr_tui->ptr_data->spec_window.width
                   / ptr_tui->ptr_data->spec_font->max_bounds.width;
    ptr_tui->max_y = ptr_tui->ptr_data->spec_window.height
                  / (ptr_tui->ptr_data->spec_font->max_bounds.ascent
                  +  ptr_tui->ptr_data->spec_font->max_bounds.descent);
    return 0;
}

int tui_free (struct tui_session * ptr_tui){

    if (ptr_tui->ptr_data){

        XFreeFont (ptr_tui->ptr_data->display, ptr_tui->ptr_data->spec_font);
        XFreeGC (ptr_tui->ptr_data->display, ptr_tui->ptr_data->context_graphics);

        XSetCloseDownMode(ptr_tui->ptr_data->display, DestroyAll);
        XCloseDisplay (ptr_tui->ptr_data->display);

        free (ptr_tui->ptr_data);
    }

    memset (ptr_tui, 0, sizeof (struct tui_session));
    return 0;
}

int tui_refresh (struct tui_session * ptr_tui){
    XFlush (ptr_tui->ptr_data->display);
    return 0;
}

int tui_clear (struct tui_session * ptr_tui){
    XClearWindow (ptr_tui->ptr_data->display,
                  ptr_tui->ptr_data->id_window);
    return 0;
}

int tui_puts (struct tui_session * ptr_tui,
              const void * ptr_data, size_t len_data,
              size_t index_x, size_t index_y, uint32_t flags){

    if (((index_x + len_data) >= ptr_tui->max_x)
    ||  (index_y >= ptr_tui->max_y)) return -1;

    XDrawImageString (ptr_tui->ptr_data->display,
                      ptr_tui->ptr_data->id_window,
                      ptr_tui->ptr_data->context_graphics,
                      ptr_tui->ptr_data->spec_window.border_width
                    + ptr_tui->ptr_data->spec_font->max_bounds.width * index_x,
                     (ptr_tui->ptr_data->spec_font->max_bounds.ascent
                    + ptr_tui->ptr_data->spec_font->max_bounds.descent)
                    * index_y + 20, ptr_data, len_data);

    return 0;
}

int tui_message (struct tui_session * ptr_tui, const char * format, ...){
    return -1;
}

int tui_prompt (struct tui_session * ptr_tui, const char * format, ...){
    return -1;
}

int tui_input (struct tui_session * ptr_tui, tui_event * ptr_event){

    XEvent event;
    Status status = 0;
    KeySym keysym = 0;
    char buffer[4];
    int count = 0;

    XNextEvent(ptr_tui->ptr_data->display, &event);

    switch (event.type){

    case KeyPress:

        count = Xutf8LookupString (ptr_tui->ptr_data->context_input,
                                  (XKeyPressedEvent*) &event, buffer,
                                   sizeof (buffer), &keysym, &status);

            if (count){
                ptr_event->type = TUI_EVENT_KEYPRESS;
                ptr_event->value = buffer[0];
            }

            break;

    case Expose:
        ptr_event->type = TUI_EVENT_REPRINT;
        ptr_event->value = 0;
        break;

    case ResizeRequest:
        XGetWindowAttributes (ptr_tui->ptr_data->display,
                              ptr_tui->ptr_data->id_window,
                             &ptr_tui->ptr_data->spec_window);
        ptr_event->type = TUI_EVENT_REPRINT;
        ptr_event->value = 0;
        break;

    default:
        ptr_event->type = 0;
        ptr_event->value = 0;
    }

    return 0;
}

int tui_scroll (struct tui_session * ptr_tui, int offset){
    return -1;
}

另外,这是一个重要的结构:

typedef struct {
    int x, y;                        /* location of window */
    int width, height;               /* width and height of window */
    int border_width;                /* border width of window */
    int depth;                       /* depth of window */
    Visual *visual;                  /* the associated visual structure */
    Window root;                     /* root of screen containing window */
    int class;                       /* InputOutput, InputOnly*/
    int bit_gravity;                 /* one of the bit gravity values */
    int win_gravity;                 /* one of the window gravity values */
    int backing_store;               /* NotUseful, WhenMapped, Always */
    unsigned long backing_planes;    /* planes to be preserved if possible */
    unsigned long backing_pixel;     /* value to be used when restoring planes */
    Bool save_under;                 /* boolean, should bits under be saved? */
    Colormap colormap;               /* color map to be associated with window */
    Bool map_installed;              /* boolean, is color map currently installed*/
    int map_state;                   /* IsUnmapped, IsUnviewable, IsViewable */
    long all_event_masks;            /* set of events all people have interest in*/
    long your_event_mask;            /* my event mask */
    long do_not_propagate_mask;      /* set of events that should not propagate */
    Bool override_redirect;          /* boolean value for override-redirect */
    Screen *screen;                  /* back pointer to correct screen */
} XWindowAttributes;

这有助于获得客户区域的水平偏移,但我没有看到任何可以帮助我获得垂直偏移的东西。

4

1 回答 1

2

原点位于基线,所以ptr_tui->ptr_data->spec_font->max_bounds.ascent如果我没有迷失在你的代码中,你必须添加而不是 20。

于 2013-11-06T21:19:34.790 回答