New Technology Xchars

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <inttypes.h>
#include <xcb/xcb.h>
#include <X11/XKBlib.h>
#include <pthread.h>
#include "./xchars.h"
#include "./symbols.h"

// Version
#define XCHARS_VERSION " Xchars 1.0.4"
// Limits
#define WIDTH 60
#define HEIGHT 400
#define MAX_STR 20
#define MAX_SIZE 20
#define MAX_WIN 10
// types of symbols
enum{screen_t,conn_t,entry_t,xchars_t,win_t,gc_t,undef_t};
// Xchars carries xcb stuff in something called an XCB
// defaults for test
char * default_font_name ="lucidasans-14";

int xchar_error(char * s1,char * s2,int line) {
printf("Line: %d,%s %s\n",line,s1,s2);
return(ERROR);
}
// Xchars checks its own xcb errors (console loop traps system sigs)
static void testCookie (XCB * xcb, char *errMsg)
{
        xcb_generic_error_t *error = xcb_request_check (xcb->conn, xcb->cookie);
        if (error)
        {
            fprintf (stderr, "ERROR: %s : %"PRIu8"\n", errMsg , error->error_code);
            xcb_disconnect (xcb->conn);
            exit (-1);
        }
   }
// Get font size
int measure_font(XCB * xcb,xcb_font_t font)
{
xcb_char2b_t xcb_str;
xcb_query_text_extents_cookie_t cookie;
xcb_query_text_extents_reply_t *reply;
xcb_str.byte1=0;
xcb_str.byte2 = 'X'; // Sample char
cookie = xcb_query_text_extents(xcb->conn, font, 1, &xcb_str);
reply = xcb_query_text_extents_reply(xcb->conn, cookie, NULL);
if(!reply)
{
puts("String error font measuer");
exit(-1);
}
xcb->xchars->font_dx= reply->overall_width;
xcb->xchars->font_dy = reply->font_ascent + reply->font_descent;
free(reply);
return(SUCCESS);
}

int XCBCursor(XCB* xcb) {
xcb_font_t font = xcb_generate_id (xcb->conn);
xcb->cookie =
xcb_open_font_checked (xcb->conn,font,
strlen ("cursor"),"cursor" );
testCookie (xcb,"can't open font");
if(xcb->cursor) // free the old cursor name
xcb_free_cursor (xcb->conn, xcb->cursor);
xcb->cursor = xcb_generate_id (xcb->conn);
xcb_create_glyph_cursor (xcb->conn,
xcb->cursor,font,font,58, 58 + 1,
0, 0, 0, 0, 0, 0 );
xcb->mask = XCB_CW_CURSOR;
xcb->values[0] = xcb->cursor;
xcb_change_window_attributes (xcb->conn, xcb->win, xcb->mask, xcb->values);
xcb->cookie = xcb_close_font_checked (xcb->conn, font);
testCookie (xcb, "can't close font");
return(SUCCESS);
    }

int XcbSetGC(XCB * xcb)
{
xcb->cookie  = xcb_change_gc_checked(
xcb->conn, xcb->gc, xcb->mask, xcb->values);
testCookie(xcb, "Cant set GC");
return(SUCCESS);
}

