# HG changeset patch # User Mychaela Falconia # Date 1521051405 0 # Node ID e7f1035f10d49dedac6813b43c36c2bcc40ec5c2 lcdemu: initial import from freecalypso-tools diff -r 000000000000 -r e7f1035f10d4 lcdemu/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lcdemu/Makefile Wed Mar 14 18:16:45 2018 +0000 @@ -0,0 +1,17 @@ +CC= gcc +CFLAGS= -O2 +PROG= fc-lcdemu +OBJS= globals.o main.o process.o window.o ximage.o xrm.o +INSTBIN=/usr/local/bin + +all: ${PROG} + +${PROG}: ${OBJS} + ${CC} ${CFLAGS} -o $@ ${OBJS} -lX11 + +install: ${PROG} + mkdir -p ${INSTBIN} + install -c ${PROG} ${INSTBIN} + +clean: + rm -f *.o *.out *errs ${PROG} diff -r 000000000000 -r e7f1035f10d4 lcdemu/globals.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lcdemu/globals.c Wed Mar 14 18:16:45 2018 +0000 @@ -0,0 +1,20 @@ +/* + * LCDemu based on HECterm by the same author + * Definitions of global variables + */ + +#include +#include +#include + +char *progbasename, *proginstancename; +char *mydisplayname; +Display *mydisplay; +Window mainwindow; +GC mainwingc; +int display_depth; + +XrmDatabase xrmdb_defaults, xrmdb_displayres, xrmdb_cmdline; +XrmQuark xrmquark_topclass, xrmquark_topinstance; + +XImage *(*convert_function)(); diff -r 000000000000 -r e7f1035f10d4 lcdemu/globals.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lcdemu/globals.h Wed Mar 14 18:16:45 2018 +0000 @@ -0,0 +1,16 @@ +/* + * LCDemu based on HECterm by the same author + * External declaratiions for global variables + */ + +extern char *progbasename, *proginstancename; +extern char *mydisplayname; +extern Display *mydisplay; +extern Window mainwindow; +extern GC mainwingc; +extern int display_depth; + +extern XrmDatabase xrmdb_defaults, xrmdb_displayres, xrmdb_cmdline; +extern XrmQuark xrmquark_topclass, xrmquark_topinstance; + +extern XImage *(*convert_function)(); diff -r 000000000000 -r e7f1035f10d4 lcdemu/main.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lcdemu/main.c Wed Mar 14 18:16:45 2018 +0000 @@ -0,0 +1,166 @@ +/* + * LCDemu main module + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "globals.h" + +main(argc, argv) + char **argv; +{ + XrmInitialize(); + process_cmdline(argc, argv); + open_display(); + init_image_conversion(); + load_resources(); + create_our_window(); + set_initial_window_title(); + set_initial_icon_name(); + create_mainwin_gc(); + XMapWindow(mydisplay, mainwindow); + XFlush(mydisplay); + + mainloop(); + /* NOTREACHED */ +} + +process_cmdline(argc, argv) + char **argv; +{ + register char **ap, *opt; + char *rhost, *ruser; + int len; + + if (argc < 1) { + fprintf(stderr, "fc-lcdemu: invalid invokation\n"); + exit(1); + } + opt = rindex(argv[0], '/'); + if (opt) + progbasename = opt + 1; + else + progbasename = argv[0]; + proginstancename = progbasename; + for (ap = argv+1; *ap; ) { + if (**ap == '-') + opt = *ap++; + else + break; + if (!strcmp(opt, "-display")) { + if (!*ap) { +argreq: fprintf(stderr, "%s: %s requires an argument\n", + progbasename, opt); + exit(1); + } + mydisplayname = *ap++; + continue; + } + if (!strcmp(opt, "-name")) { + if (!*ap) + goto argreq; + proginstancename = *ap++; + continue; + } + if (!strcmp(opt, "-geometry") || !strcmp(opt, "-geom")) { + if (!*ap) + goto argreq; + XrmPutStringResource(&xrmdb_cmdline, "LCDemu.geometry", + *ap++); + continue; + } + if (!strcmp(opt, "-iconic")) { + XrmPutStringResource(&xrmdb_cmdline, "LCDemu.iconic", + "on"); + continue; + } + if (!strcmp(opt, "-title")) { + if (!*ap) + goto argreq; + XrmPutStringResource(&xrmdb_cmdline, "LCDemu.title", + *ap++); + continue; + } + if (!strcmp(opt, "-borderwidth") || !strcmp(opt, "-bw")) { + if (!*ap) + goto argreq; + XrmPutStringResource(&xrmdb_cmdline, "*borderWidth", + *ap++); + continue; + } + if (!strcmp(opt, "-bordercolor") || !strcmp(opt, "-bd")) { + if (!*ap) + goto argreq; + XrmPutStringResource(&xrmdb_cmdline, "*borderColor", + *ap++); + continue; + } + if (!strcmp(opt, "-xrm")) { + if (!*ap) + goto argreq; + XrmPutLineResource(&xrmdb_cmdline, *ap++); + continue; + } + fprintf(stderr, "%s: %s: unrecognized option\n", progbasename, + opt); + exit(1); + } +} + +open_display() +{ + if (!mydisplayname) + mydisplayname = getenv("DISPLAY"); + if (!mydisplayname) { + fprintf(stderr, "%s: no X display available\n", progbasename); + exit(1); + } + mydisplay = XOpenDisplay(mydisplayname); + if (!mydisplay) { + fprintf(stderr, "%s: unable to open display %s\n", progbasename, + mydisplayname); + exit(1); + } +} + +mainloop() +{ + register int i, cc; + XEvent event; + fd_set readfds; + int maxfd; + char buf[1024]; + + maxfd = ConnectionNumber(mydisplay) + 1; + for (;;) { + cc = XPending(mydisplay); + for (i = 0; i < cc; i++) + XNextEvent(mydisplay, &event); + XFlush(mydisplay); + FD_ZERO(&readfds); + FD_SET(0, &readfds); + FD_SET(ConnectionNumber(mydisplay), &readfds); + i = select(maxfd, &readfds, NULL, NULL, NULL); + if (i < 0) { + if (errno == EINTR) + continue; + perror("select"); + exit(1); + } + if (FD_ISSET(0, &readfds)) { + cc = read(0, buf, sizeof buf); + if (cc > 0) + input_on_stdin(buf, cc); + else + exit(0); + XFlush(mydisplay); + } + } +} diff -r 000000000000 -r e7f1035f10d4 lcdemu/process.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lcdemu/process.c Wed Mar 14 18:16:45 2018 +0000 @@ -0,0 +1,108 @@ +/* + * Processing of LCD output (input to us) + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "globals.h" + +#define MAX_WIDTH 176 + +static unsigned +hexdecode(str) + char *str; +{ + unsigned accum = 0; + int i, c, n; + + for (i = 0; i < 4; i++) { + c = str[i]; + if (isdigit(c)) + n = c - '0'; + else if (isupper(c)) + n = c - 'A' + 10; + else + n = c - 'a' + 10; + accum <<= 4; + accum |= n; + } + return(accum); +} + +process_input_line(line) + char *line; +{ + int blitrow, blitcol, npix; + uint16_t pix16[MAX_WIDTH]; + char *cp; + XImage *xi; + + for (cp = line; isspace(*cp); cp++) + ; + if (!isdigit(*cp)) { +inv: fprintf(stderr, "fc-lcdemu: invalid input line\n"); + exit(1); + } + blitrow = atoi(cp); + while (isdigit(*cp)) + cp++; + if (!isspace(*cp)) + goto inv; + while (isspace(*cp)) + cp++; + if (!isdigit(*cp)) + goto inv; + blitcol = atoi(cp); + while (isdigit(*cp)) + cp++; + if (!isspace(*cp)) + goto inv; + while (isspace(*cp)) + cp++; + if (!isxdigit(*cp)) + goto inv; + for (npix = 0; *cp; ) { + if (!isxdigit(cp[0]) || !isxdigit(cp[1]) || + !isxdigit(cp[2]) || !isxdigit(cp[3])) + goto inv; + if (npix >= MAX_WIDTH) { + fprintf(stderr, + "fc-lcdemu error: input line exceeds MAX_WIDTH of %d pixels\n", + MAX_WIDTH); + exit(1); + } + pix16[npix++] = hexdecode(cp); + cp += 4; + } + xi = convert_function(pix16, npix); + XPutImage(mydisplay, mainwindow, mainwingc, xi, 0, 0, blitcol, blitrow, + npix, 1); + XDestroyImage(xi); +} + +input_on_stdin(inbuf, incount) + char *inbuf; +{ + char *input_end = inbuf + incount; + static char linebuf[1024]; + static int linesz; + char *cp; + + for (cp = inbuf; cp < input_end; cp++) { + if (*cp == '\n') { + linebuf[linesz] = '\0'; + process_input_line(linebuf); + linesz = 0; + continue; + } + if (linesz < sizeof(linebuf) - 1) + linebuf[linesz++] = *cp; + } +} diff -r 000000000000 -r e7f1035f10d4 lcdemu/window.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lcdemu/window.c Wed Mar 14 18:16:45 2018 +0000 @@ -0,0 +1,157 @@ +/* + * LCDemu based on HECterm by the same author + * X11 window creation functions + */ + +#include +#include +#include +#include +#include +#include +#include +#include "globals.h" + +extern char *xrm_lookup(); + +create_our_window() +{ + XrmQuark instquarks[3], classquarks[3]; + register char *cp; + register int i, geomask; + int pixwidth, pixheight, xpos, ypos; + XSetWindowAttributes xswa; + u_long xswamask; + XColor bdcolor; + XClassHint xclasshint; + XWMHints wmhints; + XSizeHints wm_normal_hints; + + /* Determine our geometry */ + instquarks[0] = xrmquark_topinstance; + classquarks[0] = xrmquark_topclass; + classquarks[1] = instquarks[1] = XrmStringToQuark("geometry"); + instquarks[2] = classquarks[2] = NULLQUARK; + cp = xrm_lookup(instquarks, classquarks); + if (cp) { + geomask = XParseGeometry(cp, &xpos, &ypos, &pixwidth, + &pixheight); + free(cp); + } else + geomask = 0; + if (!(geomask & WidthValue)) + pixwidth = 176; + if (!(geomask & HeightValue)) + pixheight = 220; + if (!(geomask & XValue)) + xpos = 0; + else if (geomask & XNegative) + xpos += DisplayWidth(mydisplay, DefaultScreen(mydisplay)) - + pixwidth; + if (!(geomask & YValue)) + ypos = 0; + else if (geomask & YNegative) + ypos += DisplayHeight(mydisplay, DefaultScreen(mydisplay)) - + pixheight; + /* fill out XSetWindowAttributes */ + xswa.event_mask = 0; /* not interested in any events */ + xswamask = CWEventMask; + /* border color */ + classquarks[1] = instquarks[1] = XrmStringToQuark("borderColor"); + cp = xrm_lookup(instquarks, classquarks); + if (cp) { + i = XParseColor(mydisplay, DefaultColormap(mydisplay, + DefaultScreen(mydisplay)), cp, &bdcolor); + free(cp); + if (i) { + i = XAllocColor(mydisplay, DefaultColormap(mydisplay, + DefaultScreen(mydisplay)), &bdcolor); + if (i) { + xswa.border_pixel = bdcolor.pixel; + xswamask |= CWBorderPixel; + } + } + } + /* border width */ + classquarks[1] = instquarks[1] = XrmStringToQuark("borderWidth"); + cp = xrm_lookup(instquarks, classquarks); + if (cp) { + i = atoi(cp); + free(cp); + } else + i = 2; + /* go for it! */ + mainwindow = XCreateWindow(mydisplay, DefaultRootWindow(mydisplay), + xpos, ypos, pixwidth, pixheight, i, CopyFromParent, + InputOutput, CopyFromParent, xswamask, &xswa); + /* set window manager properties */ + xclasshint.res_name = proginstancename; + xclasshint.res_class = "LEDemu"; + XSetClassHint(mydisplay, mainwindow, &xclasshint); + wmhints.flags = InputHint | StateHint; + wmhints.input = False; + classquarks[1] = instquarks[1] = XrmStringToQuark("iconic"); + cp = xrm_lookup(instquarks, classquarks); + if (cp) { + i = parse_boolean_resource(cp); + free(cp); + } else + i = 0; + wmhints.initial_state = i ? IconicState : NormalState; + XSetWMHints(mydisplay, mainwindow, &wmhints); + if (geomask & (WidthValue|HeightValue)) + wm_normal_hints.flags = USSize; + else + wm_normal_hints.flags = PSize; + if (geomask & (XValue|YValue)) + wm_normal_hints.flags |= USPosition; + XSetWMNormalHints(mydisplay, mainwindow, &wm_normal_hints); +} + +set_initial_window_title() +{ + XrmQuark instquarks[3], classquarks[3]; + register char *cp; + char buf[256]; + + instquarks[0] = xrmquark_topinstance; + classquarks[0] = xrmquark_topclass; + instquarks[1] = XrmStringToQuark("title"); + classquarks[1] = XrmStringToQuark("Title"); + instquarks[2] = classquarks[2] = NULLQUARK; + cp = xrm_lookup(instquarks, classquarks); + if (cp) { + XStoreName(mydisplay, mainwindow, cp); + free(cp); + return; + } + XStoreName(mydisplay, mainwindow, "Emulated LCD"); +} + +set_initial_icon_name() +{ + XrmQuark instquarks[3], classquarks[3]; + register char *cp; + + instquarks[0] = xrmquark_topinstance; + classquarks[0] = xrmquark_topclass; + instquarks[1] = XrmStringToQuark("iconName"); + classquarks[1] = XrmStringToQuark("IconName"); + instquarks[2] = classquarks[2] = NULLQUARK; + cp = xrm_lookup(instquarks, classquarks); + if (cp) { + XSetIconName(mydisplay, mainwindow, cp); + free(cp); + return; + } + XSetIconName(mydisplay, mainwindow, proginstancename); +} + +create_mainwin_gc() +{ + XGCValues xgcval; + + xgcval.graphics_exposures = False; + mainwingc = XCreateGC(mydisplay, mainwindow, GCGraphicsExposures, + &xgcval); +} diff -r 000000000000 -r e7f1035f10d4 lcdemu/ximage.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lcdemu/ximage.c Wed Mar 14 18:16:45 2018 +0000 @@ -0,0 +1,59 @@ +/* + * LCDemu based on HECterm by the same author + * XImage conversion muck + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "globals.h" + +XImage * +convert_image_depth24(input, npix) + uint16_t *input; + int npix; +{ + uint32_t *imgbuf; + int i, in, r, g, b; + XImage *img; + + imgbuf = malloc(npix * 4); + if (!imgbuf) { + perror("malloc"); + exit(1); + } + for (i = 0; i < npix; i++) { + in = input[i]; + r = (in & 0xF800) << 8; + g = (in & 0x07E0) << 5; + b = (in & 0x001F) << 3; + imgbuf[i] = r | g | b; + } + img = XCreateImage(mydisplay, CopyFromParent, display_depth, ZPixmap, + 0, (char *) imgbuf, npix, 1, 32, 0); + if (!img) { + perror("XCreateImage"); + exit(1); + } + return(img); +} + +init_image_conversion() +{ + display_depth = DefaultDepth(mydisplay, DefaultScreen(mydisplay)); + switch (display_depth) { + case 24: + convert_function = convert_image_depth24; + break; + default: + fprintf(stderr, +"error: fc-lcdemu has not been adapted for X11 depth != 24, yours is %d\n", + display_depth); + exit(1); + } +} diff -r 000000000000 -r e7f1035f10d4 lcdemu/xrm.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lcdemu/xrm.c Wed Mar 14 18:16:45 2018 +0000 @@ -0,0 +1,97 @@ +/* + * LCDemu based on HECterm by the same author + * Xrm functions + */ + +#include +#include +#include +#include +#include +#include +#include +#include "globals.h" + +static char appdefaults_pathname[] = + "/usr/local/share/freecalypso/lcdemu-defaults"; + +load_resources() +{ + xrmquark_topclass = XrmStringToQuark("LCDemu"); + xrmquark_topinstance = XrmStringToQuark(proginstancename); + xrmdb_defaults = XrmGetFileDatabase(appdefaults_pathname); + xrmdb_displayres = + XrmGetStringDatabase(XResourceManagerString(mydisplay)); +} + +/* + * The following function looks up a resource in all of our databases + * and returns a pointer (char *) to the value in a malloced buffer that + * can be freed when it is no longer needed. My reading of X11R4 + * documentation indicates that resource values returned from Xrm functions + * are not necessarily NUL-terminated (no claim is made that they are + * and XrmValue structure has a size field), which is why I copy to + * my own buffer and NUL-terminate it there. + * + * Returns NULL pointer if not found in any of the databases. + */ +char * +xrm_lookup(instquarks, classquarks) + XrmQuark *instquarks, *classquarks; +{ + XrmRepresentation reptype; + XrmValue value; + register char *buf; + + if (XrmQGetResource(xrmdb_cmdline, instquarks, classquarks, &reptype, + &value)) + goto found; + if (XrmQGetResource(xrmdb_displayres, instquarks, classquarks, &reptype, + &value)) + goto found; + if (XrmQGetResource(xrmdb_defaults, instquarks, classquarks, &reptype, + &value)) + goto found; + return(NULL); +found: buf = malloc(value.size + 1); + if (!buf) { + perror("malloc"); + exit(1); + } + bcopy(value.addr, buf, value.size); + buf[value.size] = '\0'; + return(buf); +} + +parse_boolean_resource(str) + register char *str; +{ + if (!strcasecmp(str, "on") || !strcasecmp(str, "true") || + !strcasecmp(str, "yes")) + return(1); + if (!strcasecmp(str, "off") || !strcasecmp(str, "false") || + !strcasecmp(str, "no")) + return(0); + return(atoi(str)); +} + +get_boolean_resource(resource, def) + char *resource; + int def; +{ + XrmQuark instquarks[3], classquarks[3]; + register char *cp; + register int i; + + instquarks[0] = xrmquark_topinstance; + classquarks[0] = xrmquark_topclass; + classquarks[1] = instquarks[1] = XrmStringToQuark(resource); + instquarks[2] = classquarks[2] = NULLQUARK; + cp = xrm_lookup(instquarks, classquarks); + if (cp) { + i = parse_boolean_resource(cp); + free(cp); + } else + i = def; + return(i); +}