2012/05/17

The Labs.Com Issue_05_X
Last update 1999/02/20

TPJ: Issue_05_X

This is a collection of programs published by The Perl Journal. You can download all source-code also from TPJ: Programs.
  1. README
  2. Xproto2.perl
  3. clickwindow.pl
  4. xhello.pl
  5. extra-Xproto.h
  6. xatomhash.pl
  7. names
  8. parse-xheader.pl
  9. reqs
  10. wmm.pl
  11. xauth.pl
  12. xbase.pl
  13. xbeep.pl
  14. xdpyinfo.pl
  15. xerror.pl
  16. xint.perl
  17. xlsfont.pl
  18. xwdhead.pl
  19. xwininfo.c
  20. xwininfo.pl
  21. More Samples on X
Issue_05_X
1. README
Download README

 Back in late 1991, I wrote an X library for perl.  This wasn't a bindi\ 
 ng 
 to the C Xlib; this was a raw implementation of the X protocol. 
  
 It got some small amount of use around MIT; I never got around to 
 posting it widely, but got feedback from a few people. 
 perl5 has some clever new features, which should make it easier to 
 provide a clean "interface" than the old code had, and easier to 
 set up good abstractions internally. 
 Now that I've had time to read through the Perl5 edition of the Camel 
 Book, it's time to begin...  [eichin:19961101.0337EST] 
  
 discoveries: 
 * attempted to speed up the load of the converted Xproto. 
 perl *without* -w, user time: 
   .cooked file: 0.5s [original mechanism] 
   indiv. assign: 1.1s [first modification] 
   flattened assign: 0.52s, but more variance(?) [optimized a bit] 
 Note, however, that this *appears* to be *slower* than  
  parsing the proto file.  Perhaps that shouldn't be a surprise... 
 So a win might be to store a binary format instead? 
 Problem is that these are all variable length strings; switching to a  
  split on ^@ gave about the same time range. 
  
 in perl5, we should be able to say: 
  my($output) = &xlibconvert("xConnSetupPrefix",$reply) 
  $success = $output->{"success"}; 
 this would make $output blessed? or perhaps we say 
  my($output) = Xlib->new(type=>"xConnSetupPrefix",data=>$repl\ 
 y); 
 all output needs to be, though, is a hash... ie. convert can  
 do the unpack *and* stuff the fields into the hash (and perl4 could  
 have probably handled this too, if &xlibconvert explicitly returned 
 a hash...) so xlibconvert just returns a hashref, which also happens 
 to contain the "packof" and "sizeof" fields.  However, this only helps 
 with the few cases where we read now, though it would make it easier 
 to write more of them (as we'd need to for event handling.) We need a 
 better syntax for generating protocol messages, if we can... 
  
 x_beep just does: 
   print XFD pack($xpackof{"xBellReq"},$defines{"X_Bell"},$percentage,1\ 
 ); 
 we could put the $defines into a namespace directly; in fact, the X 
 defines are a useful set themselves, and could just become X::Bell and 
 the like. (maybe def:: for the others? or just make them raw values?) 
 so, step 1: 
   print XFD pack($xpackof{"xBellReq"},X::Bell,$percentage,1); 
 we can also, at least, define xpack as 
   sub xpack { my $typ=shift; pack($packof{$typ},@_); } 
 and then say 
   print XFD &xpack("xBellReq",X::Bell,$percentage,1); 
 which, with a name space and actual functions, could instead become 
   print XFD X::xBellReq(X::Bell,$percentage,1); 
 Then note that most of these include their *own* verb at the 
 beginning, there should be a clever way to instead say 
   print XFD X::xBellReq($percentage,1); 
 and now we're getting somewhere. 
  
 [eichin:19961105.0458EST] 
 [done] All uses of xsizeof/sizeof are in bytes -- so drop the *8 /8 al\ 
 together. 
 Many use the $lll self-measuring trick, which could be generalized? 
  
 [eichin:19961106.1304EST] 
 [done] auth is way simple - perhaps we can just implement it next? 
 should fix "mismatch" code so it doesn't complain as much gratuitously 
 add more synonyms 
 [done] implement something like GetResReq/GetEmptyReq (for one arg/no \ 
 args) 
   instead of forcing stuff into extra-Xproto.h? 
 [eichin:19961108.0113EST] 
 [done] finish off "xdpyinfo" features -- store xopendisplay output, an\ 
 d then 
   parse it seperately... 
 perhaps a master data queue? or at least *some* way to handle events? \ 
 [done] 
   (maybe just a hook that prints them at first...) 
 [eichin:19961109.1630EST] 
 milestones: 
         hello world (createwindow, gc, font) [done] 
         query-tree (start on wmm!) [done] 
  
 [eichin:19961117.1841EST] 
 request list: determine full protocol coverage based on request names 
 (up to 1/3 by morning...) 
  
 [eichin:19961118.1349EST] 
 idea from ken: calculate the length in Req subs directly? we *can*...[\ 
 done] 
 [eichin:19961119.0351EST] 
 what about elisp, anyway? :-) 
  
 [eichin:19961120.0102EST] 
 how about a tie'd hash for atom name lookups? [done] 
 [eichin:19961120.1221EST] 
 now do the *reverse* as well -- what's a perl "isnumber"? that way we 
 can use the same data to go both ways... [done] 
 [eichin:19970227.0155EST] 
 Renamed .perl files to .pl since emacs handles that extension consiste\ 
 ntly 
 now.  Leave .perl for generated files for now.  Add Makefile for relea\ 
 se. 