int XCBMoveCursor(XCB * xcb) {
xcb->cookie =
xcb_warp_pointer(xcb->conn, xcb->win,
XCB_NONE , xcb->xchars->x,xcb->xchars->y,
xcb->xchars->width,xcb->xchars->height,
xcb->xchars->dx,xcb->xchars->dy);
testCookie(xcb, "can't move ursor");
return(SUCCESS);
}
int XcbFont(XCB *xcb)
{

xcb_font_t font = xcb_generate_id (xcb->conn);
xcb->cookie  =
xcb_open_font(xcb->conn, font, strlen(xcb->fontname), xcb->fontname);
testCookie(xcb, "can't open font");
xcb->values[0]=font;
xcb->mask = XCB_GC_FONT;
XcbSetGC(xcb);
measure_font(xcb,font);
XCBCursor(xcb);
return(SUCCESS);
}
int XcbRGB(XCB* xcb)
{
xcb->mask  = XCB_GC_FOREGROUND | XCB_GC_BACKGROUND;
XcbSetGC(xcb);
return(SUCCESS);
}
int XcbGC (XCB * xcb)
 {
        /* get font */
const char *font_name = default_font_name; 
    xcb_font_t font = xcb_generate_id (xcb->conn);
xcb->cookie = xcb_open_font_checked
(xcb->conn,font,strlen (font_name),font_name );
testCookie(xcb, "can't open font");
/* Generate gc id*/
xcb->gc = xcb_generate_id (xcb->conn);
xcb->mask = XCB_GC_FOREGROUND | XCB_GC_BACKGROUND;
//| XCB_GC_FONT;
xcb->values[0] = xcb->screen->black_pixel;
xcb->values[1] = xcb->screen->white_pixel;
xcb->values[2] = font;
xcb->cookie = xcb_create_gc_checked (xcb->conn,xcb->gc,xcb->win,xcb->mask,xcb->values );
testCookie(xcb,"can't create gc");
measure_font(xcb,font);
/* close font */
xcb->cookie = xcb_close_font_checked (xcb->conn, font);
testCookie(xcb, "can't close font");
return(SUCCESS);
}

int XcbWindow(XCB *xcb)
{
xcb->win = xcb_generate_id (xcb->conn);
xcb->mask = XCB_CW_BACK_PIXEL  | XCB_CW_EVENT_MASK;
xcb->values[0] = xcb->screen->white_pixel;
xcb->values[1] = XCB_EVENT_MASK_KEY_RELEASE | XCB_EVENT_MASK_BUTTON_PRESS;
// | XCB_EVENT_MASK_POINTER_MOTION |  XCB_EVENT_MASK_EXPOSURE;
xcb->cookie = xcb_create_window_checked (xcb->conn,
xcb->screen->root_depth,xcb->win, xcb->screen->root,
xcb->xchars->x,xcb->xchars->y,xcb->xchars->dx,xcb->xchars->dy,
0, XCB_WINDOW_CLASS_INPUT_OUTPUT,
xcb->screen->root_visual,xcb->mask, xcb->values);
        testCookie(xcb,  "can't create window");
xcb->cookie = xcb_map_window_checked(xcb->conn, xcb->win);
testCookie(xcb,  "can't map window");
//b->gc = XcbGC(b);
xcb_flush(xcb->conn);  // make sure window is drawn
return(SUCCESS);
}

 //////////////////////////// 
 int XcbConnect(XCB *xcb)
 {
 /* get the connection  and screenNum*/
int screenNum;
xcb->conn = xcb_connect (NULL, &screenNum);
printf("Conn scrnm %d\n",screenNum);
if (!xcb->conn) {
            fprintf (stderr, "ERROR: can't connect to an X server\n");
            return -1;
        }
/* get the current screen */
xcb_screen_iterator_t iter =
xcb_setup_roots_iterator (xcb_get_setup (xcb->conn));
// we want the screen at index screenNum of the iterator
for (int i = 0; i < screenNum; ++i)
            xcb_screen_next (&iter);
xcb->screen = iter.data;
if (!xcb->screen)
{
fprintf (stderr, "ERROR: can't get the current screen\n");
xcb_disconnect (xcb->conn);
return -1;
}
        return(SUCCESS);
}

