commit 16a709666981e77a00a88a87b286b586ac77ffdc from: rsc date: Sun Nov 23 18:15:43 2003 UTC Add drawsetlabel(Display*, char*). Turn window destruction into "hangup" note. Fix (?) snarf buffer management. Add latin1 keyboard translation. commit - 986b36bccd134726eea42f2cfabff2943d729ac4 commit + 16a709666981e77a00a88a87b286b586ac77ffdc blob - a9ae96af920015cf6707dea61ee564803d850c7c blob + 029f0aed6ed69f418900d5495e8e99cd31f6f57e --- include/draw.h +++ include/draw.h @@ -219,7 +219,7 @@ struct RGB * * given char c, Subfont *f, Fontchar *i, and Point p, one says * i = f->info+c; - * draw(b, Rect(p.x+i->left, p.y+i->top, + * void(b, Rect(p.x+i->left, p.y+i->top, * p.x+i->left+((i+1)->x-i->x), p.y+i->bottom), * color, f->bits, Pt(i->x, i->top)); * p.x += i->width; @@ -336,6 +336,7 @@ extern int writeimage(int, Image*, int); extern Image* namedimage(Display*, char*); extern int nameimage(Image*, char*, int); extern Image* allocimagemix(Display*, u32int, u32int); +extern int drawsetlabel(Display*, char*); /* * Colors @@ -529,3 +530,4 @@ void drawtopwindow(void); */ int _drawmsgread(Display*, void*, int); int _drawmsgwrite(Display*, void*, int); +int _latin1(Rune*, int); blob - 8e932ee3f6458f57c5c03b515708da8df8d494ee (mode 644) blob + /dev/null --- src/libdraw/Makefile +++ /dev/null @@ -1,123 +0,0 @@ -PLAN9=../.. -include $(PLAN9)/src/Makehdr - -LIB=libdraw.a - -OFILES=\ - alloc.$O\ - allocimagemix.$O\ - arith.$O\ - bezier.$O\ - border.$O\ - buildfont.$O\ - bytesperline.$O\ - chan.$O\ - cloadimage.$O\ - computil.$O\ - creadimage.$O\ - debug.$O\ - defont.$O\ - draw.$O\ - drawrepl.$O\ - egetrect.$O\ - ellipse.$O\ - emenuhit.$O\ - font.$O\ - freesubfont.$O\ - getdefont.$O\ - getrect.$O\ - getsubfont.$O\ - icossin.$O\ - icossin2.$O\ - init.$O\ - line.$O\ - loadimage.$O\ - menuhit.$O\ - mkfont.$O\ - openfont.$O\ - poly.$O\ - readcolmap.$O\ - readimage.$O\ - readsubfont.$O\ - rectclip.$O\ - replclipr.$O\ - rgb.$O\ - string.$O\ - stringbg.$O\ - stringsubfont.$O\ - stringwidth.$O\ - subfont.$O\ - subfontcache.$O\ - subfontname.$O\ - unloadimage.$O\ - window.$O\ - writecolmap.$O\ - writeimage.$O\ - writesubfont.$O\ - md-alloc.$O\ - md-arc.$O\ - md-cload.$O\ - md-cmap.$O\ - md-cread.$O\ - md-defont.$O\ - md-draw.$O\ - md-ellipse.$O\ - md-fillpoly.$O\ - md-hwdraw.$O\ - md-iprint.$O\ - md-line.$O\ - md-load.$O\ - md-openmemsubfont.$O\ - md-poly.$O\ - md-read.$O\ - md-string.$O\ - md-subfont.$O\ - md-unload.$O\ - md-write.$O\ - ml-draw.$O\ - ml-lalloc.$O\ - ml-layerop.$O\ - ml-ldelete.$O\ - ml-lhide.$O\ - ml-line.$O\ - ml-load.$O\ - ml-lorigin.$O\ - ml-lsetrefresh.$O\ - ml-ltofront.$O\ - ml-ltorear.$O\ - ml-unload.$O\ - x11-alloc.$O\ - x11-cload.$O\ - x11-draw.$O\ - x11-event.$O\ - x11-fill.$O\ - x11-get.$O\ - x11-init.$O\ - x11-itrans.$O\ - x11-keyboard.$O\ - x11-load.$O\ - x11-mouse.$O\ - x11-pixelbits.$O\ - x11-unload.$O\ - x11-wsys.$O\ - devdraw.$O\ - unix.$O\ - -HFILES=\ - $(PLAN9)/include/draw.h\ - $(PLAN9)/include/memdraw.h\ - $(PLAN9)/include/memlayer.h\ - $(PLAN9)/include/event.h\ - $(PLAN9)/include/cursor.h\ - $(PLAN9)/include/mouse.h\ - $(PLAN9)/include/keyboard.h\ - x11-inc.h\ - x11-memdraw.h\ - -CFLAGS+=-I$(X11)/include - -include $(PLAN9)/src/Makesyslib - -test: test.o $(LIB) - gcc -o test test.o -L$(PLAN9) -ldraw -l9 -lfmt -lutf -L$(X11)/lib -lX11 -lm - blob - /dev/null blob + f57345675373cb5b26182c8ef0601e145baded60 (mode 644) --- /dev/null +++ src/libdraw/latin1.c @@ -0,0 +1,178 @@ +#include +#include +#include + +/* + * The code makes two assumptions: strlen(ld) is 1 or 2; latintab[i].ld can be a + * prefix of latintab[j].ld only when j", { 0x21D2, 0x2255, 0x2261, 0x229C, 0x22DC, 0x22DD, }, + "V", "=", { 0x21D0, }, + "7", "8", { 0x215E, }, + "5", "68", { 0x215A, 0x215D, }, + "4", "5", { 0x2158, }, + "R", "R", { 0x211D, }, + "Q", "Q", { 0x211A, }, + "P", "P", { 0x2119, }, + "C", "CAU", { 0x2102, 0x22C2, 0x22C3, }, + "e", "nmsl", { 0x2013, 0x2014, 0x2205, 0x22EF, }, + "b", "u0123456789+-=()kqrbnp", { 0x2022, 0x2080, 0x2081, 0x2082, 0x2083, 0x2084, 0x2085, 0x2086, 0x2087, 0x2088, 0x2089, 0x208A, 0x208B, 0x208C, 0x208D, 0x208E, 0x265A, 0x265B, 0x265C, 0x265D, 0x265E, 0x265F, }, + "@e", "h", { 0x44D, }, + "@\'", "\'", { 0x44A, }, + "@s", "hc", { 0x448, 0x449, }, + "@c", "h", { 0x447, }, + "@t", "s", { 0x446, }, + "@k", "h", { 0x445, }, + "@z", "h", { 0x436, }, + "@y", "euao", { 0x435, 0x44E, 0x44F, 0x451, }, + "@E", "Hh", { 0x42D, 0x42D, }, + "@S", "HhCc", { 0x428, 0x428, 0x429, 0x429, }, + "@C", "Hh", { 0x427, 0x427, }, + "@T", "Ss", { 0x426, 0x426, }, + "@K", "Hh", { 0x425, 0x425, }, + "@Z", "Hh", { 0x416, 0x416, }, + "@@", "EZKSTYezksty\'", { 0x415, 0x417, 0x41A, 0x421, 0x422, 0x42B, 0x435, 0x437, 0x43A, 0x441, 0x442, 0x44B, 0x44C, }, + "@Y", "OoEeUuAa", { 0x401, 0x401, 0x415, 0x415, 0x42E, 0x42E, 0x42F, 0x42F, }, + "@", "ABVGDIJLMNOPRUFXabvgdijlmnoprufx", { 0x410, 0x411, 0x412, 0x413, 0x414, 0x418, 0x419, 0x41B, 0x41C, 0x41D, 0x41E, 0x41F, 0x420, 0x423, 0x424, 0x425, 0x430, 0x431, 0x432, 0x433, 0x434, 0x438, 0x439, 0x43B, 0x43C, 0x43D, 0x43E, 0x43F, 0x440, 0x443, 0x444, 0x445, }, + "*", "ABGDEZYHIKLMNCOPRSTUFXQWabgdezyhiklmncoprstufxqw*", { 0x391, 0x392, 0x393, 0x394, 0x395, 0x396, 0x397, 0x398, 0x399, 0x39A, 0x39B, 0x39C, 0x39D, 0x39E, 0x39F, 0x3A0, 0x3A1, 0x3A3, 0x3A4, 0x3A5, 0x3A6, 0x3A7, 0x3A8, 0x3A9, 0x3B1, 0x3B2, 0x3B3, 0x3B4, 0x3B5, 0x3B6, 0x3B7, 0x3B8, 0x3B9, 0x3BA, 0x3BB, 0x3BC, 0x3BD, 0x3BE, 0x3BF, 0x3C0, 0x3C1, 0x3C3, 0x3C4, 0x3C5, 0x3C6, 0x3C7, 0x3C8, 0x3C9, 0x2217, }, + "G", "-", { 0x1E4, }, + "N", "JjN", { 0x1CA, 0x1CB, 0x2115, }, + "2", "-35", { 0x1BB, 0x2154, 0x2156, }, + "z", "-", { 0x1B6, }, + "Z", "-Z", { 0x1B5, 0x2124, }, + "Y", "R", { 0x1A6, }, + "h", "v-", { 0x195, 0x210F, }, + "$*", "hfk", { 0x3D1, 0x3D5, 0x3F0, }, + "$", "fVavgHILlpRBeEFMo", { 0x192, 0x1B2, 0x251, 0x28B, 0x210A, 0x210B, 0x2110, 0x2112, 0x2113, 0x2118, 0x211B, 0x212C, 0x212F, 0x2130, 0x2131, 0x2133, 0x2134, }, + "t", "-smefu", { 0x167, 0x3C2, 0x2122, 0x2203, 0x2234, 0x22A2, }, + "T", "-u", { 0x166, 0x22A8, }, + "L", "-Jj&|", { 0x141, 0x1C7, 0x1C8, 0x22C0, 0x22C1, }, + "i", "j-fsbp", { 0x133, 0x268, 0x221E, 0x222B, 0x2286, 0x2287, }, + "I", "J-", { 0x132, 0x197, }, + "H", "-H", { 0x126, 0x210D, }, + "v\"", "Uu", { 0x1D9, 0x1DA, }, + "v", "CcDdEeLlNnRrSsTtZzAaIiOoUuGgKkj", { 0x10C, 0x10D, 0x10E, 0x10F, 0x11A, 0x11B, 0x13D, 0x13E, 0x147, 0x148, 0x158, 0x159, 0x160, 0x161, 0x164, 0x165, 0x17D, 0x17E, 0x1CD, 0x1CE, 0x1CF, 0x1D0, 0x1D1, 0x1D2, 0x1D3, 0x1D4, 0x1E6, 0x1E7, 0x1E8, 0x1E9, 0x1F0, }, + "u", "AEeGgIiOoUu-a", { 0x102, 0x114, 0x115, 0x11E, 0x11F, 0x12C, 0x12D, 0x14E, 0x14F, 0x16C, 0x16D, 0x289, 0x2191, }, + ":", "-=)", { 0xF7, 0x2254, 0x263A, }, + "a", "ebn", { 0xE6, 0x2194, 0x2220, }, + "/", "Oo", { 0xD8, 0xF8, }, + "Dv", "Zz", { 0x1C4, 0x1C5, }, + "D", "-e", { 0xD0, 0x2206, }, + "A", "E", { 0xC6, }, + "o", "AaeUuiO", { 0xC5, 0xE5, 0x153, 0x16E, 0x16F, 0x1A3, 0x229A, }, + "~!", "=", { 0x2246, }, + "~", "ANOanoIiUu-=~", { 0xC3, 0xD1, 0xD5, 0xE3, 0xF1, 0xF5, 0x128, 0x129, 0x168, 0x169, 0x2243, 0x2245, 0x2248, }, + "^", "AEIOUaeiouCcGgHhJjSsWwYy", { 0xC2, 0xCA, 0xCE, 0xD4, 0xDB, 0xE2, 0xEA, 0xEE, 0xF4, 0xFB, 0x108, 0x109, 0x11C, 0x11D, 0x124, 0x125, 0x134, 0x135, 0x15C, 0x15D, 0x174, 0x175, 0x176, 0x177, }, + "`\"", "Uu", { 0x1DB, 0x1DC, }, + "`", "AEIOUaeiou", { 0xC0, 0xC8, 0xCC, 0xD2, 0xD9, 0xE0, 0xE8, 0xEC, 0xF2, 0xF9, }, + "?", "?!", { 0xBF, 0x203D, }, + "3", "458", { 0xBE, 0x2157, 0x215C, }, + "1", "423568", { 0xBC, 0xBD, 0x2153, 0x2155, 0x2159, 0x215B, }, + ">!", "=~", { 0x2269, 0x22E7, }, + ">", ">=~<", { 0xBB, 0x2265, 0x2273, 0x2277, }, + ",", ",CcAaEeGgIiKkLlNnRrSsTtUuOo", { 0xB8, 0xC7, 0xE7, 0x104, 0x105, 0x118, 0x119, 0x122, 0x123, 0x12E, 0x12F, 0x136, 0x137, 0x13B, 0x13C, 0x145, 0x146, 0x156, 0x157, 0x15E, 0x15F, 0x162, 0x163, 0x172, 0x173, 0x1EA, 0x1EB, }, + ".", ".CcEeGgILlZzO", { 0xB7, 0x10A, 0x10B, 0x116, 0x117, 0x120, 0x121, 0x130, 0x13F, 0x140, 0x17B, 0x17C, 0x2299, }, + "p", "gOdrt", { 0xB6, 0x2117, 0x2202, 0x220F, 0x221D, }, + "m", "iuo", { 0xB5, 0xD7, 0x2208, }, + "\'\"", "Uu", { 0x1D7, 0x1D8, }, + "\'", "\'AEIOUYaeiouyCcgLlNnRrSsZz", { 0xB4, 0xC1, 0xC9, 0xCD, 0xD3, 0xDA, 0xDD, 0xE1, 0xE9, 0xED, 0xF3, 0xFA, 0xFD, 0x106, 0x107, 0x123, 0x139, 0x13A, 0x143, 0x144, 0x154, 0x155, 0x15A, 0x15B, 0x179, 0x17A, }, + "+", "-O", { 0xB1, 0x2295, }, + "dv", "z", { 0x1C6, }, + "d", "e-zgda", { 0xB0, 0xF0, 0x2A3, 0x2020, 0x2021, 0x2193, }, + "_,", "Oo", { 0x1EC, 0x1ED, }, + "_.", "Aa", { 0x1E0, 0x1E1, }, + "_\"", "UuAa", { 0x1D5, 0x1D6, 0x1DE, 0x1DF, }, + "_", "_AaEeIiOoUu", { 0xAF, 0x100, 0x101, 0x112, 0x113, 0x12A, 0x12B, 0x14C, 0x14D, 0x16A, 0x16B, }, + "r", "O\'\"", { 0xAE, 0x2019, 0x201D, }, + "-*", "l", { 0x19B, }, + "-", "-Dd:HLlTtbIZz2Ggiuh>+~O", { 0xAD, 0xD0, 0xF0, 0xF7, 0x126, 0x141, 0x142, 0x166, 0x167, 0x180, 0x197, 0x1B5, 0x1B6, 0x1BB, 0x1E4, 0x1E5, 0x268, 0x289, 0x210F, 0x2192, 0x2213, 0x2242, 0x2296, }, + "n", "oj", { 0xAC, 0x1CC, }, + "", { 0xAB, 0x2190, 0x2264, 0x2272, 0x2276, }, + "s", "a231os0456789+-=()nturbp", { 0xAA, 0xB2, 0xB3, 0xB9, 0xBA, 0xDF, 0x2070, 0x2074, 0x2075, 0x2076, 0x2077, 0x2078, 0x2079, 0x207A, 0x207B, 0x207C, 0x207D, 0x207E, 0x207F, 0x220D, 0x2211, 0x221A, 0x2282, 0x2283, }, + "O", "crEIp+-x/.o*=", { 0xA9, 0xAE, 0x152, 0x1A2, 0x2117, 0x2295, 0x2296, 0x2297, 0x2298, 0x2299, 0x229A, 0x229B, 0x229C, }, + "\"*", "IUiu", { 0x3AA, 0x3AB, 0x3CA, 0x3CB, }, + "\"", "\"AEIOUaeiouyY", { 0xA8, 0xC4, 0xCB, 0xCF, 0xD6, 0xDC, 0xE4, 0xEB, 0xEF, 0xF6, 0xFC, 0xFF, 0x178, }, + "S", "S", { 0xA7, }, + "|", "|Pp", { 0xA6, 0xDE, 0xFE, }, + "y", "$", { 0xA5, }, + "g", "$-r", { 0xA4, 0x1E5, 0x2207, }, + "l", "$-j\'\"&|z", { 0xA3, 0x142, 0x1C9, 0x2018, 0x201C, 0x2227, 0x2228, 0x22C4, }, + "c", "$Oaug", { 0xA2, 0xA9, 0x2229, 0x222A, 0x2245, }, + "!~", "-=~", { 0x2244, 0x2247, 0x2249, }, + "!", "!?m=<>bp", { 0xA1, 0x203D, 0x2209, 0x2260, 0x226E, 0x226F, 0x2284, 0x2285, }, + 0, 0, { 0, } +}; + +/* + * Given 5 characters k[0]..k[4], find the rune or return -1 for failure. + */ +static long +unicode(Rune *k) +{ + long i, c; + + k++; /* skip 'X' */ + c = 0; + for(i=0; i<4; i++,k++){ + c <<= 4; + if('0'<=*k && *k<='9') + c += *k-'0'; + else if('a'<=*k && *k<='f') + c += 10 + *k-'a'; + else if('A'<=*k && *k<='F') + c += 10 + *k-'A'; + else + return -1; + } + return c; +} + +/* + * Given n characters k[0]..k[n-1], find the corresponding rune or return -1 for + * failure, or something < -1 if n is too small. In the latter case, the result + * is minus the required n. + */ +int +_latin1(Rune *k, int n) +{ + struct cvlist *l; + int c; + char* p; + + if(k[0] == 'X'){ + if(n>=5) + return unicode(k); + else + return -5; + } + + for(l=latintab; l->ld!=0; l++) + if(k[0] == l->ld[0]){ + if(n == 1) + return -2; + if(l->ld[1] == 0) + c = k[1]; + else if(l->ld[1] != k[1]) + continue; + else if(n == 2) + return -3; + else + c = k[2]; + for(p=l->si; *p!=0; p++) + if(*p == c) + return l->so[p - l->si]; + return -1; + } + return -1; +} blob - /dev/null blob + 7c5e9371f6af4723e673e3ee935c02bc0deeb733 (mode 644) --- /dev/null +++ src/libdraw/mkfile @@ -0,0 +1,124 @@ +PLAN9=../.. +<$PLAN9/src/mkhdr + +LIB=libdraw.a + +OFILES=\ + alloc.$O\ + allocimagemix.$O\ + arith.$O\ + bezier.$O\ + border.$O\ + buildfont.$O\ + bytesperline.$O\ + chan.$O\ + cloadimage.$O\ + computil.$O\ + creadimage.$O\ + debug.$O\ + defont.$O\ + draw.$O\ + drawrepl.$O\ + egetrect.$O\ + ellipse.$O\ + emenuhit.$O\ + font.$O\ + freesubfont.$O\ + getdefont.$O\ + getrect.$O\ + getsubfont.$O\ + icossin.$O\ + icossin2.$O\ + init.$O\ + line.$O\ + latin1.$O\ + loadimage.$O\ + menuhit.$O\ + mkfont.$O\ + openfont.$O\ + poly.$O\ + readcolmap.$O\ + readimage.$O\ + readsubfont.$O\ + rectclip.$O\ + replclipr.$O\ + rgb.$O\ + string.$O\ + stringbg.$O\ + stringsubfont.$O\ + stringwidth.$O\ + subfont.$O\ + subfontcache.$O\ + subfontname.$O\ + unloadimage.$O\ + window.$O\ + writecolmap.$O\ + writeimage.$O\ + writesubfont.$O\ + md-alloc.$O\ + md-arc.$O\ + md-cload.$O\ + md-cmap.$O\ + md-cread.$O\ + md-defont.$O\ + md-draw.$O\ + md-ellipse.$O\ + md-fillpoly.$O\ + md-hwdraw.$O\ + md-iprint.$O\ + md-line.$O\ + md-load.$O\ + md-openmemsubfont.$O\ + md-poly.$O\ + md-read.$O\ + md-string.$O\ + md-subfont.$O\ + md-unload.$O\ + md-write.$O\ + ml-draw.$O\ + ml-lalloc.$O\ + ml-layerop.$O\ + ml-ldelete.$O\ + ml-lhide.$O\ + ml-line.$O\ + ml-load.$O\ + ml-lorigin.$O\ + ml-lsetrefresh.$O\ + ml-ltofront.$O\ + ml-ltorear.$O\ + ml-unload.$O\ + x11-alloc.$O\ + x11-cload.$O\ + x11-draw.$O\ + x11-event.$O\ + x11-fill.$O\ + x11-get.$O\ + x11-init.$O\ + x11-itrans.$O\ + x11-keyboard.$O\ + x11-load.$O\ + x11-mouse.$O\ + x11-pixelbits.$O\ + x11-unload.$O\ + x11-wsys.$O\ + devdraw.$O\ + unix.$O\ + +HFILES=\ + $PLAN9/include/draw.h\ + $PLAN9/include/memdraw.h\ + $PLAN9/include/memlayer.h\ + $PLAN9/include/event.h\ + $PLAN9/include/cursor.h\ + $PLAN9/include/mouse.h\ + $PLAN9/include/keyboard.h\ + x11-inc.h\ + x11-memdraw.h\ + +CFLAGS=$CFLAGS -I$X11/include + +<$PLAN9/src/mksyslib + +test: test.o $LIB + gcc -o test test.o -L$PLAN9 -ldraw -l9 -lfmt -lutf -L$X11/lib -lX11 -lm + blob - 1361b42e285ef00cdbd0e28a62b1588e70616511 blob + 408eb4191aba4f1c8d5f257e4bb49d95b407eab6 --- src/libdraw/x11-event.c +++ src/libdraw/x11-event.c @@ -36,6 +36,7 @@ eflush(void) ulong eread(ulong keys, Event *e) { + int r; ulong xmask; XEvent xevent; @@ -45,8 +46,13 @@ eread(ulong keys, Event *e) if(keys&Emouse) xmask |= MouseMask|StructureNotifyMask; - if(keys&Ekeyboard) + if(keys&Ekeyboard){ xmask |= KeyPressMask; + if((r = xtoplan9kbd(nil)) >= 0){ + e->kbdc = r; + return Ekeyboard; + } + } XSelectInput(_x.display, _x.drawable, xmask); again: @@ -56,6 +62,10 @@ again: case Expose: xexpose(&xevent, _x.display); goto again; + case DestroyNotify: + if(xdestroy(&xevent, _x.display)) + postnote(PNGROUP, getpgrp(), "hangup"); + goto again; case ConfigureNotify: if(xconfigure(&xevent, _x.display)) eresized(1); @@ -63,7 +73,7 @@ again: case ButtonPress: case ButtonRelease: case MotionNotify: - if(xtoplan9mouse(&xevent, &e->mouse) < 0) + if(xtoplan9mouse(_x.display, &xevent, &e->mouse) < 0) goto again; return Emouse; case KeyPress: @@ -126,7 +136,7 @@ ecanmouse(void) eflush(); again: if(XCheckWindowEvent(_x.display, _x.drawable, MouseMask, &xe)){ - if(xtoplan9mouse(&xe, &m) < 0) + if(xtoplan9mouse(_x.display, &xe, &m) < 0) goto again; XPutBackEvent(_x.display, &xe); return 1; @@ -138,8 +148,13 @@ int ecankbd(void) { XEvent xe; + int r; eflush(); + if((r = xtoplan9kbd(nil)) >= 0){ + xtoplan9kbd((XEvent*)-1); + return 1; + } again: if(XCheckWindowEvent(_x.display, _x.drawable, KeyPressMask, &xe)){ if(xtoplan9kbd(&xe) == -1) blob - 28f6ae4009c89b8dcb73e4f4991a313c6ba6f4f7 blob + e402dee28d0b8ae9ee607fd255b692ed00698c56 --- src/libdraw/x11-init.c +++ src/libdraw/x11-init.c @@ -100,6 +100,8 @@ getwindow(Display *d, int ref) { Image *i; + if(_x.destroyed) + postnote(PNGROUP, getpgrp(), "hangup"); if(xreplacescreenimage() == 0) return 0; freeimage(d->screenimage); @@ -124,7 +126,7 @@ static int xioerror(XDisplay *d) { print("X I/O error\n"); - exit(1); + abort(); return -1; } @@ -365,6 +367,11 @@ xattach(char *label) XFlush(_x.display); /* + * Look up clipboard atom. + */ + _x.clipboard = XInternAtom(_x.display, "CLIPBOARD", True); + + /* * Lots of display connections for various procs. */ _x.kbdcon = XOpenDisplay(NULL); @@ -386,6 +393,46 @@ fprint(2, "%r\n"); */ XCloseDisplay(_x.display); return nil; +} + +int +drawsetlabel(Display *d, char *label) +{ + char *argv[2]; + XClassHint classhint; + XTextProperty name; + + /* + * Label and other properties required by ICCCCM. + */ + memset(&name, 0, sizeof name); + if(label == nil) + label = "pjw-face-here"; + name.value = (uchar*)label; + name.encoding = XA_STRING; + name.format = 8; + name.nitems = strlen(name.value); + + memset(&classhint, 0, sizeof classhint); + classhint.res_name = label; + classhint.res_class = label; + + argv[0] = label; + argv[1] = nil; + + XSetWMProperties( + _x.display, /* display */ + _x.drawable, /* window */ + &name, /* XA_WM_NAME property */ + &name, /* XA_WM_ICON_NAME property */ + argv, /* XA_WM_COMMAND */ + 1, /* argc */ + nil, /* XA_WM_NORMAL_HINTS */ + nil, /* XA_WM_HINTS */ + &classhint /* XA_WM_CLASSHINTS */ + ); + XFlush(_x.display); + return 0; } /* @@ -601,6 +648,19 @@ xexpose(XEvent *e, XDisplay *xd) Dx(r), Dy(r), r.min.x, r.min.y); XSync(xd, False); qunlock(&_x.screenlock); +} + +int +xdestroy(XEvent *e, XDisplay *xd) +{ + XDestroyWindowEvent *xe; + + xe = (XDestroyWindowEvent*)e; + if(xe->window == _x.drawable){ + _x.destroyed = 1; + return 1; + } + return 0; } int blob - 35fd31ea2a07675971e1e83da45b975e003357f6 blob + b4d9e6899a00ab0d7298d53d4e2589c9143ce72d --- src/libdraw/x11-itrans.c +++ src/libdraw/x11-itrans.c @@ -11,8 +11,8 @@ #include #include "x11-memdraw.h" -int -xtoplan9kbd(XEvent *e) +static int +_xtoplan9kbd(XEvent *e) { int ind, k, md; @@ -117,16 +117,82 @@ xtoplan9kbd(XEvent *e) return k; } +static Rune* +xtoplan9latin1(XEvent *e) +{ + static Rune k[10]; + static int alting, nk; + int n; + int r; + + r = _xtoplan9kbd(e); + if(r < 0) + return nil; + if(alting){ + k[nk++] = r; + n = _latin1(k, nk); + if(n > 0){ + alting = 0; + k[0] = n; + k[1] = 0; + return k; + } + if(n == -1){ + alting = 0; + k[nk] = 0; + return k; + } + /* n < -1, need more input */ + return nil; + }else if(r == Kalt){ + alting = 1; + nk = 0; + return nil; + }else{ + k[0] = r; + k[1] = 0; + return k; + } +} + int -xtoplan9mouse(XEvent *e, Mouse *m) +xtoplan9kbd(XEvent *e) { + static Rune *r; + + if(e == (XEvent*)-1){ + assert(r); + r--; + return 0; + } + if(e) + r = xtoplan9latin1(e); + if(r && *r) + return *r++; + return -1; +} + +int +xtoplan9mouse(XDisplay *xd, XEvent *e, Mouse *m) +{ int s; XButtonEvent *be; XMotionEvent *me; + + if(_x.putsnarf != _x.assertsnarf){ + _x.assertsnarf = _x.putsnarf; + XSetSelectionOwner(_x.mousecon, XA_PRIMARY, _x.drawable, CurrentTime); + if(_x.clipboard != None) + XSetSelectionOwner(_x.mousecon, _x.clipboard, _x.drawable, CurrentTime); + XFlush(xd); + } switch(e->type){ case ButtonPress: be = (XButtonEvent*)e; + /* Fake message, just sent to make us announce snarf. */ + if(be->send_event && be->state==~0 && be->button==~0) + return -1; /* BUG? on mac need to inherit these from elsewhere? */ m->xy.x = be->x; m->xy.y = be->y; @@ -265,34 +331,55 @@ char* xgetsnarf(XDisplay *xd) { uchar *data, *xdata; - Atom type; + Atom clipboard, type, prop; ulong len, lastlen, dummy; int fmt, i; XWindow w; qlock(&clip.lk); + /* + * Is there a primary selection (highlighted text in an xterm)? + */ + clipboard = XA_PRIMARY; w = XGetSelectionOwner(xd, XA_PRIMARY); if(w == _x.drawable){ + mine: data = (uchar*)strdup(clip.buf); goto out; } + + /* + * If not, is there a clipboard selection? + */ + if(w == None && _x.clipboard != None){ + clipboard = _x.clipboard; + w = XGetSelectionOwner(xd, _x.clipboard); + if(w == _x.drawable) + goto mine; + } + + /* + * If not, give up. + */ if(w == None){ data = nil; goto out; } + /* * We should be waiting for SelectionNotify here, but it might never - * come, and we have no way to time out. Instead, we will zero the - * property, request our buddy to fill it in for us, and wait until - * he's done. + * come, and we have no way to time out. Instead, we will clear + * local property #1, request our buddy to fill it in for us, and poll + * until he's done or we get tired of waiting. */ - XChangeProperty(xd, _x.drawable, XA_PRIMARY, XA_STRING, 8, PropModeReplace, (uchar*)"", 0); - XConvertSelection(xd, XA_PRIMARY, XA_STRING, None, _x.drawable, CurrentTime); + prop = 1; + XChangeProperty(xd, _x.drawable, prop, XA_STRING, 8, PropModeReplace, (uchar*)"", 0); + XConvertSelection(xd, clipboard, XA_STRING, prop, _x.drawable, CurrentTime); XFlush(xd); lastlen = 0; - for(i=0; i<30; i++){ + for(i=0; i<10 || (lastlen!=0 && i<30); i++){ usleep(100*1000); - XGetWindowProperty(xd, _x.drawable, XA_STRING, 0, 0, 0, AnyPropertyType, + XGetWindowProperty(xd, _x.drawable, prop, 0, 0, 0, AnyPropertyType, &type, &fmt, &dummy, &len, &data); if(lastlen == len && len > 0) break; @@ -304,7 +391,7 @@ xgetsnarf(XDisplay *xd) } /* get the property */ data = nil; - XGetWindowProperty(xd, _x.drawable, XA_STRING, 0, SnarfSize/4, 0, + XGetWindowProperty(xd, _x.drawable, prop, 0, SnarfSize/sizeof(ulong), 0, AnyPropertyType, &type, &fmt, &len, &dummy, &xdata); if(type != XA_STRING || len == 0){ if(xdata) @@ -325,16 +412,25 @@ out: void xputsnarf(XDisplay *xd, char *data) { + XButtonEvent e; + if(strlen(data) >= SnarfSize) return; qlock(&clip.lk); strcpy(clip.buf, data); - /* - * BUG: This is wrong. Instead, we should send an event to the - * mouse connection telling it to call XSetSelectionOwner. - */ - XSetSelectionOwner(_x.mousecon, XA_PRIMARY, _x.drawable, CurrentTime); + + /* leave note for mouse proc to assert selection ownership */ + _x.putsnarf++; + + /* send mouse a fake event so snarf is announced */ + memset(&e, 0, sizeof e); + e.type = ButtonPress; + e.window = _x.drawable; + e.state = ~0; + e.button = ~0; + XSendEvent(xd, _x.drawable, True, ButtonPressMask, (XEvent*)&e); XFlush(xd); + qunlock(&clip.lk); } blob - 92b57814c987dd9e49e76ce9a33b158f1cf87ba7 blob + 443074e994b4c4c3aa1bda37854f6465bd26d297 --- src/libdraw/x11-keyboard.c +++ src/libdraw/x11-keyboard.c @@ -51,6 +51,10 @@ _ioproc(void *arg) continue; r = i; send(kc->c, &r); + while((i=xtoplan9kbd(nil)) >= 0){ + r = i; + send(kc->c, &r); + } break; } } blob - 514926da652cc0da5517f6032477c6b8b80e78d1 blob + 1b1012be7a2b42e472ac4c31388363c37f2c09ec --- src/libdraw/x11-memdraw.h +++ src/libdraw/x11-memdraw.h @@ -64,6 +64,10 @@ struct Xprivate { int usetable; XVisual *vis; u32int white; + Atom clipboard; + uint putsnarf; + uint assertsnarf; + int destroyed; }; extern Xprivate _x; @@ -78,11 +82,12 @@ extern void xputxdata(Memimage*, Rectangle); extern void _initdisplaymemimage(Display*, Memimage*); struct Mouse; -extern int xtoplan9mouse(XEvent*, struct Mouse*); +extern int xtoplan9mouse(XDisplay*, XEvent*, struct Mouse*); extern int xtoplan9kbd(XEvent*); extern void xexpose(XEvent*, XDisplay*); extern int xselect(XEvent*, XDisplay*); extern int xconfigure(XEvent*, XDisplay*); +extern int xdestroy(XEvent*, XDisplay*); extern void flushmemscreen(Rectangle); extern void xmoveto(Point); struct Cursor; blob - 6b5b3922af805dd27d62e48c3fbc6a513fdc2b48 blob + eae26788d834cb330f0def04e26418fbd7a0afb1 --- src/libdraw/x11-mouse.c +++ src/libdraw/x11-mouse.c @@ -66,6 +66,16 @@ _ioproc(void *arg) case Expose: xexpose(&xevent, _x.mousecon); continue; + case DestroyNotify: + if(xdestroy(&xevent, _x.mousecon)){ + /* drain it before sending */ + /* apps that care can notice we sent a 0 */ + /* otherwise we'll have getwindow send SIGHUP */ + nbrecv(mc->resizec, 0); + nbrecv(mc->resizec, 0); + send(mc->resizec, 0); + } + continue; case ConfigureNotify: if(xconfigure(&xevent, _x.mousecon)) nbsend(mc->resizec, &one); @@ -76,7 +86,7 @@ _ioproc(void *arg) case ButtonPress: case ButtonRelease: case MotionNotify: - if(xtoplan9mouse(&xevent, &m) < 0) + if(xtoplan9mouse(_x.mousecon, &xevent, &m) < 0) continue; send(mc->c, &m); /*