Issue_05_X
2. Xproto2.perl

  • Xproto2.perl
  • Issue_05_X
    3. clickwindow.pl

    Download clickwindow.pl

     #!perl 
     #$xlib::debug = 1; 
     #$xlib::debugpkt = 1; 
     require "./xbase.pl"; 
     # require "./xatomhash.pl"; 
     $xopen = xlib::x_open_display($ENV{"DISPLAY"}); 
     $fc = xlib::joincolor(65535,0,0); 
     $bc = xlib::joincolor(0,0,0); 
     $curs = xlib::x_createfontcursor($xopen, $XC::crosshair, $fc, $bc); 
     sub xx {  
     #    $stat = xlib::xungrabpointer($xopen, 0); # time now 
         $stat = xlib::xgrabpointer($xopen, 
                                    0,        # owner-events false 
                                    &xlib::defaultroot($xopen), # grabw 
                                    $X::defines{"ButtonPressMask"} |  
                                    $X::defines{"ButtonReleaseMask"}, 
                                    $X::defines{"GrabModeSync"}, 
                                    $X::defines{"GrabModeAsync"}, 
                                    &xlib::defaultroot($xopen), 
                                    # conf window none (vs root?) 
                                    $curs,        # cursor none 
                                    $X::defines{"CurrentTime"} # time now 
                                    );  
     #    print "grabstat: $stat\n"; 
         &xlib::xallowevents($xopen,  
                             $X::defines{"SyncPointer"}, 
                             $X::defines{"CurrentTime"}); 
     } 
     xx(); 
     $SIG{"ALRM"} = $SIG{"INT"} = sub { 
         xlib::x_closedisplay($xopen); 
         exit; 
       }; 
     alarm(30); 
     #print "waiting (30s)... $stat\n"; 
     print "click on a window to toggle backing store...\n"; 
     $xlib::handler{"ButtonRelease"} =  
     $xlib::handler{"ButtonPress"} = sub { 
         my $rep = xlib::xlibconvert("keyButtonPointer", $xopen->{"readq\ 
     ueue"}); 
     #    xlib::debugxlib($rep); 
     #    printf "child: 0x%x\n", $xchild = $rep->{"child"}; 
         $xchild = $rep->{"child"}; 
     }; 
     $st = xlib::handle_event($xopen); 
     $ch1 = $xchild; 
     #print "event: $st, child $xchild\n"; 
     xx(); 
     $st = xlib::handle_event($xopen); 
     $ch2 = $xchild; 
     #print "event: $st, child $xchild\n"; 
     # button press, button release, double check that they have the same c\ 
     hild... 
     $stat = xlib::xungrabpointer($xopen, 0); # time now 
     if ($ch1 != $ch2) { 
         die "different windows, aborting on user request"; 
     } 
      
     sub query_eval { 
         my ($d,$w,$sub)=@_; 
         &$sub($d,$w); 
         my @lf = &xlib::x_querytree($d, $w); 
         shift @lf;                        # lose the rep, we just want the\ 
      kids 
         my $i; 
         for $i (@lf) { 
             query_eval($d,$i,$sub); 
         } 
     } 
     sub toggle_backingstore { # disp, win 
         my ($d,$w) = @_; 
         printf "toggling 0x%x (%d):", $w, $w; 
         my $attrs = xlib::x_get_window_attributes($d,$w); 
         if ($attrs->{"backingStore"} == $X::defines{"NotUseful"}) { 
             print "setting to Always\n"; 
             $stat = xlib::x_change_window_attributes($d, $w, 
                                                  $X::defines{"CWBackingSto\ 
     re"}, 
                                                  $X::defines{"Always"}); 
         } else { 
             print "setting to NotUseful\n"; 
             $stat = xlib::x_change_window_attributes($d, $w, 
                                                  $X::defines{"CWBackingSto\ 
     re"}, 
                                                  $X::defines{"NotUseful"})\ 
     ; 
         } 
     } 
     query_eval($xopen,$ch1,\&toggle_backingstore); 

    Issue_05_X
    4. xhello.pl

    Download xhello.pl

     #!/usr/bin/perl 
     require "./xbase.pl"; 
     $xopen = &xlib::x_open_display($ENV{"DISPLAY"}); 
     die $xlib::status if not defined $xopen; 
      
     $fnt = xlib::x_openfont($xopen, "fixed"); 
     $win = xlib::x_create_window($xopen, 8, 
                                  xlib::defaultroot($xopen), 
                                  100, 200, 300, 400, 5, 
                                  $X::defines{"InputOutput"}, 
                                  $X::defines{"CopyFromParent"}, 
                                  $X::defines{"CWBackPixel"} 
                                  | $X::defines{"CWEventMask"}, 
                                  $xlib::root_white, 
                                  $X::defines{"ButtonPressMask"} 
                                  |$X::defines{"ButtonReleaseMask"} 
                                  |$X::defines{"ExposureMask"} 
                                  |$X::defines{"KeyPressMask"} 
                                  ); 
     $gc = xlib::x_create_gc($xopen, $win, 
                             $X::defines{"GCForeground"} 
                             | $X::defines{"GCBackground"} 
                             | $X::defines{"GCFont"}, 
                             $xlib::root_black, $xlib::root_white, $fnt); 
     #printf "fnt %x win %x gc %x\n", $fnt,$win,$gc; 
     #sleep 1; 
     $st = xlib::x_clear_area($xopen, $win, 0, 0,0,0,0); 
     $xlib::handler{"Expose"} = sub { 
       xlib::x_imagetext8($xopen, $win, $gc, 50, 75, "hello world"); 
     }; 
     $xlib::handler{"KeyPress"} = sub { 
         my $rep = xlib::xlibconvert("keyButtonPointer", $xopen->{"readq\ 
     ueue"}); 
         xlib::debugxlib($rep); 
     }; 
      
     xlib::x_mapwindow($xopen, $win); 
     while(defined($st = xlib::handle_event($xopen))) { # assume error for \ 
     now? 
         print "event: $st\n"; 
     } 
     xlib::x_closedisplay($xopen); 

    Issue_05_X
    5. extra-Xproto.h

  • extra-Xproto.h
  • Issue_05_X
    6. xatomhash.pl

    Download xatomhash.pl

     # 
     # use getatomname or internatom depending on the value looked up, but 
     # cache both 
     package XATOM; 
     use Tie::Hash; 
      
     sub TIEHASH { 
         my ($name, $d) = @_; 
         my $self={}; bless $self;  
         $self->{"display"} = $d; 
         $self->{"cache"} = {}; 
         return $self; 
     } 
      
     sub FETCH { 
         my $self = shift; 
         my $key = shift; 
         my $r = $self->{"cache"}->{$key}; 
         if (! defined($r)) { 
             if ($key =~ /^\d*$/) { 
                 $r = xlib::x_getatomname($self->{"display"},$key); 
             } else { 
                 $r = xlib::x_internatom($self->{"display"}, 
                                         $X::defines{"xTrue"},$key); 
             } 
      
             $self->{"cache"}->{$key} = $r; 
             $self->{"cache"}->{$r} = $key; 
         } 
         return $r; 
     } 
     sub EXISTS { 
         my $self = shift; 
         my $key = shift; 
         return exists $self->{"cache"}->{$key}; 
     } 
     sub STORE { 
         my $self = shift; 
         my ($key, $value) = @_;        # value irrelevant 
         my $a = xlib::x_internatom($self->{"display"},$X::defines{"xFal\ 
     se"}, $key); 
         $self->{"cache"}->{$a} = $key; 
         return $self->{"cache"}->{$key} = $a; 
     } 
     sub DELETE { 
         my $self = shift; 
         my ($key, $value) = @_; 
         # delete $self->{"refs"}->{$key}; 
         # can't actually delete something... 
         -1; 
     } 
     sub FIRSTKEY { 
         my $self = shift; 
         my $a = scalar keys %{$self->{"cache"}}; 
         return each %{$self->{"cache"}}; 
     } 
     sub NEXTKEY { 
         my $self = shift; 
         my $lastkey = shift; 
         return each %{$self->{"cache"}}; 
     } 
     sub DESTROY { 
         my $self = shift; 
     } 
     1; 

    Issue_05_X
    7. names

    Download names

     internal: 
             xlibconvert 
             debugxlib [ but exported anyway ] 
             xpack [ only used in x_open_display ] 
             split_display [ could export... ] 
             next_resource_id 
             extend_queue 
             skipevent 
             xqueueconvert 
             x_real_put_image 
     network: 
             mkport 
             mkport_unix 
             serverprint 
     other: 
             min 
     meta: 
             x_washwindow 
             x_get_one 
             x_reply 
             x_iter_raw 
             x_iter 
             genvec 
             genvec2 
             genvecstr 
             xpoly1 
             xpoly2 
             x_ungrab 
     exported: 
             handle_event 
             xdebugdisplay [but only for xdpyinfo?] 
     xlib:: 
             default:: 
                     root                defaultroot 
                     rootdepth        defaultrootdepth 
             window:: 
                     destroy                x_destroywindow 
                     destroysubs        x_destroysubwindows 
                     map                x_mapwindow 
                     mapsubs                x_mapsubwindows 
                     unmap                x_unmapwindow 
                     unmapsubs        x_unmapsubwindows 
                     configure        x_configurewindow 
                     getgeometry        x_get_geometry 
                     reparent        x_reparentwindow 
                     circulate        x_circulatewindow 
                     create                x_create_window 
                     list                x_querytree 
                     set_background_pixmap        x_set_window_background_p\ 
     ixmap 
                     attributes:: 
                             get                x_get_window_attributes 
                             change                x_change_window_attribut\ 
     es 
                     clear                x_clear_area 
                     saveset                x_changesaveset 
                     translate        TranslateCoords [pending] 
             pixmap:: 
                     create                x_create_pixmap 
                     copyarea        CopyArea [pending] 
                     copyplane        CopyPlane [pending] 
             image:: 
                     put                x_put_image 
                     get                GetImage [pending] 
                     free                FreePixmap [pending] 
             poly:: 
                     arcs                xpolyarcs 
                     fillarcs        xpolyfillarcs 
                     rects                xpolyrects 
                     fillrects        xpolyfillrects 
                     segments        xpolysegments 
                     points                xpolypoints 
                     lines                xpolylines 
                     fill                FillPoly [pending] 
             selection:: 
                     setowner        xsetselectionowner 
                     getowner        xgetselectionowner 
                     convert                xconvertselection 
             property:: 
                     change                x_changeproperty 
                     delete                x_deleteproperty 
                     get                x_getproperty 
                     list                x_listproperties 
                     rotate                RotateProperties [pending] 
             font:: 
                     getpath                x_getfontpath 
                     setpath                SetFontPath [pending] 
                     list                x_listfonts 
                     close                CloseFont [pending] 
                     query                QueryFont [pending] 
                     queryextents        QueryTextExtents [pending] 
                     open                x_openfont 
             text:: 
                     poly8                PolyText8 [pending] 
                     poly16                PolyText16 [pending] 
                     image8                x_imagetext8 
                     image16                ImageText16 [pending] 
             atom:: 
                     getname                x_getatomname 
                     intern                x_internatom 
             pointer:: 
                     grab                xgrabpointer 
                     ungrab                xungrabpointer 
                     changegrab        xchangeactivepointergrab 
                     query                xquerypointer 
                     getmapping        x_get_pointer_mapping 
                     setmapping        SetPointerMapping [pending] 
                     warp                WarpPointer [pending] 
                     getcontrol        GetPointerControl [pending] 
                     changecontrol        ChangePointerControl [pending] 
             GC:: 
                     free                FreeGC [pending] 
                     change                ChangeGC [pending] 
                     copy                CopyGC [pending] 
                     create                x_create_gc 
                     setdashes        SetDashes [pending] 
                     setcliprects        SetClipRectangles [pending] 
             colormap:: 
                     create                CreateColormap [pending] 
                     free                FreeColormap [pending] 
                     copyandfree        CopyColormapAndFree [pending] 
                     install                InstallColormap [pending] 
                     uninstall        UninstallColormap [pending] 
                     listinstalled        ListInstalledColormaps [pending] 
             color:: 
                     # may use a hash, or at least combine allocs 
                     alloc                AllocColor [pending] 
                     allocnamed        AllocNamedColor [pending] 
                     alloccells        AllocColorCells [pending] 
                     allocplanes        AllocColorPlanes [pending] 
                     free                FreeColors [pending] 
                     store                StoreColors [pending] 
                     storenamed        StoreNamedColor [pending] 
                     query                QueryColors [pending] 
                     lookup                LookupColor [pending] 
             cursor:: 
                     create                CreateCursor [pending] 
                     createglyph        CreateGlyphCursor [pending] 
                     free                FreeCursor [pending] 
                     recolor                RecolorCursor [pending] 
                     bestize                QueryBestSize [pending] 
             access:: 
                     change                ChangeHosts [pending] 
                     list                ListHosts [pending] 
                     set                SetAccessControl [pending] 
             screensaver:: 
                     set                SetScreenSaver [pending] 
                     get                GetScreenSaver [pending] 
                     force                ForceScreenSaver [pending] 
             key:: 
                     grab                xgrabkeyboard 
                     grab                xgrabkey 
                     grab                xgrabbutton 
                     ungrab                xungrabkeyboard 
                     ungrab                xungrabbutton 
                     ungrab                xungrabkey 
                     getmapping        x_get_keyboard_mapping 
                     getmapping        x_get_modifier_mapping 
                     setmapping        SetModifierMapping [pending] 
                     getcontrol        x_get_keyboard_control 
                     getfocus        x_get_input_focus 
                     setfocus        SetInputFocus [pending] 
                     getmotion        GetMotionEvents [pending] 
                     changemapping        ChangeKeyboardMapping [pending] 
                     changecontrol        ChangeKeyboardControl [pending] 
                     query                QueryKeymap [pending] 
                     beep                x_beep 
             connection:: 
                     setmode                SetCloseDownMode [pending] 
                     kill                KillClient [pending] 
                     open                x_open_display 
                     close                x_closedisplay 
                     grab                xgrabserver 
                     ungrab                xungrabserver 
             extensions:: 
                     list                x_listextensions 
                     query                QueryExtension [pending] 
             event:: 
                     xsendevent 
                     xallowevents 

    Issue_05_X
    8. parse-xheader.pl

    Download parse-xheader.pl

     #!perl 
     $xsizeof{"int"} = 4; 
     $xsizeof{"char"} = 1; 
     $xsizeof{"BYTE"} = 1; 
     $xsizeof{"BOOL"} = 1; 
     $xsizeof{"long"} = 4; 
     $xsizeof{"CARD8"} = 1; 
     $xsizeof{"CARD16"} = 2; 
     $xsizeof{"CARD32"} = 4; 
     $xsizeof{"INT8"} = 1; 
     $xsizeof{"INT16"} = 2; 
     $xsizeof{"INT32"} = 4; 
     # oops, X11R4 is missing one... 
     # X11R6 has it though. 
     # $xsizeof{"xGetModifierMappingReply"} = 256; 
     $xpackof{"int"} = "L"; 
     $xpackof{"char"} = "C"; 
     $xpackof{"BYTE"} = "C"; 
     $xpackof{"BOOL"} = "C"; 
     $xpackof{"long"} = "L"; 
     $xpackof{"CARD8"} = "C"; 
     $xpackof{"CARD16"} = "S"; 
     $xpackof{"CARD32"} = "L"; 
     $xpackof{"INT8"} = "C"; 
     $xpackof{"INT16"} = "S"; 
     $xpackof{"INT32"} = "L"; 
     # these are stored in %xpad in case we decide we want to be general la\ 
     ter on 
     # but for now we copy it all into %xpackof anyhow. 
     for $i ("", 1..3) { 
         $xpad{"BYTE pad$i"} = "x"; 
     } 
     $xpad{"BYTE bpad"} = "x"; 
     $xpad{"CARD8 pad"} = "x"; 
     $xpad{"CARD8 pad1"} = "x"; 
     $xpad{"CARD16 pad"} = "x2"; 
     $xpad{"CARD16 pad1"} = "x2"; 
     $xpad{"CARD16 pad2"} = "x2"; 
     # these are mostly Xevent subfields... 
     for $i ("", "00", 1..7) { 
         $xpad{"CARD32 pad$i"} = "x4"; 
     } 
     for $i (keys %xpad) { $xpackof{$i} = $xpad{$i}; } 
     $incomment = 0; 
     sub fropcomment { # $incomment 
         my($incomment) = @_; 
         s/\/\*.*\*\///g; 
         if(/\*\//) { 
             $incomment = 0; 
             s/^.*\*\///; 
         } 
         next if $incomment; 
         if(/\/\*/) { 
             $incomment = 1; 
             s/\/\*.*//; 
         } 
     } 
      
     # walk XPROTO file and fill in any defines, xsizeof, xtypeof, requests 
     # we come across, sometimes calling process_struct to help 
     sub munchproto { 
         while(<XPROTO>) { 
             $incomment = &fropcomment($incomment); 
      
             if(/\#if defined\(\_\_cplusplus\) \|\| defined\(c\_plusplus\)/\ 
     ) { 
                 while(<XPROTO>) { 
                     last if (/\#else/); 
                 } 
             } 
             next if(/\#else/); 
             next if(/\#endif/); 
             next if(/\#undef/); 
             next if(/\#ifdef NEED_EVENTS/); 
             next if(/\#ifdef NEED_REPLIES/); 
             next if(/\#ifndef XPROTO_H/); 
             next if(/\#include/);        # maybe do these some other time. 
             $eventing=1 if(/^\#define KeyPress/); 
             $eventing=0 if(/^\#define LASTEvent/); 
      
             if(/^\#define (\w+)$/) { 
                 $defines{$1} = 1; 
                 print "# defined flag $1\n"; 
                 next; 
             } 
          
             if(/^\#define sz_(\w+) (\d+)$/) { 
                 $xsizeof{$1} = $2; 
                 print "# processed size $1\n"; 
                 next; 
             } 
      
             if(/^\#define (\w+) CARD(\d+)$/) { 
                 $xtypeof{$1} = "CARD".$2; 
                 $xsizeof{$1} = $2/8; 
                 print "# processed type $1\n"; 
                 next; 
             } 
             if(/^\#define (\w+)\s+(\d+)L?\s*$/) { 
                 $defines{$1} = $2; 
                 print "# defined flag $1 = $2\n"; 
                 my ($s,$t) = ($1,$2); 
                 if(/^\#define X\_/) { 
                     $requests[$t] = $s; 
                     print "# request $t maps to $s\n"; 
                 } 
                 if ($eventing) { 
                     $events[$t] = $s; 
                     print "# event code $t maps to $s\n"; 
                 } 
                 $eventing=0 if(/^\#define LASTEvent/); 
                 next; 
             } 
             if(/^\#define (\w+)\s+(0x[0-9a-fA-F]+)\s*$/) { 
                 $defines{$1} = oct($2); 
                 print "# defined flag $1 = $2\n"; 
                 next; 
             } 
             if(/^\#define (\w+)\s+\(1L?<<(\d+)\)\s*$/) { 
                 $defines{$1} = 2**$2; 
                 print "# defined flag $1 = $defines{$1} (2**$2)\n"; 
                 next; 
             } 
             if(/^typedef CARD(\d+) (\w+);/) { 
                 $xtypeof{$2} = "CARD".$1; 
                 $xsizeof{$2} = $1/8; 
                 print "# processed type $2\n"; 
                 next; 
             } 
      
             if(/^typedef struct \{/) { 
                 &process_struct(); 
                 next; 
             } 
             if(/^typedef struct _(\w+) \{/) { 
                 &process_struct(); 
                 next; 
             } 
      
             if(/^typedef (\w+) (\w+);/) { 
                 $xtypeof{$2} = $xtypeof{$1}; 
                 $xsizeof{$2} = $xsizeof{$1}; 
                 print "# processed type $2 (alias of $1)\n"; 
                 $xalias{$2} = $1; 
                 next; 
             } 
      
     #        print; 
         } 
     } 
      
     # process_struct: walk XPROTO when we've got a typedef struct to work \ 
     on 
     # handle some unions, filling in xsizeof and xtypeof only.  skip comme\ 
     nts 
     # and WORD64 code. 
     sub process_struct { 
         my($typ,$siz) = ([],0); 
         while(<XPROTO>) { 
             $incomment = &fropcomment($incomment); 
             if(/\#if defined\(\_\_cplusplus\) \|\| defined\(c\_plusplus\)/\ 
     ) { 
                 while(<XPROTO>) { 
                     last if (/\#else/); 
                 } 
             } 
             if(/\#ifdef WORD64/) { 
                 while(<XPROTO>) { 
                     last if (/\#else/); 
                 } 
             } 
             next if(/\#else/); 
             next if(/\#endif/); 
             s/ +B16//g; 
             s/ B32//g; 
             last if(/\} (\w+)\;/); 
             if(/union \{/) { 
                 my($utt); 
                 print "# handling Union\n"; 
                 while(<XPROTO>) { 
                     local($in_union) = !defined($xtypeof{"mappingNotify"})\ 
     ; 
                     $utt = $_; 
                     if(/struct \{/) { 
                         &process_struct(); 
                     } 
                     last if($utt =~ /\} u\;/); 
                 } 
             } 
      
             while(/(\w+)\s+(\w*)\,/) { 
                 while(/(\w+)\s+(\w+)\,/) { 
                     push(@$typ,"$1 $2"); 
                     $siz += $xsizeof{$1}; 
                     s/$2\,//; 
                 } 
                 last if (/(\w+)\s+(\w+)\;/); 
                 $_ .= <XPROTO>; 
                 s/\/\*.*\*\///g; 
                 s/ +B16//g; 
                 s/ B32//g; 
             } 
             if(/(\w+)\s+(\w+)\[(\d+)\]\;/) { 
                 push(@$typ,"$1 $2 $3"); 
                 $siz += $xsizeof{$1}*$3; 
             } 
             if(/(\w+)\s+(\w+)\;/) { 
                 push(@$typ,"$1 $2"); 
                 $siz += $xsizeof{$1}; 
             } 
         } 
         m/\} (\w+);/; 
         my $t = $1; 
         print "# processed type $t\n"; 
          
         if($t eq "xEvent") { 
             # xEvent is a "special" case... 
             # xsizeof is already set... 
             # and we don't really need xtypeof... 
             $typ = ["BYTE raw_bits 32"]; 
             $siz = 32; 
         } 
         if($siz != $xsizeof{$t}) { 
             print "### mismatch:  @$typ, $siz, $t, $xsizeof{$t}\n"; 
         } 
         if ($in_union == 1) { 
             if ($t eq "u") { 
                 if (!defined($xtypeof{"mappingNotify"})) { 
                     print "SETTING union_u to @$typ/$siz\n"; 
                     $union_u_typeof = $typ; 
                     $union_u_sizeof = $siz; 
                 } else { 
                     $in_union = 0; 
                 } 
             } else { 
                 print "ADDING @$union_u_typeof to $t\n"; 
                 print "WAS @$typ...\n"; 
                 if ($$typ[0] eq "CARD32 pad00") { 
                     splice(@$typ,0,1,@$union_u_typeof); 
                 } 
                 print "IS NOW @$typ...\n"; 
                 print "SIZ is $siz\n"; 
             } 
         } 
         $xtypeof{$t} = join(":",@$typ); 
         $xsizeof{$t} = $siz; 
     } 
     # munchkeys: walk all xtypeof and generate xpackof 
     sub munchkeys { 
         for $typ (keys %xtypeof) { 
             print "Walking: $typ -- "; 
             &walk_type($typ); 
             $ss = length(pack($xpackof{$typ},0)); 
             print "$xpackof{$typ}, $xsizeof{$typ} $ss\n"; 
             if($ss != $xsizeof{$typ}) { 
                 print "MISMATCH: $xtypeof{$typ}\n"; 
             } 
         } 
     } 
      
     # walk_type: given a type that's in xtypeof, generate xpackof 
     #  *and* modify xtypeof by dropping pad fields 
     sub walk_type { 
         my($typ) = @_; 
         return if $xpackof{$typ} ne ""; # already done 
         return if !defined($xtypeof{$typ});        # not doable 
         my($xele,$save_1,$save_3); 
         my $xnew = []; 
         for $xele (split(/\:/,$xtypeof{$typ})) { 
             if($xele =~ /^(\w+) (\w+)$/) { 
                 $save_1 = $1; 
                 # allow preloads for "special" names like "BYTE pad" 
                 if($xpackof{$xele} ne "") { 
                     # assume a "whole line" subst means padding, 
                     # and we drop the field. Might change this later. 
                     $save_1 = $xele; 
                 } else { 
                     push(@$xnew,$xele); 
                 } 
                 if($xpackof{$save_1} eq "") { 
                     &walk_type($save_1); 
                 } 
                 $xpackof{$typ} .= $xpackof{$save_1}; 
             } elsif($xele =~ /^(\w+) (\w+) (\d+)$/) { 
                 $save_1 = $1; $save_3 = $3; 
                 # allow preloads for "special" names like "BYTE pad 3" 
                 if($xpackof{"$1 $2"} ne "") { 
                     # assume a "whole line" subst means padding, 
                     # and we drop the field. Might change this later. 
                     $save_1 = "$1 $2"; 
                 } else { 
                     push(@$xnew,$xele); 
                 } 
                 if($xpackof{$save_1} eq "") { 
                     &walk_type($save_1); 
                 } 
                 $xpackof{$typ} .= $xpackof{$save_1}.$save_3; 
             } elsif($xele =~ /^(\w+)$/) { 
                 # it can't really recurse here, can it? 
                 # maybe if something is typedef xCharInfo. 
                 push(@$xnew,$xele); 
                 $xpackof{$typ} .= $xpackof{$1}; 
             } else { 
                 die "bad element of $typ: $xele ($xtypeof{$typ})"; 
             } 
         } 
         $xtypeof{$typ} = join(":",@$xnew); 
     } 
     for $fn ("/usr/include/X11/Xproto.h", "/usr/include/X11/Xprotostr.h", 
              "extra-Xproto.h", "/usr/include/X11/X.h",  
              "/usr/include/X11/cursorfont.h") { 
         open(XPROTO,"< $fn") || die "Couldn't open $fn: $@"; 
         &munchproto; 
         close XPROTO; 
     } 
     # X.h to actually to pick up *Mask, GC* and the like... 
      
     &munchkeys; 
      
     open(PERLOUT,">Xproto2.perl") || die "couldn't open Xproto2.perl: $\ 
     @"; 
     open(LISPOUT,">Xproto2.el") || die "couldn't open Xproto2.el: $@"; 
     print PERLOUT "package X;\n"; 
     print PERLOUT "\%xpackof = (\n"; 
     print LISPOUT "(setq xpackof '(\n"; 
     for $xtype (sort keys %xpackof) { 
         print PERLOUT qq{"$xtype", "$xpackof{$xtype}",\n}; 
         print LISPOUT qq{("$xtype" "$xpackof{$xtype}")\n}; 
     } 
     print PERLOUT "); # xpackof\n"; 
     print LISPOUT ")) ; xpackof\n"; 
     print PERLOUT "\%xtypeof = (\n"; 
     print LISPOUT "(setq xtypeof '(\n"; 
     for $xtype (sort keys %xtypeof) { 
         print PERLOUT qq{"$xtype", "$xtypeof{$xtype}", \n}; 
         print LISPOUT qq{("$xtype" (}; 
         for (split(/\:/,$xtypeof{$xtype})) { 
             m/(\w+) ?(\w+)?/; 
             print LISPOUT qq{("$2" $1) }; 
             $result{$2} = shift @fields; 
         } 
         print LISPOUT qq{))\n}; 
     #    print LISPOUT qq{("$xtype" "$xtypeof{$xtype}")\n}; 
     } 
     print PERLOUT "); # xtypeof\n"; 
     print LISPOUT ")) ; xtypeof\n"; 
     print PERLOUT "\%xsizeof = (\n"; 
     print LISPOUT "(setq xsizeof '(\n"; 
     for $xtype (sort keys %xtypeof) { 
         print PERLOUT qq{"$xtype", $xsizeof{$xtype},\n}; 
         print LISPOUT qq{("$xtype" $xsizeof{$xtype})\n}; 
     } 
     print PERLOUT "); # xsizeof\n"; 
     print LISPOUT ")) ; xsizeof\n"; 
     print PERLOUT "\%defines = (\n"; 
     print LISPOUT "(setq xdefines '(\n"; 
     for $def (sort keys %defines) { 
         print PERLOUT qq{"$def", $defines{$def},\n}; 
         print LISPOUT qq{("$def" $defines{$def})\n}; 
     } 
     print PERLOUT "); # defines\n"; 
     print LISPOUT ")) ; xdefines\n"; 
      
     print PERLOUT "sub pad4 { ((\$_[0]+3)>>2)<<2; }\n"; 
     print PERLOUT qq{sub xpad { my \$l=pad4(\$_[0])-\$_[0]; "\\0" x \$l; }\ 
     \n}; 
     %xsubs=(); 
     for $def (sort keys %defines) { 
         next if $def !~ /^X_/; 
         ($j = $def) =~ s/^X_//; 
         print PERLOUT qq{\$$j = $defines{$def};\n}; 
         # don't need X:: scoping in these copies... 
         my $req = "x${j}Req"; 
         if (defined $xpackof{$req}) { 
             if ($xalias{$req} eq "xResourceReq") { 
                 print PERLOUT qq{sub $req { pack(\$xpackof{"$req"},\$$j,2,\ 
     \@_);}\n}; 
                 $xsubs{$req} = $req; 
                 print PERLOUT "sub new$req { $req(\@_); }\n"; 
                 $xsubs{"new$req"} = "new$req"; 
             } elsif ($xalias{$req} eq "xReq") { 
                 print "GOTONE: xReq $j/$req isn't fake\n"; 
                 print PERLOUT qq{sub $req { pack(\$xpackof{"$req"},\$$j,0,\ 
     1);}\n}; 
             } else { 
                 my @fields = split(/\:/,$xtypeof{$req}); 
                 if ($fields[1] eq "CARD16 length") {  
                     print PERLOUT  
                         qq{sub $req { pack(\$xpackof{"$req"},\$$j,\@_);}\n\ 
     }; 
                 } elsif ($fields[2] eq "CARD16 length") {  
                     print PERLOUT  
                         qq{sub $req { pack(\$xpackof{"$req"},\$$j,\$_[1],\\ 
     $_[0],\@_[2..\$#_]);}\n}; 
                 } else { 
                     print "$req failed: ".join(":",@fields)."\n"; 
                     die; 
                 }  
      my $fl = scalar(@fields)-2; # -length, -reqType, so points to extra 
     print PERLOUT "sub new$req { my \$l=\$_[$fl]; my \$x=$req(0,\@_).\$l; \ 
     $req(pad4(length(\$x))/4,\@_).\$l.xpad(length(\$x)); }\n"; 
                 $xsubs{$req} = $req; 
                 $xsubs{"new$req"} = "new$req"; 
             } 
         } elsif ($xalias{$j} eq "xReq") { 
             print PERLOUT qq{sub $req { pack(\$xpackof{"$j"},\$$j,0,1);}\n\ 
     }; 
             $xsubs{$req} = $req; 
             print PERLOUT "sub new$req { $req(\@_); }\n"; 
             $xsubs{"new$req"} = "new$req"; 
         } 
     } 
     print PERLOUT "\%xsubs = (\n"; 
     for $subs (sort keys %xsubs) { 
         print PERLOUT qq{"$subs" => \\&$subs,\n}; 
     } 
     print PERLOUT ");\n"; 
     for $def (sort keys %defines) { 
         print PERLOUT qq{\$requests[$defines{$def}] = "$def";\n} if $def =\ 
     ~ /^X_/; 
     } 
     { 
         print PERLOUT "\@xevents = (\""; 
         print PERLOUT join(qq{\",\"}, @events); 
         print PERLOUT "\"); # xevents\n"; 
     } 
     print PERLOUT "package XC;\n"; 
     for $def (sort keys %defines) { 
         next if $def !~ /^XC_(.*)$/; 
         print PERLOUT "\$$1 = $defines{$def};\n"; 
     } 
     print PERLOUT "1;\n"; 
     close PERLOUT; 
     close LISPOUT; 

    Issue_05_X
    9. reqs

    Download reqs

     $requests[1] = "X_CreateWindow"; [done] 
     $requests[2] = "X_ChangeWindowAttributes"; [done] 
     $requests[3] = "X_GetWindowAttributes"; [done] 
     $requests[4] = "X_DestroyWindow"; [done] 
     $requests[5] = "X_DestroySubwindows"; [done] 
     $requests[6] = "X_ChangeSaveSet"; [done] 
     $requests[7] = "X_ReparentWindow"; [done] 
     $requests[8] = "X_MapWindow"; [done] 
     $requests[9] = "X_MapSubwindows"; [done] 
     $requests[10] = "X_UnmapWindow"; [done] 
     $requests[11] = "X_UnmapSubwindows"; [done] 
     $requests[12] = "X_ConfigureWindow"; [done] 
     $requests[13] = "X_CirculateWindow"; [done] 
     $requests[14] = "X_GetGeometry"; [done] 
     $requests[15] = "X_QueryTree"; [done] 
     $requests[16] = "X_InternAtom"; [done] 
     $requests[17] = "X_GetAtomName"; [done] 
     $requests[18] = "X_ChangeProperty"; [done] 
     $requests[19] = "X_DeleteProperty"; [done] 
     $requests[20] = "X_GetProperty"; [done] 
     $requests[21] = "X_ListProperties"; [done] 
     $requests[22] = "X_SetSelectionOwner"; [done] 
     $requests[23] = "X_GetSelectionOwner"; [done] 
     $requests[24] = "X_ConvertSelection"; [done] 
     $requests[25] = "X_SendEvent"; [done] 
     $requests[26] = "X_GrabPointer"; [done] 
     $requests[27] = "X_UngrabPointer"; [done] 
     $requests[28] = "X_GrabButton"; [done] 
     $requests[29] = "X_UngrabButton"; [done] 
     $requests[30] = "X_ChangeActivePointerGrab"; [done] 
     $requests[31] = "X_GrabKeyboard"; [done] 
     $requests[32] = "X_UngrabKeyboard"; [done] 
     $requests[33] = "X_GrabKey"; [done] 
     $requests[34] = "X_UngrabKey"; [done] 
     $requests[35] = "X_AllowEvents"; [done] 
     $requests[36] = "X_GrabServer"; [done] 
     $requests[37] = "X_UngrabServer"; [done] 
     $requests[38] = "X_QueryPointer"; [done] 
     $requests[39] = "X_GetMotionEvents"; 
     $requests[40] = "X_TranslateCoords"; 
     $requests[41] = "X_WarpPointer"; 
     $requests[42] = "X_SetInputFocus"; 
     $requests[43] = "X_GetInputFocus"; [done] 
     $requests[44] = "X_QueryKeymap"; 
     $requests[45] = "X_OpenFont"; [done] 
     $requests[46] = "X_CloseFont"; 
     $requests[47] = "X_QueryFont"; 
     $requests[48] = "X_QueryTextExtents"; 
     $requests[49] = "X_ListFonts"; [done] 
     $requests[50] = "X_ListFontsWithInfo"; 
     $requests[51] = "X_SetFontPath"; 
     $requests[52] = "X_GetFontPath"; [done] 
     $requests[53] = "X_CreatePixmap"; [done] 
     $requests[54] = "X_FreePixmap"; 
     $requests[55] = "X_CreateGC"; [done] 
     $requests[56] = "X_ChangeGC"; 
     $requests[57] = "X_CopyGC"; 
     $requests[58] = "X_SetDashes"; 
     $requests[59] = "X_SetClipRectangles"; 
     $requests[60] = "X_FreeGC"; 
     $requests[61] = "X_ClearArea"; [done] 
     $requests[62] = "X_CopyArea"; 
     $requests[63] = "X_CopyPlane"; 
     $requests[64] = "X_PolyPoint"; [done] 
     $requests[65] = "X_PolyLine"; [done] 
     $requests[66] = "X_PolySegment"; [done] 
     $requests[67] = "X_PolyRectangle"; [done] 
     $requests[68] = "X_PolyArc"; [done] 
     $requests[69] = "X_FillPoly"; 
     $requests[70] = "X_PolyFillRectangle"; [done] 
     $requests[71] = "X_PolyFillArc"; [done] 
     $requests[72] = "X_PutImage"; [done] 
     $requests[73] = "X_GetImage"; 
     $requests[74] = "X_PolyText8"; 
     $requests[75] = "X_PolyText16"; 
     $requests[76] = "X_ImageText8"; [done] 
     $requests[77] = "X_ImageText16"; 
     $requests[78] = "X_CreateColormap"; 
     $requests[79] = "X_FreeColormap"; 
     $requests[80] = "X_CopyColormapAndFree"; 
     $requests[81] = "X_InstallColormap"; 
     $requests[82] = "X_UninstallColormap"; 
     $requests[83] = "X_ListInstalledColormaps"; 
     $requests[84] = "X_AllocColor"; 
     $requests[85] = "X_AllocNamedColor"; 
     $requests[86] = "X_AllocColorCells"; 
     $requests[87] = "X_AllocColorPlanes"; 
     $requests[88] = "X_FreeColors"; 
     $requests[89] = "X_StoreColors"; 
     $requests[90] = "X_StoreNamedColor"; 
     $requests[91] = "X_QueryColors"; 
     $requests[92] = "X_LookupColor"; 
     $requests[93] = "X_CreateCursor"; 
     $requests[94] = "X_CreateGlyphCursor"; 
     $requests[95] = "X_FreeCursor"; 
     $requests[96] = "X_RecolorCursor"; 
     $requests[97] = "X_QueryBestSize"; 
     $requests[98] = "X_QueryExtension"; 
     $requests[99] = "X_ListExtensions"; [done] 
     $requests[100] = "X_ChangeKeyboardMapping"; 
     $requests[101] = "X_GetKeyboardMapping"; [done] 
     $requests[102] = "X_ChangeKeyboardControl"; 
     $requests[103] = "X_GetKeyboardControl"; [done] 
     $requests[104] = "X_Bell"; [done] 
     $requests[105] = "X_ChangePointerControl"; 
     $requests[106] = "X_GetPointerControl"; 
     $requests[107] = "X_SetScreenSaver"; 
     $requests[108] = "X_GetScreenSaver"; 
     $requests[109] = "X_ChangeHosts"; 
     $requests[110] = "X_ListHosts"; 
     $requests[111] = "X_SetAccessControl"; 
     $requests[112] = "X_SetCloseDownMode"; 
     $requests[113] = "X_KillClient"; 
     $requests[114] = "X_RotateProperties"; 
     $requests[115] = "X_ForceScreenSaver"; 
     $requests[116] = "X_SetPointerMapping"; 
     $requests[117] = "X_GetPointerMapping"; [done] 
     $requests[118] = "X_SetModifierMapping"; 
     $requests[119] = "X_GetModifierMapping"; [done] 
     $requests[127] = "X_NoOperation"; 

    Issue_05_X
    10. wmm.pl

    Download wmm.pl

     #!perl 
     require "./xbase.pl"; 
     require "./xatomhash.pl"; 
     $xopen = &xlib::x_open_display($ENV{"DISPLAY"}); 
     die $xlib::status if not defined $xopen; 
     tie %xatom, XATOM, $xopen; 
     # features: 
     #   list all (id, name) [done] 
     #   walk tree doing something 
     #   move, resize, map/unmap  (by id, by name?) 
     #   select window with click 
     sub getwinname { 
         my ($d,$w) = @_; 
     #    $atom_wm_name = xlib::x_internatom($d,$X::defines{"xTrue"},"WM_NA\ 
     ME") 
     #        if ! defined($atom_wm_name); 
     #    die if $atom_wm_name == 0; 
         my @x = xlib::x_getproperty($d,$X::defines{"xFalse"}, $w,$xatom{"W\ 
     M_NAME"}, 
                                     $X::defines{"AnyPropertyType"}, 0,255)\ 
     ; 
         return $x[1]; 
     } 
      
     sub list_all { 
         my $d = shift; 
         my $debug = shift; 
         list_level($d, $xlib::root_window, $debug); 
     } 
      
     sub list_level { 
         my $d = shift; 
         my $w = shift; 
         my $debug = shift; 
         my @ret; 
         my @lf = &xlib::x_querytree($d, $w, $xlib::root_window); 
         shift @lf;                        # lose the rep, we just want the\ 
      kids 
         for $i (@lf) { 
             # need one level deeper... 
             my $wn = getwinname($d, $i); 
             if ($wn eq "") { 
                 my @l2 = &xlib::x_querytree($d, $i); 
                 shift @l2;                # lose the rep, we just want the\ 
      kids 
                 for $j (@l2) { 
                     my $wn = getwinname($d, $j); 
                     if ($wn ne "") { 
                         printf "%x(%x): %s\n", $i, $j, $wn if $debug; 
                         push(@ret, $i, $wn); 
                         last; 
                     } 
                 } 
             } else { 
                 printf "%x: %s\n", $i, $wn if $debug; 
                 push(@ret, $i, $wn); 
             } 
         } 
         for $i (@lf) { 
             push(@ret, list_level($d, $i, $debug)); 
         } 
         @ret; 
     } 
     @list = list_all($xopen,1); 
     print join(":",@list),"\n"; 
      
     while(1) { 
         my $wid = shift @list; 
         my $wn = shift @list; 
      
         if ($wn =~ /studentloan/) { 
             print "changing $wn\n"; 
             xlib::x_changeproperty($xopen,$X::defines{"PropModeReplace"},$\ 
     wid, 
                                    $xatom{"WM_NAME"},$xatom{"STRING"},8,"h\ 
     ello"); 
             xlib::x_changeproperty($xopen,$X::defines{"PropModeReplace"},$\ 
     wid, 
                                    $xatom{"WM_ICON_NAME"},$xatom{"STRING"}\ 
     , 
                                    8,"hello icon"); 
         } 
         last if scalar(@list) == 0; 
     } 
     xlib::handle_event($xopen); 

    Issue_05_X
    11. xauth.pl

    Download xauth.pl

      
     #        2 bytes                Family value (second byte is as in pro\ 
     tocol HOST) 
     #        2 bytes                address length (always MSB first) 
     #        A bytes                host address (as in protocol HOST) 
     #        2 bytes                display "number" length (always MSB fi\ 
     rst) 
     #        S bytes                display "number" string 
     #        2 bytes                name length (always MSB first) 
     #        N bytes                authorization name string 
     #        2 bytes                data length (always MSB first) 
     #        D bytes                authorization data string 
     # define FamilyLocal (256)        /* not part of X standard (i.e. X.h)\ 
      */ 
     # define FamilyWild  (65535) 
     # define FamilyNetname    (254)   /* not part of X standard */ 
     # define FamilyKrb5Principal (253) /* Kerberos 5 principal name */ 
     # define FamilyLocalHost (252)        /* for local non-net authenticat\ 
     ion */ 
     # from X.h, 
     # "FamilyChaos", 2, 
     # "FamilyDECnet", 1, 
     # "FamilyInternet", 0, 
     $X::defines{"FamilyLocal"} = 256; 
     sub unpack_xauth_record { # $data 
         my ($data) = @_; 
         my ($family, $len, $addr, $disp, $authname, $authdata); 
         ($family, $len, $data) = unpack("nna*", $data); 
         ($addr, $data) = unpack("a$len a*", $data); 
         ($len, $data) = unpack("na*", $data); 
         ($disp, $data) = unpack("a$len a*", $data); 
         ($len, $data) = unpack("na*", $data); 
         ($authname, $data) = unpack("a$len a*", $data); 
         ($len, $data) = unpack("na*", $data); 
         ($authdata, $data) = unpack("a$len a*", $data); 
         return { "family" => $family, 
                  "addr"   => $addr, 
                  "disp"   => $disp, 
                  "authname" => $authname, 
                  "authdata" => $authdata, 
                  "remainder" => $data}; 
     } 
      
     sub parse_xauth_file { 
         my $xadb = (); 
         my $data; 
         { 
             my $xafile = defined($ENV{"XAUTHORITY"})? 
                 $ENV{"XAUTHORITY"}: ($ENV{"HOME"}."/.Xauthority");  
             local *XAUTH; 
             open(XAUTH, "<$xafile") || return $xadb; 
             local $/ = undef; 
             $data = <XAUTH>; 
             close XAUTH; 
         } 
         while(length($data)) { 
             my $res = unpack_xauth_record($data); 
             my $tmprec = {}; 
             $data = $res->{"remainder"}; 
             foreach (sort keys %$res) { 
                 next if /^remainder$/; 
                 $tmprec->{$_} = $res->{$_}; 
             } 
             push(@$xadb, $tmprec); 
         } 
         return $xadb; 
     } 
     sub debug_xauth_file { 
         my $xdb = parse_xauth_file(); 
         foreach (@$xdb) { 
             my $res = $_; 
             foreach (sort keys %$res) { 
                 if (/^addr$/ && length($res->{$_}) == 4) { #  
                     print "$_: ",join(".",unpack("C4",$res->{$_})),"\n"\ 
     ; 
                     next; 
                 } 
                 print "$_: ",unpack("H*",$res->{$_}),"\n" 
                     if /^authdata$/; 
                 next if /^authdata$/; 
                  
                 print "$_: $res->{$_}\n"; 
             } 
         } 
     } 
     sub search_xauth_file { # display 
         my($displayname) = @_; 
         my $xdb = parse_xauth_file(); 
         my ($family, $addr, $res); 
         # display cases: 
         # :0.* -- unix, so family = FamilyLocal, addr=`hostname` 
         # host:0.* -- inet, so family = FamilyInternet, addr = 4byte ip ad\ 
     dr 
         my($node, $off, $screen); 
         ($node, $off, $screen) = split_display($displayname); 
         if ($node eq "") { 
             # unix domain socket case 
             $family = $X::defines{"FamilyLocal"}; 
             $addr = `hostname`; chomp $addr; 
         } else { 
             # tcp case 
             $family = $X::defines{"FamilyInternet"}; 
             my ($name, $aliases, $type, $len, $thisaddr) = gethostbyname($\ 
     node); 
             $addr = $thisaddr; 
         } 
         foreach $res (@$xdb) { 
             if ($res->{"family"} eq $family 
                 && $res->{"addr"} eq $addr) { 
                 return $res; 
             } 
         } 
         return undef; 
     } 
      
     # debug_xauth_file(); 
     1; 

    Issue_05_X
    12. xbase.pl

    Download xbase.pl

     #!perl 
     package xlib; 
      
     require "./Xproto2.perl"; 
      
     sub xlibconvert { # type, data 
         my ($typ, $data) = @_; 
         my %result; 
         my (@fields) = unpack($X::xpackof{$typ},$data); 
      
         for (split(/\:/,$X::xtypeof{$typ})) { 
             m/(\w+) (\w+)/; 
             $result{$2} = shift @fields; 
         } 
         # nice trick: roll the sizeof in here too... 
         $result{"sizeof"} = $X::xsizeof{$typ}; 
         $result{"packof"} = $X::xpackof{$typ}; 
         $result{"typeof"} = $X::xtypeof{$typ}; 
         $result{"typ"} = $typ; 
         return \%result; 
     } 
      
     sub debugxlib { # value 
         my ($val) = @_; 
         print "$val->{typ}:\n"; 
         for (split(/:/,$val->{"typeof"})) { 
             m/(\w+) (\w+)/; 
             print "\t$2: $val->{$2}\n"; 
         } 
         1; 
     } 
      
     sub xpack { my $typ=shift; pack($X::xpackof{$typ},@_); } 
      
     use Socket qw(AF_INET PF_INET SOCK_STREAM INADDR_ANY AF_UNIX PF_UNIX); 
     sub mkport { 
       my($saddr,$port,$FD) = @_; 
       my $proto = (getprotobyname("tcp"))[2]; 
       my $sin = Socket::sockaddr_in($port, $saddr); 
       socket($FD, PF_INET, SOCK_STREAM, $proto) || return "socket:$!"; 
       connect($FD, $sin) || return "connect:$!"; 
       select($FD); $| = 1; select(STDOUT); $| = 1; 
       return "OK"; 
     } 
     sub mkport_unix { 
       my($path,$FD) = @_; 
       my $proto = 0;                # *not* tcp... 
       my $sun = Socket::sockaddr_un($path); 
       socket($FD, PF_UNIX, SOCK_STREAM, $proto) || return "socket:$!"; 
       connect($FD, $sun) || return "connect:$!"; 
       select($FD); $| = 1; select(STDOUT); $| = 1; 
       return "OK"; 
     } 
     sub split_display { # $disp var 
         my ($node, $dispnum, $off, $screen); 
         my ($displayname) = @_; 
         ($node,$dispnum)=split(':',$displayname); 
         ($off,$screen) = split('\.',$dispnum); 
         $screen = 0 if !defined($screen); 
         return ($node, $off, $screen); 
     } 
      
     require "./xauth.pl"; 
      
     sub min { my($a,$b)=@_; ($a<$b) ? $a : $b; } 
     sub serverprint { # $d 
         my $d = shift; 
         print {$d->{"XFD"}} @_; 
         if ($debug || $debugpkt) { 
             print "seq: $xseqnum\n"; $xseqnum++; 
             printf("x request: ".("%02x " x min(128,length($_[0])))."\n",  
                    unpack("C*",$_[0])); 
             print "x request length = ",length($_[0]),"\n"; 
         } 
     } 
      
     sub x_open_display { 
         my($displayname) = @_; 
         my($node, $off, $screen, $base); 
     #  local(XFD); 
         my($reply)=""; 
         my $result = {}; 
         my (@root, @pixmap_format); 
      
         ($node, $off, $screen) = split_display($displayname); 
         $result->{"Screen"} = $screen; 
         print "x_open_display: n=$node, o=$off, s=$screen\n" if $debug; 
         if ($node eq "") { 
             # get a socket... /tmp/.X11-unix/X\d are unix domain sockets 
             my $path = "/tmp/.X11-unix/X$off"; 
             $status = &mkport_unix($path,\*XFD); 
         } else { 
             ($name, $aliases, $type, $len, $thisaddr) = gethostbyname($nod\ 
     e); 
             $status = &mkport($thisaddr,$X::TCP_PORT+$off,\*XFD); 
             if($status ne "OK") { return undef; } 
         } 
         $result->{"XFD"} = \*XFD; 
        
         my $xauth = search_xauth_file($displayname); 
     # network byte order is MSB first 
     # byte "B" for MSB first, then CARD16 major, CARD16 minor, 
     #  STRING8 auth prot name, STRING8 auth prot data 
         my $xauthname = defined($xauth)?$xauth->{"authname"}:""; 
         my $xauthdata = defined($xauth)?$xauth->{"authdata"}:""; 
         my $x= xpack("xConnClientPrefix", 
                      unpack("S","lB")&255, 
                      $X::PROTOCOL, $X::PROTOCOL_REVISION, 
                      length($xauthname), 
                      length($xauthdata), 
                      0); 
         $x.= $xauthname; 
         $x .= "\0" x (&pad4(length($x))-length($x)); 
         $x.= $xauthdata; 
         $x .= "\0" x (&pad4(length($x))-length($x)); 
      
         $xseqnum = 0; 
         serverprint($result, $x); 
         print STDOUT "reading...\n" if $debug; 
         # "read" doesn't work anymore with 1024, though shorter vals are o\ 
     k 
         # perhaps we should just read sizeof(xConnSetupPrefix)? 
         sysread(XFD,$reply,1024) || ($status = "read:$!" && return undef); 
         print STDOUT "done reading...\n" if $debug; 
      
         my($output) = &xlibconvert("xConnSetupPrefix",$reply); 
         $success = $output->{"success"}; 
       if($success == 0) { 
           print "Proto Major: ", $output->{"majorVersion"}, 
                 " Proto Minor: ", $output->{"minorVersion"}, "\n"; 
           $rlen = $output->{"lengthReason"}; 
           $xlen = $output->{"sizeof"}; 
           print "reason len: $rlen\n"; 
           $reason = substr($reply,$xlen,$rlen); 
           $status = "open failed: $reason"; 
           return undef; 
       } else { 
           $xlen = $output->{"sizeof"}; 
           $output = &xlibconvert("xConnSetup", substr($reply, $xlen)); 
           debugxlib($output) if $debug; 
           $result->{"setup"} = $output; 
           $xlen += $output->{"sizeof"}; 
           $vlen = $output->{"nbytesVendor"}; 
           $vendor = substr($reply, $xlen, $vlen); 
           print "Vendor: $vendor\n" if $debug; 
           $result->{"vendor"} = $vendor; 
           # ignore the rest for now... 
           # @output contains most of the fields... 
           $resource_id_base = $output->{"ridBase"}; 
           $resource_id_mask = $output->{"ridMask"}; 
           $resource_id_ctr = 1;        # store this in $result too? 
      
           $max_request_size = $output->{"maxRequestSize"}; 
      
           $nroots = $output->{"numRoots"}; 
           $nformats = $output->{"numFormats"}; 
           $base = &pad4($xlen+$vlen); 
           for $i (0..$nformats-1) { 
               $pixmap_format[$i] =  
                   &xlibconvert("xPixmapFormat", substr($reply, $base)); 
               debugxlib($pixmap_format[$i]) if $debug; 
               $base += $pixmap_format[$i]->{"sizeof"}; 
           } 
           $result->{"Formats"} = \@pixmap_format; 
           # $rootbase = &pad4($xlen+$vlen)+$X::xsizeof{"xPixmapFormat"}*$n\ 
     formats; 
           # just use the first root for now... 
           for $i (0..$nroots-1) { 
               $root[$i] = &xlibconvert("xWindowRoot", substr($reply,$base)\ 
     ); 
               $base += $root[$i]->{"sizeof"}; 
               debugxlib($root[$i]) if $debug; 
               for $j (0..$root[$i]->{"nDepths"}-1) { 
                   my $d = &xlibconvert("xDepth", substr($reply,$base)); 
                   debugxlib($d) if $debug; 
                   $root[$i]->{"depth"}[$j] = $d; 
                   $base += $d->{"sizeof"}; 
                   for $k (0..$d->{"nVisuals"}-1) { 
                       my $v = &xlibconvert("xVisualType",substr($reply,$ba\ 
     se)); 
                       debugxlib($v) if $debug; 
                       $d->{"visual"}[$k] = $v; 
                       $base += $v->{"sizeof"}; 
                   } 
               } 
           } 
           $result->{"readqueue"} = substr($reply,$base); 
           $result->{"Roots"} = \@root; 
      
           $root_window = $root[$screen]->{"windowId"}; 
           $root_white = $root[$screen]->{"whitePixel"}; 
           $root_black = $root[$screen]->{"blackPixel"}; 
      
           print "Root Window: $root_window\n" if $debug; 
           return $result; 
       } 
     } 
     sub xdebugdisplay {                        # xopendisplay result 
         my $disp = shift; 
         my ($i, $j, $k); 
         my ($format, $root, $depth, $visual); 
         debugxlib($disp->{"setup"}); 
         for $i (0..$disp->{"setup"}->{"numFormats"}-1) { 
             my $format = $disp->{"Formats"}[$i]; 
             debugxlib($format); 
         } 
         for $i (0..$disp->{"setup"}->{"numRoots"}-1) { 
             my $root = $disp->{"Roots"}[$i]; 
             print "Root $i\n"; 
             debugxlib($root); 
             for $j (0..$root->{"nDepths"}-1) { 
                 my $depth = $root->{"depth"}[$j]; 
                 print "Root $i Depth $j\n"; 
                 debugxlib($depth); 
                 for $k (0..$depth->{"nVisuals"}-1) { 
                     my $visual = $depth->{"visual"}[$k]; 
                     print "Root $i Depth $j Visual $k\n"; 
                     debugxlib($visual); 
                 } 
             } 
         } 
     } 
     sub next_resource_id { 
         $resource_id_base | ($resource_id_mask & $resource_id_ctr++); 
     } 
     sub pad4 { (($_[0]+3)>>2)<<2; } 
     sub x_beep { 
         my ($d,$percentage) = @_; 
         serverprint($d,X::newxBellReq($percentage)); 
         "OK"; 
     } 
     sub x_washwindow { 
         my ($func, $d, $w) = @_; 
         serverprint($d, &{$X::xsubs{"x${func}Req"}}($w)); 
         "OK" 
     } 
     sub x_destroywindow { x_washwindow("DestroyWindow", @_); } 
     sub x_destroysubwindows { x_washwindow("DestroySubwindows", @_); } 
     sub x_mapwindow { x_washwindow("MapWindow", @_); } 
     sub x_mapsubwindows { x_washwindow("MapSubwindows", @_); } 
     sub x_unmapwindow { x_washwindow("UnmapWindow", @_); } 
     sub x_unmapsubwindows { x_washwindow("UnmapSubwindows", @_); } 
     sub x_configurewindow { 
         my($d,$wind,$mask,@vals)=@_; 
         genvec2($d, "xConfigureWindowReq", "XID", [$wind,$mask], \@vals); 
     } 
      
     sub x_reparentwindow { 
         my ($d, $w, $p, $x, $y) = @_; 
         serverprint($d, X::newxReparentWindowReq($w,$p,$x,$y)); 
         "OK" 
     } 
      
     sub x_circulatewindow { 
         my ($d, $dir, $w) = @_; 
         serverprint($d, X::newxCirculateWindowReq($dir,$w)); 
         "OK" 
     } 
      
     sub x_changesaveset { 
         my ($d, $mode, $win) = @_; 
         serverprint($d, X::newxChangeSaveSetReq($mode,$win)); 
         "OK"; 
     } 
      
     sub x_clear_area { 
         my($d, $wind, $expose, $x,$y,$width,$height)=@_; 
         serverprint($d, X::newxClearAreaReq($expose,$wind, $x,$y,$width,$h\ 
     eight)); 
         "OK"; 
     } 
      
     sub x_create_pixmap { 
         my($d,$draw, $depth, $width, $height)=@_; 
         my($ret); 
         # 4 is length -- fix it? 
         serverprint($d,X::newxCreatePixmapReq($depth, $ret = &next_resourc\ 
     e_id, 
                                            $draw, $width, $height)); 
         $ret; 
     } 
     sub x_create_gc { 
         my($d,$draw, $mask, @vals)=@_; 
         my($ret); 
         genvec2($d,"xCreateGCReq","XID", [$ret = &next_resource_id, $draw,\ 
      $mask], 
                 \@vals); 
         $ret; 
     } 
     sub x_put_image { 
         my($d,$draw,$gc,$format,$image,$destx,$desty,$width,$height,$lpad,\ 
     $depth,$bpl) 
             = @_; 
         my($imm,$lns,$off_l,$off); 
         my($chunk_lines,$chunk_bytes); 
         my $overhead = $X::xsizeof{"xPutImageReq"}; 
         my $maxreq = (4*$max_request_size)-$overhead; 
         $lns = $xh; 
         $off_l = 0; 
         $off = 0; 
         $chunk_lines = int($maxreq/$bpl); 
         $chunk_bytes = $bpl * $chunk_lines; 
         while(length($image)-$off > $maxreq) { 
             $imm = substr($image, $off, $chunk_bytes); 
             # print "imm: ",length($imm),"\n"; 
             &xlib::x_real_put_image($d,$draw,$gc,$format, 
                                     $imm,$destx,$desty+$off_l, 
                                     $width,$chunk_lines,$lpad,$depth); 
             $off_l += $chunk_lines; 
             $off = $bpl * $off_l; 
         } 
         $off = $bpl * $off_l; 
         if (length($image)-$off > 0) { 
             $imm = substr($image, $off); 
             # print "imm trail: ",length($imm),"\n"; 
             &xlib::x_real_put_image($d,$draw,$gc,$format, 
                                     $imm,$destx,$desty+$off_l, 
                                     $width,$height-$off_l,$lpad,$depth); 
         } 
     } 
      
     sub x_real_put_image { 
         my($d,$draw,$gc,$format,$image,$destx,$desty,$width,$height,$lpad,\ 
     $depth) 
             = @_; 
      
         genvecstr($d, "xPutImageReq", [$format, $draw, $gc, $width, $heigh\ 
     t, 
                                        $destx, $desty, $lpad, $depth], $im\ 
     age); 
         "OK"; 
     } 
     sub x_get_window_attributes { 
         my ($d,$w) = @_; 
         my ($rep,$q) = x_reply($d, "GetWindowAttributes", [$w]); 
         $rep; 
     } 
     sub x_change_window_attributes { 
         my $d = shift; 
         my ($win, $mask, @vals) = @_; 
         genvec2($d, "xChangeWindowAttributesReq", "XID", [$win,$mask], \@v\ 
     als); 
     } 
     sub x_set_window_background_pixmap { 
         my($d,$wind,$pixmap)=@_; 
         x_change_window_attributes($d,$wind,$X::defines{"CWBackPixmap"},$p\ 
     ixmap); 
     } 
      
     sub extend_queue { 
         my $d = shift; 
         my $l = shift; 
         while (length ($d->{"readqueue"}) < $l) { 
             my $data = ""; 
             sysread($d->{"XFD"},$data,1024) || die "$! in extend_queue"\ 
     ; 
             $d->{"readqueue"} .= $data; 
         } 
     } 
      
     sub x_getatomname { 
         my ($d,$atom) = @_; 
         my ($rep,$q) = x_reply($d,"GetAtomName", [$atom]); 
         my $sl = $rep->{"nameLength"}; 
         my $name; my $pl = pad4($sl)-$sl; 
         ($name,$$q) = unpack("a$sl x$pl a*", $$q); 
         print "atom name: $name\n" if $debug; 
         $name; 
     } 
      
     sub x_internatom { 
         my ($d,$exists,$name) = @_; 
         genvecstr($d, "xInternAtomReq", [$exists,length($name)], $name); 
         handle_event($d); 
         my ($rep,$q) = xqueueconvert($d,"xInternAtomReply"); 
         $rep->{"atom"}; 
     } 
      
     sub x_getproperty { 
         my ($d,$flag,$win,$prop,$type,$loff,$llen) = @_; 
         my ($rep,$q) =  
             x_reply($d,"GetProperty", [$flag,$win,$prop,$type,$loff,$llen]\ 
     ); 
         my $f = $rep->{"format"};        # 0 8 16 32 
         my $sl = $rep->{"nItems"}*$f/8; 
         my $val; my $pl = pad4($sl)-$sl; 
         ($val,$$q) = unpack("a$sl x$pl a*", $$q); 
         print "atom value: $val\n" if $debug && ($f eq 8); 
         return ($f, $val, $rep->{"propertyType"}); 
     } 
      
     sub x_changeproperty { 
         my ($d,$mode,$win,$prop,$type,$form,@vals) = @_; 
         # for format=8, use a string, else a list 
         my $p = "CARD$form"; 
         if ($form == 8) { 
             @vals = unpack("C*",$vals[0]); 
         } 
         genvec2($d,"xChangePropertyReq",$p, 
                 [$mode,$win,$prop,$type,$form,scalar(@vals)], \@vals); 
         "OK"; 
     } 
      
     sub x_deleteproperty { 
         my ($d, $w, $a) = @_; 
         serverprint($d, X::newxDeletePropertyReq($w,$a)); 
         "OK"; 
     } 
      
     sub x_getfontpath { 
         my ($d) = @_; 
         x_iter($d, "GetFontPath", "nPaths", "STRING8"); 
     } 
     sub x_listfonts { 
         my ($d, $f) = @_; 
         x_iter($d,"ListFonts","nFonts","STRING8", [-1,length($f),$f]); 
     } 
      
     sub x_listextensions { 
         my ($d) = @_; 
         x_iter($d,"ListExtensions","nExtensions","STRING8"); 
     } 
     sub x_get_geometry {                # very much like GetWindowAttribut\ 
     es... 
         my ($d,$w) = @_; 
         my ($rep,$q) = x_reply($d, "GetGeometry", [$w]); 
         $rep; 
     } 
     sub x_get_one {  
         my ($type, $d) = @_; 
         my ($rep,$q) = x_reply($d, $type); 
         $rep; 
     } 
     sub x_get_input_focus { x_get_one("GetInputFocus",@_); } 
     sub x_get_keyboard_control { x_get_one("GetKeyboardControl",@_); } 
     require "./xerror.pl"; 
     sub handle_event { 
         my $d = shift; 
         my $rep; 
         my $q = \$d->{"readqueue"}; 
         extend_queue($d, $X::xsizeof{"xEvent"}); 
         $rep = xlibconvert("xGenericReply",$$q); 
         if ($rep->{"type"} == $X::Reply) { 
             print "reply: \n" if $debug; 
             debugxlib($rep) if $debug; 
             extend_queue($d, $X::xsizeof{"xEvent"}+4*$rep->{"length"}); 
             # handle reply 
             return $rep->{"length"}; 
         } elsif ($rep->{"type"} == $X::Error) { 
             # handle error 
             $rep = &xlibconvert("xError",$$q); 
             print "xerror: $X::ErrorList[$rep->{errorCode}]\n"; 
             printf "xerror: resid %x\n", $rep->{"resourceID"}; 
             print  "major:  $X::requests[$rep->{majorCode}]\n"; 
             debugxlib($rep); 
             $$q = substr($$q,$rep->{"sizeof"}); 
             return undef; 
         } else { 
             # process the event off the input queue and on to the event qu\ 
     eue... 
             $rep = xlibconvert("u",$$q); 
             print "xevent: $X::xevents[$rep->{type}]\n" if $debug; 
             my $h = $handler{$X::xevents[$rep->{"type"}]}; 
             &$h if (defined $h); 
             debugxlib($rep) if $debug || !defined($h); 
             skipevent($d, "xEvent"); 
             return 0; 
         } 
         return -1; 
     } 
     sub skipevent { # tag  
         my ($d,$tag) = @_; 
         my $q = \$d->{"readqueue"}; 
         $$q = substr($$q, $X::xsizeof{$tag}); 
         print "event queue length: ",length($$q),"\n" if $debug; 
     } 
      
     sub xqueueconvert { 
         my ($d,$tag) = @_; 
         my $ret = xlibconvert($tag,$d->{"readqueue"}); 
         debugxlib($rep) if $debug; 
         skipevent($d, $tag); 
         ($ret, \$d->{"readqueue"}); 
     }     
      
     sub defaultroot { 
         my $d = shift; 
         return $d->{"Roots"}[$d->{"Screen"}]->{"windowId"}; 
     } 
     sub defaultrootdepth { 
         my $d = shift; 
         return $d->{"Roots"}[$d->{"Screen"}]->{"rootDepth"}; 
     } 
      
     sub x_reply { 
         my ($d, $func, $args) = @_; 
         serverprint($d, &{$X::xsubs{"newx${func}Req"}}(@$args)); 
         handle_event($d); 
         xqueueconvert($d,"x${func}Reply"); 
     } 
     sub x_iter_raw { 
         my ($d, $func, $counter, $vtype, $args) = @_; 
         my ($rep,$q) = x_reply($d, $func, $args); 
         my ($val,$i,@ret); 
         for $i (1..$rep->{$counter}) { 
             if ($vtype eq "STRING8") { 
                 my ($sl) = unpack("C",$$q); 
                 ($sl,$val,$$q) = unpack("C a$sl a*", $$q); 
             } else { 
                 ($val,$$q) = unpack($X::xpackof{$vtype}."a*", $$q); 
             } 
             print "$vtype: <$val>\n" if $debug; 
             push(@ret,$val); 
         } 
         return ($rep, @ret);        # some reps have useful info... 
     } 
      
     sub x_iter { 
         my ($rep,@ret) = x_iter_raw(@_); 
         return @ret; 
     } 
     sub x_listproperties { 
         my ($d, $w) = @_; 
         x_iter($d, "ListProperties", "nProperties", "Atom", [$w]); 
     } 
      
     sub x_querytree { 
         my ($d, $root) = @_; 
         $root = defaultroot($d) if (!defined($root)); 
         x_iter_raw($d, "QueryTree", "nChildren", "Window", [$root]); 
     } 
      
     sub x_get_keyboard_mapping { 
         my ($d, $first, $count) = @_; 
         x_iter_raw($d, "GetKeyboardMapping","length","KeySym", [$first,$co\ 
     unt]); 
     } 
     sub x_get_modifier_mapping { 
         my ($d) = @_; 
         x_iter_raw($d, "GetModifierMapping","length","KeyCode"); 
     } 
      
     sub x_get_pointer_mapping { 
         my ($d) = @_; 
         x_iter($d, "GetPointerMapping","nElts","CARD8"); 
     } 
     sub x_imagetext8 { 
         my $d = shift; 
         my ($w, $gc, $x, $y, $string) = @_; 
         my $l = length($string);  
         genvecstr($d, "xImageText8Req", [$l,$w,$gc,$x,$y], $string); 
         "OK"; 
     } 
     sub x_openfont { 
         my $d = shift; 
         my ($f) = (@_);                # font name 
         my $l = length($f);  
         genvecstr($d, "xOpenFontReq", [$ret = &next_resource_id,$l], $f); 
         $ret; 
     } 
     sub splitcolor { 
         my ($c) = @_; 
         return ($$c[0],$$c[1],$$c[2]); 
     } 
      
     sub joincolor { 
         my ($r,$g,$b) = @_; 
         return [$r,$g,$b]; 
     } 
     sub x_createfontcursor { 
         my ($d,$ch,$fore,$back) = @_; 
         if (!defined($d->{"cursorfont"})) { 
             $d->{"cursorfont"} = x_openfont($d,"cursor"); 
         } 
         my $c = $d->{"cursorfont"}; 
         my $cursor; 
         my ($fr,$fg,$fb) = splitcolor($fore); 
         my ($br,$bg,$bb) = splitcolor($back); 
         print "Fore($fore): $fr,$fg,$fb\n" if $debug; 
         print "Back($back): $br,$bg,$bb\n" if $debug; 
         serverprint($d, 
                     &X::newxCreateGlyphCursorReq($cursor = &next_resource_\ 
     id, 
                                                  $c, # sourcefont 
                                                  $c, # maskfont 
                                                  $ch, # sourcechar 
                                                  $ch+1, # maskchar 
                                                  $fr, $fg, $fb, 
                                                  $br, $bg, $bb)); 
         $cursor; 
     } 
      
     sub x_closedisplay { 
         my $d = shift; 
         close $d->{"XFD"}; 
     } 
     sub x_create_window { 
         my($d,$depth,$parent,$x,$y,$w,$h,$bwid,$class,$vis,$mask, @vals) =\ 
      @_; 
         my($ret); 
         genvec2($d,"xCreateWindowReq","XID",  
                 [$depth, $ret = &next_resource_id, $parent,  
                  $x,$y,$w,$h,$bwid, $class, $vis, $mask], \@vals); 
         $ret; 
     } 
      
     sub genvec { 
         my ($type, @vals) = @_; 
         my $p = $X::xpackof{$type}; 
         my $nvals = length(pack("C*",unpack($p," "x80))); 
         my $val = ""; 
         while(1) { 
             my @v = splice(@vals,0,$nvals); 
             $val .= pack($p, @v); 
             last if scalar(@vals) <= 0; 
         } 
         return $val; 
     } 
     sub genvec2 { 
         my ($d, $req, $elem, $args, $vals) = @_; 
         my $val = genvec($elem, @$vals); 
         serverprint($d,&{$X::xsubs{"new$req"}}(@$args,$val)); 
         "OK"; 
     } 
      
     sub genvecstr { 
         my ($d, $req, $args, $val) = @_; 
         serverprint($d,&{$X::xsubs{"new$req"}}(@$args,$val)); 
         "OK"; 
     } 
      
     sub xpoly1 { 
         my ($req, $type, $d, $draw, $gc, @vals) = @_; 
         genvec2($d, "x${req}Req", "x$type", [$draw,$gc], \@vals); 
     } 
     sub xpolyarcs { xpoly1("PolyArc", "Arc", @_); } 
     sub xpolyfillarcs { xpoly1("PolyFillArc", "Arc", @_); } 
     sub xpolyrects { xpoly1("PolyRectangle", "Rectangle", @_); } 
     sub xpolyfillrects { xpoly1("PolyFillRectangle", "Rectangle", @_); } 
     sub xpolysegments { xpoly1("PolySegment", "Segment", @_); } 
      
     sub xpoly2 { 
         my ($req, $type, $d, $mode, $draw, $gc, @points) = @_; 
         genvec2($d,"x${req}Req", "x$type", [$mode,$draw,$gc], \@points); 
     } 
     sub xpolypoints { xpoly2("PolyPoint", "Point", @_); } 
     sub xpolylines { xpoly2("PolyLine", "Point", @_); } 
     sub xsetselectionowner {  
         my ($d,$owner,$selection,$time) = @_; 
         serverprint($d, X::newxSetSelectionOwner($owner,$selection,$time))\ 
     ; 
         "OK"; 
     } 
     sub xgetselectionowner { 
         my ($d) = @_; 
         my ($rep,$q) = x_reply($d, "GetSelectionOwner"); 
         $rep->{"owner"}; 
     } 
     sub xconvertselection {  
         my ($d,$who,$selection,$target,$prop,$time) = @_; 
         serverprint($d,  
                   X::newxConvertSelection($who,$selection,$target,$prop,$t\ 
     ime)); 
         "OK"; 
     } 
      
     # calls this as  
     # should be: xsendevent($d,false,PointerWindow,0,X::newxWhatever(...))\ 
     ; 
     # xsendevent($d,false,PointerWindow,0,pack($X::xpackof{"selectionClear\ 
     "},...)); 
     sub xsendevent { 
         my ($d,$prop,$dest,$mask,$event) = @_; 
         serverprint($d, X::newxSendEventReq($prop,$dest,$mask,unpack("C32"\ 
     ,$event))); 
         "OK"; 
     } 
     sub xgrabpointer { 
         my ($d,$owner,$gwind,$mask,$pmode,$kmode,$confw,$cursor,$time) = @\ 
     _; 
         my ($rep,$q) = x_reply($d, "GrabPointer",  
                                [$owner,$gwind,$mask,$pmode,$kmode,$confw,$\ 
     cursor,$time]); 
         return $rep->{"status"}; 
     } 
     sub xgrabkeyboard { 
         my ($d,$owner,$wind,$time,$pmode,$kmode) = @_; 
         my ($rep,$q) = x_reply($d, "GrabKeyboard", 
                                [$owner,$wind,$time,$pmode,$kmode]); 
         return $rep->{"status"}; 
     } 
     sub xgrabserver { 
         my ($d) = @_; 
         serverprint($d, X::xGrabServerReq()); 
         "OK"; 
     } 
     sub xgrabbutton { 
         my ($d,$owner,$grabw,$mask,$pmode,$kmode,$confw,$cursor,$button,$m\ 
     ods) 
             = @_; 
         serverprint($d, X::newxGrabButtonReq($owner,$grabw,$mask,$pmode,$k\ 
     mode,$confw,$cursor,$button,$mods)); 
         "OK"; 
     } 
     sub xgrabkey { 
         my ($d,$owner,$grabw,$mods,$key,$pmode,$kmode) = @_; 
         serverprint($d, X::xGrabKeyReq($owner,$grabw,$mods,$key,$pmode,$km\ 
     ode)); 
         "OK"; 
     } 
      
     sub x_ungrab { 
         my ($func, $d, @args) = @_; 
         serverprint($d, &{$X::xsubs{"newxUngrab${func}Req"}}(@args)); 
         "OK"; 
     } 
     sub xungrabpointer { x_ungrab("Pointer", @_); }        # time 
     sub xungrabkeyboard { x_ungrab("Keyboard", @_); } # time 
     sub xungrabbutton { x_ungrab("Button", @_); } # button,window,mods 
     sub xungrabkey { x_ungrab("Key", @_); }        # keycode,window,mods 
     sub xungrabserver { x_ungrab("Server", @_); } # nothing 
     sub xallowevents { 
         my ($d,$mode,$time) = @_; 
         serverprint($d, X::newxAllowEventsReq($mode,$time)); 
         "OK"; 
     } 
     sub xchangeactivepointergrab { 
         my ($d, $cursor, $time, $mask) = @_; 
         serverprint($d, X::newxChangeActivePointerGrabReq($cursor,$time,$m\ 
     ask)); 
         "OK"; 
     } 
     sub xquerypointer {                # just like x_get_geometry 
         my ($d, $w) = @_; 
         my ($rep,$q) = x_reply($d, "QueryPointer", [$w]); 
         $rep; 
     } 
     1; 

    Issue_05_X
    13. xbeep.pl

    Download xbeep.pl

     #!perl 
     require "./xbase.pl"; 
     $xopen = &xlib::x_open_display($ENV{"DISPLAY"}); 
     die $xlib::status if not defined $xopen; 
      
     print &xlib::x_beep($xopen,25),"\n"; 
     xlib::x_closedisplay($xopen); 

    Issue_05_X
    14. xdpyinfo.pl

    Download xdpyinfo.pl

     #!perl 
     require "./xbase.pl"; 
     $xopen = &xlib::x_open_display($ENV{"DISPLAY"}); 
     die $xlib::status if not defined $xopen; 
      
     &xlib::xdebugdisplay($xopen); 
     print "remaining in queue: ",length($xopen->{"readqueue"}),"\n"; 
     @le = &xlib::x_listextensions($xopen); 
     print "extensions: ", join("\n      name: ",@le), "\n"; 
     close $xopen->{"XFD"}; 

    Issue_05_X
    15. xerror.pl

    Download xerror.pl

     #/* 
     # * descriptions of errors in Section 4 of Protocol doc (pp. 350-351);\ 
      more 
     # * verbose descriptions are given in the error database 
     # */ 
     # static Const char * Const _XErrorList[] = { 
     @X::ErrorList = ( 
     "no error", 
     "BadRequest", 
     "BadValue", 
     "BadWindow", 
     "BadPixmap", 
     "BadAtom", 
     "BadCursor", 
     "BadFont", 
     "BadMatch", 
     "BadDrawable", 
     "BadAccess", 
     "BadAlloc", 
     "BadColor", 
     "BadGC", 
     "BadIDChoice", 
     "BadName", 
     "BadLength", 
     "BadImplementation", 
     ); 

    Issue_05_X
    16. xint.perl

  • xint.perl
  • Issue_05_X
    17. xlsfont.pl

    Download xlsfont.pl

     #!perl 
     require "./xbase.pl"; 
     $xopen = &xlib::x_open_display($ENV{"DISPLAY"}); 
     die $xlib::status if not defined $xopen; 
      
     $xlib::debugpkt = 1; 
     @lf = &xlib::x_listfonts($xopen,shift); 
     print "fontnames: ", join("\n    name: ",@lf), "\n"; 
      
     close $xopen->{"XFD"}; 

    Issue_05_X
    18. xwdhead.pl

    Download xwdhead.pl

     #!perl 
     package xlib; 
      
     #   read(XWDFILE,$dat,$X::xsizeof{"XWDFileHeader"}) || return "read:$!\ 
     "; 
     #   read(XWDFILE,$win_nam, $xwddat->{"header_size"} - $xwddat->{\ 
     "sizeof"}) 
     #   read(XWDFILE,$xwd_colors, $X::xsizeof{"xColorItem"} * $xwddat->\ 
     {"ncolors"}) 
     #   read(XWDFILE,$xwd_image, $xwddat->{"bytes_per_line"} * $xwd_ima\ 
     ge_height) 
     sub getxwd_read { 
         my($fname) = @_; 
         open(XWDFILE,$fname) || die "getxwd_read: $fname: $!"; 
         sub xread { 
             my $v=""; my $sz = shift; 
             read(XWDFILE,$v,$sz) || die "xread: $!"; 
             return $v; 
         } 
         getxwd_core(\&xread); 
     } 
      
     sub getxwd_str { 
         my($xwdbits)=@_; 
         my $ptr = 0; 
         sub xsubstr { 
             my $sz = shift; 
             my $v = substr($xwdbits,$ptr,$sz); 
             $ptr += $sz; 
             return $v; 
         } 
         getxwd_core(\&xsubstr); 
     } 
      
     sub getxwd_core { 
         my($readfn)=@_; 
         my($dat) = ""; 
         $win_nam=""; 
         $xwd_colors=""; 
         $xwd_image=""; 
         $dat = &$readfn($X::xsizeof{"XWDFileHeader"}); 
         $xwddat = xlibconvert("XWDFileHeader",$dat); 
          
         if ($X::defines{"XWD_FILE_VERSION"} !=  
             $xwddat->{"file_version"}) { 
             $X::xpackof{"XWDFileHeader"} =~ s/L/N/g; 
             $xwddat = xlibconvert("XWDFileHeader",$dat); 
             if ($X::defines{"XWD_FILE_VERSION"} !=  
                 $xwddat->{"file_version"}) { 
                 return "xwud: XWD file format version missmatch."; 
             } 
         } 
         if ($xwddat->{"header_size"} < $xwddat->{"sizeof"}) { 
             return "xwud: XWD header size is too small."; 
         } 
         $win_nam = &$readfn($xwddat->{"header_size"} - $xwddat->{"si\ 
     zeof"}); 
         $xwd_image_width = $xwddat->{"pixmap_width"}; 
         $xwd_image_height = $xwddat->{"pixmap_height"}; 
         $xwd_image_depth = $xwddat->{"pixmap_depth"}; 
     # coincidentally, XColorItem is the same as XColor... 
         $xwd_colors = &$readfn($X::xsizeof{"xColorItem"} * $xwddat->{"n\ 
     colors"}); 
         $xwd_image  = &$readfn($xwddat->{"bytes_per_line"} * $xwd_image\ 
     _height); 
         return "OK"; 
     } 
     1; 

    Issue_05_X
    19. xwininfo.c

    Download xwininfo.c

     /* $XConsortium: xwininfo.c,v 1.55 94/04/17 20:24:40 rws Exp $ */ 
     /* 
      
     Copyright (c) 1987  X Consortium 
      
     Permission is hereby granted, free of charge, to any person obtaining 
     a copy of this software and associated documentation files (the 
     "Software"), to deal in the Software without restriction, including 
     without limitation the rights to use, copy, modify, merge, publish, 
     distribute, sublicense, and/or sell copies of the Software, and to 
     permit persons to whom the Software is furnished to do so, subject to 
     the following conditions: 
      
     The above copyright notice and this permission notice shall be include\ 
     d 
     in all copies or substantial portions of the Software. 
     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRES\ 
     S 
     OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 
     MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 
     IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR 
     OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 
     ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 
     OTHER DEALINGS IN THE SOFTWARE. 
     Except as contained in this notice, the name of the X Consortium shall 
     not be used in advertising or otherwise to promote the sale, use or 
     other dealings in this Software without prior written authorization 
     from the X Consortium. 
      
     */ 
      
     /* 
      * xwininfo.c        - MIT Project Athena, X Window system window 
      *                  information utility. 
      * 
      * 
      *        This program will report all relevant information 
      *        about a specific window. 
      * 
      *  Author:        Mark Lillibridge, MIT Project Athena 
      *                16-Jun-87 
      */ 
     #include <X11/Xlib.h> 
     #include <X11/Xutil.h> 
     #include <X11/Xatom.h> 
     #include <X11/Xos.h> 
     #include <X11/extensions/shape.h> 
     #include <X11/Xmu/WinUtil.h> 
     #include <stdio.h> 
     /* Include routines to handle parsing defaults */ 
     #include "dsimple.h" 
      
     static char *window_id_format = "0x%lx"; 
      
     /* 
      * Report the syntax for calling xwininfo: 
      */ 
     usage() 
     { 
         fprintf (stderr, 
             "usage:  %s [-options ...]\n\n", program_name); 
         fprintf (stderr, 
             "where options include:\n"); 
         fprintf (stderr, 
             "    -help                print this message\n"); 
         fprintf (stderr, 
             "    -display host:dpy    X server to contact\n"); 
         fprintf (stderr, 
             "    -root                use the root window\n"); 
         fprintf (stderr, 
             "    -id windowid         use the window with the specified id\ 
     \n"); 
         fprintf (stderr, 
             "    -name windowname     use the window with the specified na\ 
     me\n"); 
         fprintf (stderr, 
             "    -int                 print window id in decimal\n"); 
         fprintf (stderr, 
             "    -children            print parent and child identifiers\n\ 
     "); 
         fprintf (stderr, 
             "    -tree                print children identifiers recursive\ 
     ly\n"); 
         fprintf (stderr, 
             "    -stats               print window geometry [DEFAULT]\n"); 
         fprintf (stderr, 
             "    -bits                print window pixel information\n"); 
         fprintf (stderr, 
             "    -events              print events selected for on window\\ 
     n"); 
         fprintf (stderr, 
             "    -size                print size hints\n"); 
         fprintf (stderr, 
             "    -wm                  print window manager hints\n"); 
         fprintf (stderr, 
             "    -shape               print shape extents\n"); 
         fprintf (stderr, 
             "    -frame               don't ignore window manager frames\n\ 
     "); 
         fprintf (stderr, 
             "    -english             print sizes in english units\n"); 
         fprintf (stderr, 
             "    -metric              print sizes in metric units\n"); 
         fprintf (stderr, 
             "    -all                 -tree, -stats, -bits, -events, -wm, \ 
     -size, -shape\n"); 
         fprintf (stderr, 
             "\n"); 
         exit (1); 
     } 
      
     /* 
      * pixel to inch, metric converter. 
      * Hacked in by Mark W. Eichin <eichin@athena> [eichin:19880619.\ 
     1509EST] 
      * 
      * Simply put: replace the old numbers with string print calls. 
      * Returning a local string is ok, since we only ever get called to 
      * print one x and one y, so as long as they don't collide, they're 
      * fine. This is not meant to be a general purpose routine. 
      * 
      */ 
     #define getdsp(var,fn) var = fn(dpy, DefaultScreen(dpy)) 
     int xp=0, xmm=0; 
     int yp=0, ymm=0; 
     int bp=0, bmm=0; 
     int english = 0, metric = 0; 
     void scale_init() 
     { 
       getdsp(yp,  DisplayHeight); 
       getdsp(ymm, DisplayHeightMM); 
       getdsp(xp,  DisplayWidth); 
       getdsp(xmm, DisplayWidthMM); 
       bp  = xp  + yp; 
       bmm = xmm + ymm; 
     } 
     #define MILE (5280*12) 
     #define YARD (3*12) 
     #define FOOT (12) 
     char *nscale(n, np, nmm, nbuf) 
          int n, np, nmm; 
          char *nbuf; 
     { 
       sprintf(nbuf, "%d", n); 
       if(metric||english) { 
         sprintf(nbuf+strlen(nbuf), " ("); 
       } 
       if(metric) { 
         sprintf(nbuf+strlen(nbuf),"%.2f mm%s", ((double) n)*nmm/np, englis\ 
     h?"; ":""); 
       } 
       if(english) { 
         double inch_frac; 
         Bool printed_anything = False; 
         int mi, yar, ft, inr; 
         inch_frac = ((double) n)*(nmm/25.4)/np; 
         inr = (int)inch_frac; 
         inch_frac -= (double)inr; 
         if(inr>=MILE) { 
           mi = inr/MILE; 
           inr %= MILE; 
           sprintf(nbuf+strlen(nbuf), "%d %s(?!?)", 
                   mi, (mi==1)?"mile":"miles"); 
           printed_anything = True; 
         } 
         if(inr>=YARD) { 
           yar = inr/YARD; 
           inr %= YARD; 
           if (printed_anything) 
               sprintf(nbuf+strlen(nbuf), ", "); 
           sprintf(nbuf+strlen(nbuf), "%d %s", 
                   yar, (yar==1)?"yard":"yards"); 
           printed_anything = True; 
         } 
         if(inr>=FOOT) { 
           ft = inr/FOOT; 
           inr  %= FOOT; 
           if (printed_anything) 
               sprintf(nbuf+strlen(nbuf), ", "); 
           sprintf(nbuf+strlen(nbuf), "%d %s", 
                   ft, (ft==1)?"foot":"feet"); 
           printed_anything = True; 
         } 
         if (!printed_anything || inch_frac != 0.0 || inr != 0) { 
           if (printed_anything) 
               sprintf(nbuf+strlen(nbuf), ", "); 
           sprintf(nbuf+strlen(nbuf), "%.2f inches", inr+inch_frac); 
         } 
       } 
       if (english || metric) strcat (nbuf, ")"); 
       return(nbuf); 
     }           
     char xbuf[BUFSIZ]; 
     char *xscale(x) 
          int x; 
     { 
       if(!xp) { 
         scale_init(); 
       } 
       return(nscale(x, xp, xmm, xbuf)); 
     } 
     char ybuf[BUFSIZ]; 
     char *yscale(y) 
          int y; 
     { 
       if(!yp) { 
         scale_init(); 
       } 
       return(nscale(y, yp, ymm, ybuf)); 
     } 
     char bbuf[BUFSIZ]; 
     char *bscale(b) 
          int b; 
     { 
       if(!bp) { 
         scale_init(); 
       } 
       return(nscale(b, bp, bmm, bbuf)); 
     } 
     /* end of pixel to inch, metric converter */ 
     /* This handler is enabled when we are checking 
        to see if the -id the user specified is valid. */ 
      
     /* ARGSUSED */ 
     bad_window_handler(disp, err) 
         Display *disp; 
         XErrorEvent *err; 
     { 
         char badid[20]; 
         sprintf(badid, window_id_format, err->resourceid); 
         Fatal_Error("No such window with id %s.", badid); 
         exit (1); 
     } 
      
     main(argc, argv) 
          int argc; 
          char **argv; 
     { 
       register int i; 
       int tree = 0, stats = 0, bits = 0, events = 0, wm = 0, size  = 0, sh\ 
     ape = 0; 
       int frame = 0, children = 0; 
       Window window; 
      
       INIT_NAME; 
      
       /* Open display, handle command line arguments */ 
       Setup_Display_And_Screen(&argc, argv); 
       /* Get window selected on command line, if any */ 
       window = Select_Window_Args(&argc, argv); 
      
       /* Handle our command line arguments */ 
       for (i = 1; i < argc; i++) { 
         if (!strcmp(argv[i], "-help")) 
           usage(); 
         if (!strcmp(argv[i], "-int")) { 
           window_id_format = "%ld"; 
           continue; 
         } 
         if (!strcmp(argv[i], "-children")) { 
           children = 1; 
           continue; 
         } 
         if (!strcmp(argv[i], "-tree")) { 
           tree = 1; 
           continue; 
         } 
         if (!strcmp(argv[i], "-stats")) { 
           stats = 1; 
           continue; 
         } 
         if (!strcmp(argv[i], "-bits")) { 
           bits = 1; 
           continue; 
         } 
         if (!strcmp(argv[i], "-events")) { 
           events = 1; 
           continue; 
         } 
         if (!strcmp(argv[i], "-wm")) { 
           wm = 1; 
           continue; 
         } 
         if (!strcmp(argv[i], "-frame")) { 
           frame = 1; 
           continue; 
         } 
         if (!strcmp(argv[i], "-size")) { 
           size = 1; 
           continue; 
         } 
         if (!strcmp(argv[i], "-shape")) { 
           shape = 1; 
           continue; 
         } 
         if (!strcmp(argv[i], "-english")) { 
           english = 1; 
           continue; 
         } 
         if (!strcmp(argv[i], "-metric")) { 
           metric = 1; 
           continue; 
         } 
         if (!strcmp(argv[i], "-all")) { 
           tree = stats = bits = events = wm = size = shape = 1; 
           continue; 
         } 
         usage(); 
       } 
       /* If no window selected on command line, let user pick one the hard\ 
      way */ 
       if (!window) { 
               printf("\n"); 
               printf("xwininfo: Please select the window about which you\n\ 
     "); 
               printf("          would like information by clicking the\n")\ 
     ; 
               printf("          mouse in that window.\n"); 
               window = Select_Window(dpy); 
               if (window && !frame) { 
                   Window root; 
                   int dummyi; 
                   unsigned int dummy; 
                   if (XGetGeometry (dpy, window, &root, &dummyi, &dummyi, 
                                     &dummy, &dummy, &dummy, &dummy) && 
                       window != root) 
                     window = XmuClientWindow (dpy, window); 
               } 
       } 
      
       /* 
        * Do the actual displaying as per parameters 
        */ 
       if (!(children || tree || bits || events || wm || size)) 
         stats = 1; 
      
       /* 
        * make sure that the window is valid 
        */ 
       { 
         Window root; 
         int x, y; 
         unsigned width, height, bw, depth; 
         int (*old_handler)(); 
         old_handler = XSetErrorHandler(bad_window_handler); 
         XGetGeometry (dpy, window, &root, &x, &y, &width, &height, &bw, &d\ 
     epth); 
         XSync (dpy, False); 
         (void) XSetErrorHandler(old_handler); 
       } 
       printf("\nxwininfo: Window id: "); 
       Display_Window_Id(window, True); 
       if (children || tree) 
         Display_Tree_Info(window, tree); 
       if (stats) 
         Display_Stats_Info(window); 
       if (bits) 
         Display_Bits_Info(window); 
       if (events) 
         Display_Events_Info(window); 
       if (wm) 
         Display_WM_Info(window); 
       if (size) 
         Display_Size_Hints(window); 
       if (shape) 
         Display_Window_Shape(window); 
       printf("\n"); 
       exit(0); 
     } 
      
     /* 
      * Lookup: lookup a code in a table. 
      */ 
     typedef struct { 
             long code; 
             char *name; 
     } binding; 
      
     static char _lookup_buffer[100]; 
      
     char *LookupL(code, table) 
         long code; 
         binding *table; 
     { 
             char *name; 
      
             sprintf(_lookup_buffer, "unknown (code = %ld. = 0x%lx)", code,\ 
      code); 
             name = _lookup_buffer; 
             while (table->name) { 
                     if (table->code == code) { 
                             name = table->name; 
                             break; 
                     } 
                     table++; 
             } 
             return(name); 
     } 
      
     char *Lookup(code, table) 
         int code; 
         binding *table; 
     { 
         return LookupL((long)code, table); 
     } 
     /* 
      * Routine to display a window id in dec/hex with name if window has o\ 
     ne 
      */ 
     Display_Window_Id(window, newline_wanted) 
         Window window; 
         Bool newline_wanted; 
     { 
         char *win_name; 
         printf(window_id_format, window);         /* print id # in hex/dec\ 
      */ 
         if (!window) { 
             printf(" (none)"); 
         } else { 
             if (window == RootWindow(dpy, screen)) { 
                 printf(" (the root window)"); 
             } 
             if (!XFetchName(dpy, window, &win_name)) { /* Get window name \ 
     if any */ 
                 printf(" (has no name)"); 
             } else if (win_name) { 
                 printf(" \"%s\"", win_name); 
                 XFree(win_name); 
             } else 
                 printf(" (has no name)"); 
         } 
      
         if (newline_wanted) 
             printf("\n"); 
         return; 
     } 
      
     /* 
      * Display Stats on window 
      */ 
     static binding _window_classes[] = { 
             { InputOutput, "InputOutput" }, 
             { InputOnly, "InputOnly" }, 
             { 0, 0 } }; 
     static binding _map_states[] = { 
             { IsUnmapped, "IsUnMapped" }, 
             { IsUnviewable, "IsUnviewable" }, 
             { IsViewable, "IsViewable" }, 
             { 0, 0 } }; 
     static binding _backing_store_states[] = { 
             { NotUseful, "NotUseful" }, 
             { WhenMapped, "WhenMapped" }, 
             { Always, "Always" }, 
             { 0, 0 } }; 
     static binding _bit_gravity_states[] = { 
             { ForgetGravity, "ForgetGravity" }, 
             { NorthWestGravity, "NorthWestGravity" }, 
             { NorthGravity, "NorthGravity" }, 
             { NorthEastGravity, "NorthEastGravity" }, 
             { WestGravity, "WestGravity" }, 
             { CenterGravity, "CenterGravity" }, 
             { EastGravity, "EastGravity" }, 
             { SouthWestGravity, "SouthWestGravity" }, 
             { SouthGravity, "SouthGravity" }, 
             { SouthEastGravity, "SouthEastGravity" }, 
             { StaticGravity, "StaticGravity" }, 
             { 0, 0 }}; 
     static binding _window_gravity_states[] = { 
             { UnmapGravity, "UnmapGravity" }, 
             { NorthWestGravity, "NorthWestGravity" }, 
             { NorthGravity, "NorthGravity" }, 
             { NorthEastGravity, "NorthEastGravity" }, 
             { WestGravity, "WestGravity" }, 
             { CenterGravity, "CenterGravity" }, 
             { EastGravity, "EastGravity" }, 
             { SouthWestGravity, "SouthWestGravity" }, 
             { SouthGravity, "SouthGravity" }, 
             { SouthEastGravity, "SouthEastGravity" }, 
             { StaticGravity, "StaticGravity" }, 
             { 0, 0 }}; 
     static binding _visual_classes[] = { 
             { StaticGray, "StaticGray" }, 
             { GrayScale, "GrayScale" }, 
             { StaticColor, "StaticColor" }, 
             { PseudoColor, "PseudoColor" }, 
             { TrueColor, "TrueColor" }, 
             { DirectColor, "DirectColor" }, 
             { 0, 0 }}; 
      
     Display_Stats_Info(window) 
          Window window; 
     { 
       XWindowAttributes win_attributes; 
       XVisualInfo vistemplate, *vinfo; 
       XSizeHints hints; 
       int dw = DisplayWidth (dpy, screen), dh = DisplayHeight (dpy, screen\ 
     ); 
       int rx, ry, xright, ybelow; 
       int showright = 0, showbelow = 0; 
       Status status; 
       Window wmframe; 
       int junk; 
       long longjunk; 
       Window junkwin; 
       if (!XGetWindowAttributes(dpy, window, &win_attributes)) 
         Fatal_Error("Can't get window attributes."); 
       vistemplate.visualid = XVisualIDFromVisual(win_attributes.visual); 
       vinfo = XGetVisualInfo(dpy, VisualIDMask, &vistemplate, &junk); 
      
       (void) XTranslateCoordinates (dpy, window, win_attributes.root,  
                                     -win_attributes.border_width, 
                                     -win_attributes.border_width, 
                                     &rx, &ry, &junkwin); 
       xright = (dw - rx - win_attributes.border_width * 2 - 
                 win_attributes.width); 
       ybelow = (dh - ry - win_attributes.border_width * 2 - 
                 win_attributes.height); 
      
       printf("\n"); 
       printf("  Absolute upper-left X:  %s\n", xscale(rx)); 
       printf("  Absolute upper-left Y:  %s\n", yscale(ry)); 
       printf("  Relative upper-left X:  %s\n", xscale(win_attributes.x)); 
       printf("  Relative upper-left Y:  %s\n", yscale(win_attributes.y)); 
       printf("  Width: %s\n", xscale(win_attributes.width)); 
       printf("  Height: %s\n", yscale(win_attributes.height)); 
       printf("  Depth: %d\n", win_attributes.depth); 
       printf("  Visual Class: %s\n", Lookup(vinfo->class, _visual_class\ 
     es)); 
       printf("  Border width: %s\n", bscale(win_attributes.border_width)); 
       printf("  Class: %s\n", 
                Lookup(win_attributes.class, _window_classes)); 
       printf("  Colormap: 0x%lx (%sinstalled)\n",  
              win_attributes.colormap, win_attributes.map_installed ? "" : \ 
     "not "); 
       printf("  Bit Gravity State: %s\n", 
                Lookup(win_attributes.bit_gravity, _bit_gravity_states)); 
       printf("  Window Gravity State: %s\n", 
                Lookup(win_attributes.win_gravity, _window_gravity_states))\ 
     ; 
       printf("  Backing Store State: %s\n", 
                Lookup(win_attributes.backing_store, _backing_store_states)\ 
     ); 
       printf("  Save Under State: %s\n", 
                win_attributes.save_under ? "yes" : "no"); 
       printf("  Map State: %s\n", 
              Lookup(win_attributes.map_state, _map_states)); 
       printf("  Override Redirect State: %s\n", 
                win_attributes.override_redirect ? "yes" : "no"); 
       printf("  Corners:  +%d+%d  -%d+%d  -%d-%d  +%d-%d\n", 
              rx, ry, xright, ry, xright, ybelow, rx, ybelow); 
       /* 
        * compute geometry string that would recreate window 
        */ 
       printf("  -geometry "); 
      
       /* compute size in appropriate units */ 
       status = XGetWMNormalHints(dpy, window, &hints, &longjunk); 
       if (status  &&  hints.flags & PResizeInc  && 
                   hints.width_inc != 0  &&  hints.height_inc != 0) { 
           if (hints.flags & (PBaseSize|PMinSize)) { 
               if (hints.flags & PBaseSize) { 
                   win_attributes.width -= hints.base_width; 
                   win_attributes.height -= hints.base_height; 
               } else { 
                   /* ICCCM says MinSize is default for BaseSize */ 
                   win_attributes.width -= hints.min_width; 
                   win_attributes.height -= hints.min_height; 
               } 
           } 
           printf("%dx%d", win_attributes.width/hints.width_inc, 
                  win_attributes.height/hints.height_inc); 
       } else 
           printf("%dx%d", win_attributes.width, win_attributes.height); 
       if (!(hints.flags&PWinGravity)) 
           hints.win_gravity = NorthWestGravity; /* per ICCCM */ 
       /* find our window manager frame, if any */ 
       wmframe = window; 
       while (True) { 
           Window root, parent; 
           Window *childlist; 
           unsigned int ujunk; 
      
           status = XQueryTree(dpy, wmframe, &root, &parent, &childlist, &u\ 
     junk); 
           if (parent == root || !parent || !status) 
               break; 
           wmframe = parent; 
           if (status && childlist) 
               XFree((char *)childlist); 
       } 
       if (wmframe != window) { 
           /* WM reparented, so find edges of the frame */ 
           /* Only works for ICCCM-compliant WMs, and then only if the 
              window has corner gravity.  We would need to know the origina\ 
     l width 
              of the window to correctly handle the other gravities. */ 
           XWindowAttributes frame_attr; 
           if (!XGetWindowAttributes(dpy, wmframe, &frame_attr)) 
               Fatal_Error("Can't get frame attributes."); 
           switch (hints.win_gravity) { 
             case NorthWestGravity: case SouthWestGravity: 
             case NorthEastGravity: case SouthEastGravity: 
             case WestGravity: 
               rx = frame_attr.x; 
           } 
           switch (hints.win_gravity) { 
             case NorthWestGravity: case SouthWestGravity: 
             case NorthEastGravity: case SouthEastGravity: 
             case EastGravity: 
               xright = dw - frame_attr.x - frame_attr.width - 
                   2*frame_attr.border_width; 
           } 
           switch (hints.win_gravity) { 
             case NorthWestGravity: case SouthWestGravity: 
             case NorthEastGravity: case SouthEastGravity: 
             case NorthGravity: 
               ry = frame_attr.y; 
           } 
           switch (hints.win_gravity) { 
             case NorthWestGravity: case SouthWestGravity: 
             case NorthEastGravity: case SouthEastGravity: 
             case SouthGravity: 
               ybelow = dh - frame_attr.y - frame_attr.height - 
                   2*frame_attr.border_width; 
           } 
       } 
       /* If edge gravity, offer a corner on that edge (because the applica\ 
     tion 
          programmer cares about that edge), otherwise offer upper left unl\ 
     ess 
          some other corner is close to an edge of the screen. 
          (For corner gravity, assume gravity was set by XWMGeometry. 
          For CenterGravity, it doesn't matter.) */ 
       if (hints.win_gravity == EastGravity  || 
           (abs(xright) <= 100  &&  abs(xright) < abs(rx) 
             &&  hints.win_gravity != WestGravity)) 
           showright = 1; 
       if (hints.win_gravity == SouthGravity  || 
           (abs(ybelow) <= 100  &&  abs(ybelow) < abs(ry) 
             &&  hints.win_gravity != NorthGravity)) 
           showbelow = 1; 
        
       if (showright) 
           printf("-%d", xright); 
       else 
           printf("+%d", rx); 
       if (showbelow) 
           printf("-%d", ybelow); 
       else 
           printf("+%d", ry); 
       printf("\n"); 
     } 
      
     /* 
      * Display bits info: 
      */ 
     static binding _gravities[] = { 
             { UnmapGravity, "UnMapGravity" },      /* WARNING: both of the\ 
     se have*/ 
             { ForgetGravity, "ForgetGravity" },    /* the same value - see\ 
      code */ 
             { NorthWestGravity, "NorthWestGravity" }, 
             { NorthGravity, "NorthGravity" }, 
             { NorthEastGravity, "NorthEastGravity" }, 
             { WestGravity, "WestGravity" }, 
             { CenterGravity, "CenterGravity" }, 
             { EastGravity, "EastGravity" }, 
             { SouthWestGravity, "SouthWestGravity" }, 
             { SouthGravity, "SouthGravity" }, 
             { SouthEastGravity, "SouthEastGravity" }, 
             { StaticGravity, "StaticGravity" }, 
             { 0, 0 } }; 
      
     static binding _backing_store_hint[] = { 
             { NotUseful, "NotUseful" }, 
             { WhenMapped, "WhenMapped" }, 
             { Always, "Always" }, 
             { 0, 0 } }; 
      
     static binding _bool[] = { 
             { 0, "No" }, 
             { 1, "Yes" }, 
             { 0, 0 } }; 
     Display_Bits_Info(window) 
          Window window; 
     { 
       XWindowAttributes win_attributes; 
      
       if (!XGetWindowAttributes(dpy, window, &win_attributes)) 
         Fatal_Error("Can't get window attributes."); 
       printf("\n"); 
       printf("  Bit gravity: %s\n", 
              Lookup(win_attributes.bit_gravity, _gravities+1)); 
       printf("  Window gravity: %s\n", 
              Lookup(win_attributes.win_gravity, _gravities)); 
       printf("  Backing-store hint: %s\n", 
              Lookup(win_attributes.backing_store, _backing_store_hint)); 
       printf("  Backing-planes to be preserved: 0x%x\n", 
              win_attributes.backing_planes); 
       printf("  Backing pixel: %d\n", win_attributes.backing_pixel); 
       printf("  Save-unders: %s\n", 
              Lookup(win_attributes.save_under, _bool)); 
     } 
      
     /* 
      * Routine to display all events in an event mask 
      */ 
     static binding _event_mask_names[] = { 
             { KeyPressMask, "KeyPress" }, 
             { KeyReleaseMask, "KeyRelease" }, 
             { ButtonPressMask, "ButtonPress" }, 
             { ButtonReleaseMask, "ButtonRelease" }, 
             { EnterWindowMask, "EnterWindow" }, 
             { LeaveWindowMask, "LeaveWindow" }, 
             { PointerMotionMask, "PointerMotion" }, 
             { PointerMotionHintMask, "PointerMotionHint" }, 
             { Button1MotionMask, "Button1Motion" }, 
             { Button2MotionMask, "Button2Motion" }, 
             { Button3MotionMask, "Button3Motion" }, 
             { Button4MotionMask, "Button4Motion" }, 
             { Button5MotionMask, "Button5Motion" }, 
             { ButtonMotionMask, "ButtonMotion" }, 
             { KeymapStateMask, "KeymapState" }, 
             { ExposureMask, "Exposure" }, 
             { VisibilityChangeMask, "VisibilityChange" }, 
             { StructureNotifyMask, "StructureNotify" }, 
             { ResizeRedirectMask, "ResizeRedirect" }, 
             { SubstructureNotifyMask, "SubstructureNotify" }, 
             { SubstructureRedirectMask, "SubstructureRedirect" }, 
             { FocusChangeMask, "FocusChange" }, 
             { PropertyChangeMask, "PropertyChange" }, 
             { ColormapChangeMask, "ColormapChange" }, 
             { OwnerGrabButtonMask, "OwnerGrabButton" }, 
             { 0, 0 } }; 
     Display_Event_Mask(mask) 
          long mask; 
     { 
       long bit, bit_mask; 
      
       for (bit=0, bit_mask=1; bit<sizeof(long)*8; bit++, bit_mask <&\ 
     lt;= 1) 
         if (mask & bit_mask) 
           printf("      %s\n", 
                  LookupL(bit_mask, _event_mask_names)); 
     } 
      
     /* 
      * Display info on events 
      */ 
     Display_Events_Info(window) 
          Window window; 
     { 
       XWindowAttributes win_attributes; 
       if (!XGetWindowAttributes(dpy, window, &win_attributes)) 
         Fatal_Error("Can't get window attributes."); 
      
       printf("\n"); 
       printf("  Someone wants these events:\n"); 
       Display_Event_Mask(win_attributes.all_event_masks); 
      
       printf("  Do not propagate these events:\n"); 
       Display_Event_Mask(win_attributes.do_not_propagate_mask); 
       printf("  Override redirection?: %s\n", 
              Lookup(win_attributes.override_redirect, _bool)); 
     } 
      
       /* left out visual stuff */ 
       /* left out colormap */ 
       /* left out map_installed */ 
      
     /* 
      * Display root, parent, and (recursively) children information 
      */ 
     Display_Tree_Info(window, recurse) 
          Window window; 
          int recurse;                /* true if should show children's chi\ 
     ldren */ 
     { 
         display_tree_info_1(window, recurse, 0); 
     } 
     display_tree_info_1(window, recurse, level) 
          Window window; 
          int recurse; 
          int level;                        /* recursion level */ 
     { 
       int i, j; 
       int rel_x, rel_y, abs_x, abs_y; 
       unsigned int width, height, border, depth; 
       Window root_win, parent_win; 
       unsigned int num_children; 
       Window *child_list; 
       XClassHint classhint; 
      
       if (!XQueryTree(dpy, window, &root_win, &parent_win, &child_list, 
                       &num_children)) 
         Fatal_Error("Can't query window tree."); 
      
       if (level == 0) { 
         printf("\n"); 
         printf("  Root window id: "); 
         Display_Window_Id(root_win, True); 
         printf("  Parent window id: "); 
         Display_Window_Id(parent_win, True); 
       } 
      
       if (level == 0  ||  num_children > 0) { 
         printf("     "); 
         for (j=0; j<level; j++) printf("   "); 
         printf("%d child%s%s\n", num_children, num_children == 1 ? "" : "r\ 
     en", 
                num_children ? ":" : "."); 
       } 
       for (i = (int)num_children - 1; i >= 0; i--) { 
         printf("     "); 
         for (j=0; j<level; j++) printf("   "); 
         Display_Window_Id(child_list[i], False); 
         printf(": ("); 
         if(XGetClassHint(dpy, child_list[i], &classhint)) { 
             if(classhint.res_name) { 
                 printf("\"%s\" ", classhint.res_name); 
                 XFree(classhint.res_name); 
             } else 
                 printf("(none) "); 
             if(classhint.res_class) { 
                 printf("\"%s\") ", classhint.res_class); 
                 XFree(classhint.res_class); 
             } else 
                 printf("(none)) "); 
         } else 
             printf(") "); 
      
         if (XGetGeometry(dpy, child_list[i], &root_win, 
                          &rel_x, &rel_y, &width, &height, &border, &depth)\ 
     ) { 
             Window child; 
      
             printf (" %ux%u+%d+%d", width, height, rel_x, rel_y); 
             if (XTranslateCoordinates (dpy, child_list[i], root_win, 
                                        0 ,0, &abs_x, &abs_y, &child)) { 
                 printf ("  +%d+%d", abs_x - border, abs_y - border); 
             } 
         } 
         printf("\n"); 
          
         if (recurse) 
             display_tree_info_1(child_list[i], 1, level+1); 
       } 
      
       if (child_list) XFree((char *)child_list); 
     } 
      
     /* 
      * Display a set of size hints 
      */ 
     Display_Hints(hints) 
          XSizeHints *hints; 
     { 
             long flags; 
      
             flags = hints->flags; 
              
             if (flags & USPosition) 
               printf("      User supplied location: %s, %s\n", 
                      xscale(hints->x), yscale(hints->y)); 
      
             if (flags & PPosition) 
               printf("      Program supplied location: %s, %s\n", 
                      xscale(hints->x), yscale(hints->y)); 
      
             if (flags & USSize) { 
               printf("      User supplied size: %s by %s\n", 
                      xscale(hints->width), yscale(hints->height)); 
             } 
             if (flags & PSize) 
               printf("      Program supplied size: %s by %s\n", 
                      xscale(hints->width), yscale(hints->height)); 
             if (flags & PMinSize) 
               printf("      Program supplied minimum size: %s by %s\n", 
                      xscale(hints->min_width), yscale(hints->min_hei\ 
     ght)); 
             if (flags & PMaxSize) 
               printf("      Program supplied maximum size: %s by %s\n", 
                      xscale(hints->max_width), yscale(hints->max_hei\ 
     ght)); 
             if (flags & PBaseSize) { 
               printf("      Program supplied base size: %s by %s\n", 
                      xscale(hints->base_width), yscale(hints->base_h\ 
     eight)); 
             } 
      
             if (flags & PResizeInc) { 
               printf("      Program supplied x resize increment: %s\n", 
                      xscale(hints->width_inc)); 
               printf("      Program supplied y resize increment: %s\n", 
                      yscale(hints->height_inc)); 
               if (hints->width_inc != 0 && hints->height_inc != 0) { 
                   if (flags & USSize) 
                       printf("      User supplied size in resize increment\ 
     s:  %s by %s\n", 
                              (xscale(hints->width / hints->width_inc\ 
     )),  
                              (yscale(hints->height / hints->height_i\ 
     nc))); 
                   if (flags & PSize) 
                       printf("      Program supplied size in resize increm\ 
     ents:  %s by %s\n", 
                              (xscale(hints->width / hints->width_inc\ 
     )),  
                              (yscale(hints->height / hints->height_i\ 
     nc))); 
                   if (flags & PMinSize) 
                       printf("      Program supplied minimum size in resiz\ 
     e increments: %s by %s\n", 
                              xscale(hints->min_width / hints->width_\ 
     inc), yscale(hints->min_height / hints->height_inc)); 
                   if (flags & PBaseSize) 
                       printf("      Program supplied base size in resize i\ 
     ncrements:  %s by %s\n", 
                              (xscale(hints->base_width / hints->widt\ 
     h_inc)),  
                              (yscale(hints->base_height / hints->hei\ 
     ght_inc))); 
               } 
             } 
      
             if (flags & PAspect) { 
               printf("      Program supplied min aspect ratio: %s/%s\n", 
                      xscale(hints->min_aspect.x), yscale(hints->min_\ 
     aspect.y)); 
               printf("      Program supplied max aspect ratio: %s/%s\n", 
                      xscale(hints->max_aspect.x), yscale(hints->max_\ 
     aspect.y)); 
             } 
             if (flags & PWinGravity) { 
               printf("      Program supplied window gravity: %s\n", 
                      Lookup(hints->win_gravity, _gravities)); 
             } 
     } 
      
     /* 
      * Display Size Hints info 
      */ 
     Display_Size_Hints(window) 
          Window window; 
     { 
             XSizeHints *hints = XAllocSizeHints(); 
             long supplied; 
             printf("\n"); 
             if (!XGetWMNormalHints(dpy, window, hints, &supplied)) 
                 printf("  No normal window size hints defined\n"); 
             else { 
                 printf("  Normal window size hints:\n"); 
                 hints->flags &= supplied; 
                 Display_Hints(hints); 
             } 
      
             if (!XGetWMSizeHints(dpy, window, hints, &supplied, XA_WM_ZOOM\ 
     _HINTS)) 
                 printf("  No zoom window size hints defined\n"); 
             else { 
                 printf("  Zoom window size hints:\n"); 
                 hints->flags &= supplied; 
                 Display_Hints(hints); 
             } 
             XFree((char *)hints); 
     } 
      
     Display_Window_Shape (window) 
         Window  window; 
     { 
         Bool    ws, bs; 
         int            xws, yws, xbs, ybs; 
         unsigned int wws, hws, wbs, hbs; 
      
         if (!XShapeQueryExtension (dpy, &bs, &ws)) 
             return; 
         printf("\n"); 
         XShapeQueryExtents (dpy, window, &ws, &xws, &yws, &wws, &hws, 
                                          &bs, &xbs, &ybs, &wbs, &hbs); 
         if (!ws) 
               printf("  No window shape defined\n"); 
         else { 
               printf("  Window shape extents:  %sx%s", 
                      xscale(wws), yscale(hws)); 
               printf("+%s+%s\n", xscale(xws), yscale(yws)); 
         } 
         if (!bs) 
               printf("  No border shape defined\n"); 
         else { 
               printf("  Border shape extents:  %sx%s", 
                      xscale(wbs), yscale(hbs)); 
               printf("+%s+%s\n", xscale(xbs), yscale(ybs)); 
         } 
     } 
      
     /* 
      * Display Window Manager Info 
      */ 
     static binding _state_hints[] = { 
             { DontCareState, "Don't Care State" }, 
             { NormalState, "Normal State" }, 
             { ZoomState, "Zoomed State" }, 
             { IconicState, "Iconic State" }, 
             { InactiveState, "Inactive State" }, 
             { 0, 0 } }; 
     Display_WM_Info(window) 
          Window window; 
     { 
             XWMHints *wmhints; 
             long flags; 
             wmhints = XGetWMHints(dpy, window); 
             printf("\n"); 
             if (!wmhints) { 
                     printf("  No window manager hints defined\n"); 
                     return; 
             } 
             flags = wmhints->flags; 
             printf("  Window manager hints:\n"); 
             if (flags & InputHint) 
               printf("      Client accepts input or input focus: %s\n", 
                      Lookup(wmhints->input, _bool)); 
             if (flags & IconWindowHint) { 
                     printf("      Icon window id: "); 
                     Display_Window_Id(wmhints->icon_window, True); 
             } 
      
             if (flags & IconPositionHint) 
               printf("      Initial icon position: %s, %s\n", 
                      xscale(wmhints->icon_x), yscale(wmhints->icon_y\ 
     )); 
      
             if (flags & StateHint) 
               printf("      Initial state is %s\n", 
                      Lookup(wmhints->initial_state, _state_hints)); 
     } 

    Issue_05_X
    20. xwininfo.pl

    Download xwininfo.pl

     #!/usr/bin/perl  
     # get libraries  
     require "./xbase.pl";  
     require "./xatomhash.pl"; 
     # open the display  
     $xopen = &xlib::x_open_display($ENV{"DISPLAY"});  
     die $xlib::status if not defined $xopen;  
     # map atoms to properties  
     tie %xatom, XATOM, $xopen; 
      
     # print all atoms for window $w on display $d  
     sub printatoms {  
     my ($d, $w) = @_;  
     my @atoms = xlib::x_listproperties($d,$w);  
     for $i (@atoms) {          
     my $n = $xatom{$i};          
     my @x = xlib::x_getproperty($d, 
     $X::defines{"xFalse"}, $w, $i,                          
     $X::defines{"AnyPropertyType"}, 0,255);  
             my $ptn = ($x[2]==0)?"*none*":($xatom{$x[2]});  
             printf "0x%x (%s)[$ptn]<%s>", $i, $n, $x[1];  
     }  
     print "\n";  
     } 
     # query display $d window $w for children;  
     # print info with indentation $n  
     sub query {  
     my ($d,$w,$n)=@_;  
     my @lf = &xlib::x_querytree($d, $w);  
     shift @lf;                         # lose the rep, we just want the ki\ 
     ds 
     my $i;  
     for $i (@lf) {  
             printf("%s%x", " " x $n, $i);  
             printatoms($d,$i);          
     query($d,$i,$n+1);  
     }  
     }  
     # handle the top level directly  
     print "root: "; 
     printatoms($xopen,xlib::defaultroot($xopen));  
     # now recursively handle the children  
     query($xopen,undef,0);  
      
     # we're done.  
     xlib::x_closedisplay($xopen);  

    Issue_05_X
    21. More Samples on X

    • Issue_05_X

                                                                                                                                       

    Hipocrisy of the finest: "I agree that no single company can create all the hardware and software. Openness is central because it's the foundation of choice."
    -- Steve Balmer (Microsoft) blaming Apple regarding iPhone, February 18, 2009

    Last update 1999/02/20

    All Rights Reserved - (C) 1997 - 2009 by The Labs.Com

    Top of Page

    The Labs.Com