int XcbText (XCB* xcb )
{
/* draw the text */
int len = strlen (xcb->xchars->str);
char * str= xcb->xchars->str;
xcb->cookie=
(xcb_void_cookie_t) xcb_image_text_8_checked (xcb->conn,len,
xcb->win,xcb->gc,xcb->xchars->x, xcb->xchars->y,str);
testCookie(xcb,"can't paste text");
xcb_flush(xcb->conn);  // make sure window is drawn
return(SUCCESS);
}
int XcbGeometry(XCB * xcb) {
xcb_generic_error_t *e;
xcb_get_geometry_cookie_t  cookie;
// Get a request id
cookie = xcb_get_geometry(xcb->conn, xcb->win);
// then request
xcb->rect = xcb_get_geometry_reply(xcb->conn, cookie, &e);
printf("%d %d\n",xcb->rect->width,xcb->rect->height);
return(SUCCESS);
}
int XcbSetWindow(XCB *xcb)
{
    xcb_change_window_attributes (xcb->conn, xcb->win, xcb->mask, xcb->values);
    return(SUCCESS);
}
int XcbPoll(XCB * xcb) {
xcb_generic_event_t *event;
if( (event = xcb_poll_for_event (xcb->conn)) ) {
switch (event->response_type & ~0x80) {
case XCB_EXPOSE:
            //xcb_expose_event_t *expose = (xcb_expose_event_t *)event;
            /* ...do stuff */
break;
default:
            /* Unknown event type, ignore it */
break;
       }
free (event);
}
return(SUCCESS);
}


XcbTypes XcbEntry =
{
XcbConnect,
XcbWindow,
XcbGC,
XcbSetGC,
XcbFont,
XcbRGB,
XcbText,
XcbPoll,
XcbGeometry
};
/////////////// Xchar universal interface methods ////////////
PSym check_arg(char *args,int type,int *status) {
PSym s = get_key(pack_text( args));  //
if(!s || !s->key ) *status=0;
else  if(s->type != type) *status=0;
else *status=1;
return(s);
}
// NewRect win gc xchars x y width height
int NewRect(int *argc,void * args[])
{
int i=*argc;
int status;
PSym win_sym = check_arg(args[i+1],win_t,&status);
if(!status)  return(xchar_error("No Win",args[i+1],__LINE__));
PSym gc_sym = check_arg(args[i+2],gc_t,&status);
if(!status)   return(xchar_error("No gc",args[i+1],__LINE__));
PSym xchars_sym = put_key(pack_text( args[i+3]));  //
xchars_sym->def.vp = (void *) calloc(1,sizeof(XCHARS));
XCHARS * xchars= xchars_sym->def.vp;
xchars->font_dx=10;
xchars->font_dy=10;
xchars->x=atoi(args[i+4]);
xchars->y=atoi(args[i+5]);
xchars->dx=atoi(args[i+6]);
xchars->dy=atoi(args[i+7]);
xchars->xchars=0;
xchars->gc=gc_sym->def.gc;
xchars->str="Dixchars from Rect";
xchars_sym->type = xchars_t;
xchars_sym->symlink.sym= win_sym;
*argc +=8;
printf("New Rect \n");
return(SUCCESS);
}
// DelRect xchars
int DelRect(int *argc,void*args[])
{
int i=*argc;
int status;
PSym xchars_sym = check_arg(args[i+1],xchars_t,&status);
if(!status)   return(xchar_error("No Rect",args[i+1],__LINE__));
free(xchars_sym->def.vp);
*argc +=2;
return(SUCCESS);
}
// xcb_free_window
//   xcb_disconnect (connection);
// DelGC gc
//xcb_void_cookie_t
//               xcb_destroy_window_checked (xcb_connection_t *c, xcb_window_t window)
int DelGC(int *argc,void*args[])
{
int i=*argc;
int status;
PSym gc_sym = check_arg(args[i+1],gc_t,&status);
if(!status)   return(xchar_error("No Rect",args[i+1],__LINE__));
  /* free the gc */
     //xcb_void_cookie_t gcCookie = xcb_free_gc (connection, gc);
free(gc_sym->def.vp);
*argc+=2;
return(SUCCESS);
}
// Newin conn win
int NewWin(int *argc,void * args[])
{
int i=*argc; // starts with command
int status;
PSym conn_sym = check_arg(args[i+1],conn_t,&status);
if(!status)   return(xchar_error("No conn",args[i+1],__LINE__));
XCB * xcb =  conn_sym->symlink.xcb;
if(xcb->conn != conn_sym->def.vp) printf("conn error\n");
if(!xcb->xchars) return(xchar_error("No xchars",args[i+1],__LINE__));
PSym win_sym = put_key(pack_text( args[i+2]));
win_sym->type= win_t;
win_sym->symlink.sym =conn_sym;
XcbWindow(xcb);
win_sym->def.win=xcb->win;
*argc +=3;
printf("New Win \n");
return(SUCCESS);
}

