#include #include "mktclapp.h" #include #include #include #include #include /* Where's the standard definition for this? */ #define min(a,b) ((a) < (b) ? (a) : (b)) /* * Some useful hyperlinks: * * (find-node "(libc)Function Index") * (find-vldifile "tcl8.0-dev.list") * (eeman "Tcl_GetLongFromObj") * (eeman "Tcl_GetStringFromObj") * (eeman "Tcl_GetInt") * (find-tcltag "Tcl_CloseObjCmd") * (find-tcltag "Tcl_WrongNumArgs") * (find-tcltag "Tcl_GetChannel") * (find-tcltag "Channel") * (eeman "Tcl_GetChannel") * * (find-fline "~/MTA/") * (find-fline "~/MTA/new.c" "ET_OBJCOMMAND_initfontbuf") * (find-vldifile "tcl8.0-dev.list") * (eeman "Tcl_SetObjResult") * (eeman "Tcl_NewStringObj") * */ /* * * mktclapp support * */ #define ET_ERRORF(listargs) ({Et_ResultF listargs; return TCL_ERROR;}) #define ET_ERROR(str) ET_ERRORF((interp,str)) #define ET_ERROR1(str,a) ET_ERRORF((interp,str,a)) #define ET_ERROR2(str,a,b) ET_ERRORF((interp,str,a,b)) #define ET_ERROR3(str,a,b,c) ET_ERRORF((interp,str,a,b,c)) #define ET_ERROR4(str,a,b,c,d) ET_ERRORF((interp,str,a,b,c,d)) #define OARGV_STRING(n, lenptr) Tcl_GetStringFromObj(objv[n], lenptr) #define OARGV0 OARGV_STRING(0, 0) #define OARGV_INT(n) ({ \ int _tmpint; \ if (Tcl_GetIntFromObj(interp, objv[n], &_tmpint) != TCL_OK) \ ET_ERROR2("%s: arg %d not an int", OARGV0, n); \ _tmpint; \ }) #define ET_OARGSERROR(argstr) \ ET_ERROR2("wrong # args: should be \"%s %s\"", OARGV0, argstr) #define ET_ARGSERROR(argstr) \ ET_ERROR2("wrong # args: should be \"%s %s\"", argv[0], argstr) #define ET_ORETURN(data, len) \ Tcl_SetObjResult(interp, Tcl_NewStringObj(data, len)) /* * A special #define to get the nchars/nrows/data triples. * */ #define get_nchars_nrows_data_len(pnchars, pnrows, pdata) \ ({nchars = OARGV_INT(pnchars); \ if (nchars != 256 && nchars != 512) \ ET_ERROR("NCHARS must be 256 or 512"); \ nrows = OARGV_INT(pnrows); \ if (nrows < 1 || nrows > 32) \ ET_ERROR("NROWS must be in the range 1..32"); \ data = OARGV_STRING(pdata, &len); \ if (len != nchars * nrows) \ ET_ERROR2("DATA has len %d, should have been %d", \ len, nchars * nrows); \ }) /* * New Tcl commands: * * change_char nchar chardata nchars nrows data -> newdata * change_nchars newnchars nchars nrows data -> newdata * change_nrows newnrows nchars nrows data -> newdata * duplicate_rows data -> newdata * setfont channel nchars nrows data * tobinary rowdata rowdata ... -> chardata * vcsa2pnmdata rgb0 rgb1 ... rgb15 nchars nrows fontdata vcsadata * */ /* * change_char NCHAR CHARDATA NCHARS NROWS DATA -> NEWDATA * */ int ET_OBJCOMMAND_change_char(ET_OBJARGS) { int nchar, charlen, nchars, nrows, len; char *chardata, *data, newdata[512 * 32]; if(objc != 6) ET_OARGSERROR("NCHAR CHARDATA NCHARS NROWS DATA"); nchar = OARGV_INT(1); chardata = OARGV_STRING(2, &charlen); get_nchars_nrows_data_len(3, 4, 5); if (nchar < 0 || nchar >= nchars) ET_ERROR("NCHAR must be in the range 0..NCHARS-1"); if (charlen < 1 || charlen > 32) ET_ERROR("The lenght of CHARDATA must be in the range 1..32"); memcpy(newdata, data, nchars*nrows); memset(newdata + nchar*nrows, 0, nrows); memcpy(newdata + nchar*nrows, chardata, min(charlen, nrows)); ET_ORETURN(newdata, nchars * nrows); return TCL_OK; } /* * change_nchars NEWNCHARS NCHARS NROWS DATA -> NEWDATA * */ int ET_OBJCOMMAND_change_nchars(ET_OBJARGS) { int newnchars, nchars, nrows, len; char *data, newdata[512 * 32]; if(objc != 5) ET_OARGSERROR("NEWNCHARS NCHARS NROWS DATA"); newnchars = OARGV_INT(1); if (newnchars != 256 && newnchars != 512) ET_ERROR("NEWNCHARS must be 256 or 512"); get_nchars_nrows_data_len(2, 3, 4); memset(newdata, 0, newnchars * nrows); memcpy(newdata, data, min(newnchars, nchars) * nrows); ET_ORETURN(newdata, newnchars * nrows); return TCL_OK; } /* * change_nrows NEWNROWS NCHARS NROWS DATA -> NEWDATA * */ int ET_OBJCOMMAND_change_nrows(ET_OBJARGS) { int newnrows, nchars, nrows, len, i; char *data, newdata[512 * 32]; if(objc != 5) ET_OARGSERROR("NEWNROWS NCHARS NROWS DATA"); newnrows = OARGV_INT(1); if (newnrows < 1 || newnrows > 32) ET_ERROR("NEWNROWS must be in the range 1..32"); get_nchars_nrows_data_len(2, 3, 4); memset(newdata, 0, nchars * newnrows); for(i=0; i NEWDATA * */ int ET_OBJCOMMAND_duplicate_rows(ET_OBJARGS) { int len, i; char *data, newdata[512 * 32], *p1, *p2; if(objc != 2) ET_OARGSERROR("DATA"); data = OARGV_STRING(1, &len); if (len > 512 * 16) ET_ERROR("Input data too long (limit 512*16 bytes)"); for(i=0, p1=data, p2=newdata; i CHARDATA * * We only consider the last bit in each char of a ROWDATA. * Remember that "0" and " " have even ascii codes, "1" and "o" have * odd ascii codes. * */ int ET_OBJCOMMAND_tobinary(ET_OBJARGS) { int n, len, i, byte, bit; char *rowdata, chardata[512*32]; if(objc < 1+1 || objc > 512*32+1) ET_OARGSERROR("ROWDATA ... (repeated 1 to 512*32 times)"); for(n=0; n0; ++i, bit>>=1) byte |= rowdata[i]&1?bit:0; chardata[n] = byte; } ET_ORETURN(chardata, n); return TCL_OK; } /* (+ 2 (* (+ 1 (* 6 8 80)) 8 50)) */ /* (+ 2 (* (+ 1 (* 6 8 132)) 8 50)) */ /* °°±±ÛÛ ²² */ /* (find-fline "~/ICON/vcsa2pnm.icn") */ #define ASCS_PER_PIXEL 6 #define PNMBUFFERSIZE ((ASCS_PER_PIXEL*9*132+1)*60*8+2) #define APPEND(str) (memcpy(p, str, strlen(str)), p+=strlen(str)) /* * vcsa2pnmdata RGB0 RGB1 ... RGB15 NCHARS NROWS FONTDATA VCSADATA * Used to make screenshots of text screens. * (find-k22file "drivers/char/vc_screen.c" "4 bytes") * At this time we just guess it's 80x50. * */ int ET_OBJCOMMAND_vcsa2pnmdata(ET_OBJARGS) { char pnmbuffer[PNMBUFFERSIZE]; char *p = pnmbuffer; unsigned char *vcsabuf; char *colors[16], *fgcolor, *bgcolor; int i, tmplen, v, pv, h, pbyte, color, pbit; int nchars, nrows, len; char *data; /* fontdata */ if(objc != 21) ET_OARGSERROR("RGB0 RGB1 ... RGB15 NCHARS NROWS FONTDATA VCSADATA"); for(i=0; i<16; ++i) { colors[i] = OARGV_STRING(1+i, &tmplen); if(tmplen>ASCS_PER_PIXEL) ET_ERROR4("color %i ({%s}) has lenght %d; max is %d", i, colors[i], tmplen, ASCS_PER_PIXEL); } get_nchars_nrows_data_len(17, 18, 19); vcsabuf = OARGV_STRING(20, 0) + 4; /* skip #lines,#cols,x,y */ for(v=0; v<50; ++v) { for(pv=0; pv<8; ++pv) { for(h=0; h<80; ++h) { pbyte = data[vcsabuf[v*80*2 + h*2]*nrows + pv]; color = vcsabuf[v*80*2 + h*2 + 1]; fgcolor = colors[color&0x0F]; bgcolor = colors[(color&0xF0)>>4]; for(pbit=128; pbit!=0; pbit>>=1) { APPEND(pbyte&pbit?fgcolor:bgcolor); } APPEND((pbyte&0x07)==0x07?fgcolor:bgcolor); /* 9th column */ APPEND("\n"); /* after every row of a char a newline */ } APPEND("\n"); /* after every row an extra newline */ } APPEND("\n"); /* after every row of chars another newline */ } *p=0; /* end of string */ Et_ResultF(interp, "%s", pnmbuffer); return TCL_OK; }