// PutStr xchars gc string
int PutStr(int * argc,void * args[] )
{// he structure is an unused,ongoing test
struct {
char *cmd_name; char * xchars_name;
char * gc_name; char * string;
} *ptr=(void *) args;
printf("PutString %s %s %s %s \n",
ptr->cmd_name,ptr->xchars_name,ptr->gc_name,ptr->string);
int base= *argc;
int status;
PSym xchars_sym = check_arg(args[base+1],xchars_t,&status);
if(!status)   return(xchar_error("No xchars",args[base+1],__LINE__));;
PSym gc_sym = check_arg(args[base+2],gc_t,&status);
if(!status)   return(xchar_error("No gc",args[base+2],__LINE__));
XCHARS *xchars = xchars_sym->def.xchars;
PSym win_sym = xchars_sym->symlink.sym;
PSym conn_sym =  win_sym->symlink.sym;
XCB * xcb= conn_sym->symlink.xcb;
xcb->gc = gc_sym->def.l;
xcb->win = win_sym->def.l;
xcb->conn= conn_sym->def.conn;
xchars->str=args[base+3];
xcb->xchars=xchars;
XcbText(xcb);
*argc +=4;
return(SUCCESS);
}
// DelWin xchars
int DelWin(int * argc,void * args[] )
{
int i= *argc; // start with command
int status;
PSym win_sym = check_arg(args[i+1],win_t,&status);
if(!status)   return(xchar_error("No win",args[i+1],__LINE__));
free(win_sym->def.s);
*argc +=2;
return(SUCCESS);
}

// SetFont conn gc font_name
int SetFont(int * argc,void * args[] )
{
int i= *argc; // start with command
int status;
PSym conn_sym = check_arg(args[i+1],conn_t,&status);
if(!status)   return(xchar_error("No conn",args[i+1],__LINE__));
PSym gc_sym = check_arg(args[i+2],gc_t,&status);
if(!status)   return(xchar_error("No gc",args[i+2],__LINE__));
XCB * xcb= conn_sym->symlink.xcb;
xcb->gc=gc_sym->def.l;
xcb->conn=conn_sym->def.vp;
xcb->fontname=(char *)args[i+3];
XcbFont(xcb);
*argc += 4;
printf("New Font \n");
return(SUCCESS);
}
// SetRGB conn gc for_rgb back_rgb
int SetRGB(int * argc,void * args[])
{
int i= *argc; // skip command
int status;
PSym conn_sym = check_arg(args[i+1],conn_t,&status);
if(!status)   return(xchar_error("No conn",args[i+1],__LINE__));
PSym gc_sym = check_arg(args[i+2],gc_t,&status);
if(!status)   return(xchar_error("No gc",args[i+2],__LINE__));
XCB * xcb= conn_sym->symlink.xcb;
xcb->conn=conn_sym->def.vp;
xcb->gc=gc_sym->def.gc;
xcb->values[0]=atoi(args[i+3]);
xcb->values[1]=atoi(args[i+4]);
XcbRGB(xcb);
*argc += 5;
printf("New Color \n");
return(SUCCESS);
}

// NewGC conn gcname
int NewGC(int *argc,void * args[])
{
int i= *argc; // starting with command
int status;
PSym conn_sym = check_arg(args[i+1],conn_t,&status);
if(!status)   return(xchar_error("No conn",args[i+1],__LINE__));
XCB * xcb = conn_sym->symlink.xcb;
PSym gc_sym = put_key(pack_text( args[i+2]));  //
xcb->win =xcb->screen->root;
gc_sym->type = gc_t;
gc_sym->def.gc =xcb->gc;
gc_sym->symlink.sym = conn_sym;  // GCs per connection
*argc += 3;
printf("New GC \n");
return(XcbGC(xcb));
}
// NewConn conn
XCB * prev_box=0;
int DelConn(int *argc,void * args[]){return(SUCCESS);}
int NewConn(int *argc,void * args[])
{
int base = *argc; //  command
unsigned long v = pack_text( args[base+1]);
PSym conn_sym = put_key(v);
XCB * xcb= (XCB *) calloc(1,sizeof(XCB));
xcb->xcb=prev_box;
prev_box= xcb;
conn_sym->symlink.xcb=xcb;
XcbConnect(xcb);
conn_sym->def.vp=xcb->conn;
conn_sym->type=conn_t;
args[base+1]= xcb;
*argc += 2;
printf("New Conn \n");
return(SUCCESS);
}

// NewGC conn gcname
int PollConn(int *argc,void * args[])
{
int i= *argc; // starting with command
int status;
PSym conn_sym = check_arg(args[i+1],conn_t,&status);
if(!status)   return(xchar_error("No conn",args[i+1],__LINE__));
XCB * xcb = conn_sym->symlink.xcb;
XcbPoll(xcb);
return(SUCCESS);
}
int init();
//int init();
// Command arg1 rg2 ...
int xchars(int *argc, void *args[])
{
int status;
PSym enter;
pthread_mutex_t xchars_mutex;
if(!strcmp(args[*argc],"Init")) return(init());
enter = check_arg(args[*argc],entry_t,&status);
if(!status)  return(NOTFOUND);
pthread_mutex_lock(&xchars_mutex);
enter->def.entry(argc,args);
pthread_mutex_unlock(&xchars_mutex);
return(SUCCESS);
}


// All the console entry points for Xchars
#define m(a) {a,#a}
struct {
EntryType * entry;
char * str;
} List[] = { m(NewGC),m(NewConn),
m(NewWin),m(NewRect),
m(PutStr), m(SetRGB),m(SetFont),
m(DelConn),m(DelRect),m(DelGC),m(DelWin),m(0)
};
const int Nterms = sizeof( List)/(sizeof(long)*2);

int init()
{
int i=0;
unsigned long v;
while(List[i].entry)
{
v = pack_text(List[i].str);
PSym p = put_key(v);
p->type = entry_t;
p->def.entry= List[i].entry;
i++;
}
return(SUCCESS);
}

#ifdef TEST
#define MAXINT 4000
int convert( void * arg) {
Val v;
v.vp = arg;
if(v.l < MAXINT) return(v.l);
else return (atoi(v.s));
}

int XcharsTest(XCHARS * xchars,void * args[]) {
xchars->font_dx=6;
xchars->font_dy=10;
xchars->x=convert(args[0]);
xchars->y=convert(args[1]);
xchars->dx=convert(args[2]);
xchars->dy=convert(args[3]);
xchars->xchars=0;
xchars->str= " Xchars from Rect";
return(SUCCESS);
}
int main()
{ unsigned long args[4]={30,30,1000,1000};
XCB xcb;
XCHARS xchars;
puts(XCHARS_VERSION);
puts("Standalone");
init();
XcbConnect( &xcb);
XcharsTest(&xchars,(void **) args);
xcb.xchars = &xchars;
XcbWindow(&xcb);
XcbGC(&xcb);
xchars.gc=xcb.gc;
XcbGeometry(&xcb);
xchars.str="Hello world\n Second line\n third ine";
xchars.x=10;
xchars.y=10;
XcbText(&xcb);
return(SUCCESS);
}
#endif

No comments: