home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / x / volume14 / xtoolplaces / part01 / getinfo.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-08-26  |  11.6 KB  |  341 lines

  1. /*Copyright (c) 1991 Xerox Corporation.  All Rights Reserved.
  2.  
  3.   Permission to use,  copy,  modify  and  distribute  without
  4.   charge this software, documentation, images, etc. is grant-
  5.   ed, provided that this copyright and the author's  name  is
  6.   retained.
  7.  
  8.   A fee may be charged for this program ONLY to recover costs
  9.   for distribution (i.e. media costs).  No profit can be made
  10.   on this program.
  11.  
  12.   The author assumes no responsibility for disasters (natural
  13.   or otherwise) as a consequence of use of this software.
  14.  
  15.   Adam Stein (stein.wbst129@xerox.com)
  16. */
  17.  
  18. #include <stdio.h>
  19. #include <ctype.h>
  20. #include <X11/Xlib.h>
  21. #include <X11/Xutil.h>
  22. #include <X11/cursorfont.h>
  23. #include <X11/Xatom.h>
  24.  
  25. int mult_screens,screen_number,display_number;
  26. char hostname[50];
  27. Atom wm_save_yourself,wm_protocols,wm_client_machine;
  28. Display *display;
  29. Window root_window;
  30. extern int console_checking;
  31. extern char *program,*addon,*use_display;
  32. extern FILE *fp;
  33.  
  34. /*This function will initialize the interface to X, lock the pointer and
  35.   change it to a watch, start the recursive procedure of going through
  36.   the window tree list, and then release the pointer and change the cursor
  37.   back to normal when done.
  38.  
  39.   Inputs:  none
  40.   Outputs: none
  41.   Locals:  child             - list of child window IDs
  42.        cursor            - X cursor bitmap
  43.        hostname         - name of host
  44.        loop             - loop through screen number array
  45.        num_child         - number of children under a parent
  46.        parent            - parent window ID of child in the window tree
  47.        root              - top window ID to start in window tree from
  48.        screens         - array of screens to save from
  49.   Globals: display           - interface info to X display
  50.        display_number    - number of the display this will be working under
  51.        mult_screens      - flag indicating if saving more than 1 screen
  52.        program           - name of currently executing program
  53.        root_window       - root window ID
  54.        screen_number     - number of the screen this will be working under
  55.        stderr         - standard error
  56.        use_display       - display to use
  57.        wm_client_machine - WM_CLIENT_MACHINE atom
  58.        wm_protocols      - WM_PROTOCOLS atom
  59.        wm_save_yourself  - WM_SAVE_YOURSELF atom
  60.          CurrentTime         - indicates to execute action immediately
  61.        False             - indicates not to do something
  62.        GrabModeAsync     - indicates to grab device asynchronously
  63.        GrabModeSync      - indicates to grab device synchronously
  64.        None             - indicates no choice for an item
  65.        NULL             - 0
  66.        XC_watch          - indicates the watch bitmap
  67. */
  68. getinfo()
  69. {
  70.     register int *screens,loop;
  71.     int num_child;
  72.     register Cursor cursor;
  73.     Window root,parent,*child;
  74.     int *make_list();
  75.  
  76.     /*Get hostname*/
  77.     if(gethostname(hostname,50)) {
  78.       perror(program);
  79.       exit(1);
  80.     }
  81.  
  82.     /*Open a connection to the X server*/
  83.     if((display = XOpenDisplay(use_display)) == NULL) {
  84.       fprintf(stderr,"%s: can't open display (%s)\n",program,
  85.           XDisplayName(use_display));
  86.       exit(1);
  87.     }
  88.  
  89.     /*Find out what screens to save application states from*/
  90.     display_number = display->ext_number;
  91.     screens = make_list(DefaultScreen(display),ScreenCount(display));
  92.     if(screens[1] != -1) mult_screens = 1;
  93.     else mult_screens = 0;
  94.  
  95.     /*Set up ATOMS to use*/
  96.     wm_save_yourself = XInternAtom(display,"WM_SAVE_YOURSELF",False);
  97.     wm_protocols = XInternAtom(display,"WM_PROTOCOLS",False);
  98.     wm_client_machine = XInternAtom(display,"WM_CLIENT_MACHINE",False);
  99.  
  100.     /*Change cursor to a watch and ring bell once to let user know
  101.       that the server is tied up and the process has begun*/
  102.     root_window = RootWindow(display,DefaultScreen(display));
  103.     cursor = XCreateFontCursor(display,XC_watch);
  104.     XGrabPointer(display,root_window,False,0,GrabModeSync,GrabModeAsync,
  105.              None,cursor,CurrentTime);
  106.     XBell(display,50);
  107.  
  108.     /*Loop through the screens to save from*/
  109.     for(loop = 0;screens[loop] != -1;++loop) {
  110.       /*Get information about root window*/
  111.       screen_number = screens[loop];
  112.       root_window = RootWindow(display,screen_number);
  113.  
  114.       /*Get list of root window's child*/
  115.       if(!XQueryTree(display,root_window,&root,&parent,&child,&num_child)) {
  116.         fprintf(stderr,"%s: couldn't get root window's child (window 0x%lx)\n",program,root_window);
  117.         exit(1);
  118.       }
  119.  
  120.       /*Loop through children windows*/
  121.       for(;num_child;--num_child)
  122.         search(display,child[num_child-1],root_window);
  123.   
  124.       /*Free resources*/
  125.       XFree(child);
  126.     }
  127.  
  128.     /*Change cursor back to normal and ring bell twice to signal that
  129.       the process of saving the desktop is over*/
  130.     XUngrabPointer(display,CurrentTime);
  131.     XBell(display,50);
  132.     XBell(display,50);
  133.     XFlush(display);
  134.  
  135.     /*Close the connection to the X server*/
  136.     XCloseDisplay(display);
  137. }
  138.  
  139. /*This function will recursively search through the window tree.  It will check
  140.   each window to see if it's state should be saved with a WM_SAVE_YOURSELF
  141.   message and if it has a WM_COMMAND property to save.  A window is saved
  142.   if:
  143.     1.  it has WM_NAME set (so we know it's not a pop-up, etc)
  144.     2.  it's a group leader or assume it's ok if group leader isn't set
  145.     3.  it's parent is the root window
  146.     4.  it has a WM_COMMAND property to save or is on a list specified
  147.         with the '-m' option
  148.  
  149.   Inputs:  display            - interface info to X display
  150.        parent_window      - parent window ID of window we are examining
  151.        window             - window we are examining
  152.   Outputs: none
  153.   Locals:  argc              - number of WM_COMMAND arguments
  154.        argv                  - WM_COMMAND arguments
  155.        child              - list of child window IDs
  156.        command_line       - command line arguments in a single string
  157.        console            - indicates if a window is a console
  158.        count              - number of protocols that a window can receive
  159.        event          - event information
  160.        group_leader       - window ID of group leader
  161.        hints              - window hints
  162.        name              - X window name
  163.        num_child          - number of children under a parent
  164.        parent             - parent window ID of child in the window tree
  165.        protocols          - list of protocols that a window can receive
  166.        root               - top window ID to start in window tree from
  167.        save_yourself      - flag indicating if window saved itself or not
  168.        status             - status of get calls
  169.   Globals: addon          - name of file containing commands to add on
  170.        console_checking   - indicates if the check console flag was given
  171.        fp              - file pointer to write window information to
  172.        mult_screens       - flag indicating if saving more than 1 screen
  173.        on_missing_list    - flag indicating if window is a missing app
  174.        program            - name of currently executing program
  175.        screen_number      - number of the screen this will be working under
  176.        stderr          - standard error
  177.        wm_protocols          - WM_PROTOCOLS atom
  178.        wm_save_yourself   - WM_SAVE_YOURSELF atom
  179.        ClientMessage      - event that indicates a message from 1 client
  180.                 to another
  181.        False          - indicates not to do something
  182.        PropertyChangeMask - indicates a window property has changed
  183.        PropertyNotify     - event that indicates a property has changed
  184.        WindowGroupHint    - mask for group hint bit in hint flags
  185. */
  186. search(display,window,parent_window)
  187. register Display *display;
  188. register Window window,parent_window;
  189. {
  190.     register int save_yourself,on_missing_list,console = 0;
  191.     int num_child,count,argc,group_leader = 0;
  192.     register char *command_line,*name;
  193.     char **argv;
  194.     Atom *protocols;
  195.     register Status status;
  196.     Window root,parent,*child;
  197.     XEvent event;
  198.     register XWMHints *hints;
  199.     char *combine(),*get_geometry(),*getname(),*lower();
  200.  
  201.  
  202.     /*If a child had children of it's own, loop thru it's children
  203.       recursively*/
  204.     if(XQueryTree(display,window,&root,&parent,&child,&num_child)) {
  205.       for(;num_child;--num_child)
  206.         search(display,child[num_child-1],parent);
  207.  
  208.       /*Free resources*/
  209.       XFree(child);
  210.     }
  211.  
  212.     /*Don't report window if it doesn't have a name (in which case it's
  213.       probably a pop-up or unmapped child*/
  214.     if(name = getname(window)) XFree(name);
  215.     else return;
  216.  
  217.     /*Don't report window if it's not a group leader or isn't a top
  218.       window*/
  219.     hints = XGetWMHints(display,window);
  220.  
  221.     /*Also check if program didn't set #!$% group leader, in this case
  222.       assume it's ok (I'm sure that's asking for trouble!)*/
  223.     if(hints) {
  224.       if((hints->window_group == window) ||
  225.          !(hints->flags & WindowGroupHint))
  226.         group_leader = 1;
  227.       XFree(hints);
  228.     }
  229.     if(!group_leader || (parent_window != root_window)) return;
  230.  
  231.     /*Determine if window has WM_SAVE_YOURSELF ATOM and send it if
  232.       it does to save it's state*/
  233.     status = XGetWMProtocols(display,window,&protocols,&count);
  234.     if(status && is_save_yourself(protocols,count)) {
  235.       save_yourself = 1;
  236.  
  237.       /*If window does have WM_SAVE_YOURSELF, send it a message to
  238.         save it's state and wait for the PropertyNotify response*/
  239.       event.type = ClientMessage;
  240.       event.xclient.window = window;
  241.       event.xclient.message_type = wm_protocols;
  242.       event.xclient.format = 32;
  243.       event.xclient.data.l[0] = (long) wm_save_yourself;
  244.       XSelectInput(display,window,PropertyChangeMask);
  245.       XSendEvent(display,window,False,0L,&event);
  246.       XNextEvent(display,&event);
  247.       if(event.type == PropertyNotify) {
  248.         if(event.xproperty.window != window) {
  249.           fprintf(stderr,"%s: unexpected PropertyNotify event\n",program);
  250.           exit(1);
  251.         }
  252.       } else {
  253.            fprintf(stderr,"%s: unexpected event\n",program);
  254.            exit(1);
  255.          }
  256.     } else save_yourself = 0;
  257.  
  258.     /*Free resources*/
  259.     XFree(protocols);
  260.  
  261.     /*Determine if window is on missing apps list*/
  262.     on_missing_list = on_list(window);
  263.  
  264.     /*Get WM_COMMAND.  If window doesn't have it set, skip it, otherwise
  265.       write it out*/
  266.     status = XGetCommand(display,window,&argv,&argc);
  267.     if((status && argc && isprint(argv[0][0])) || on_missing_list) {
  268.       /*Put arguments into a single string and free up argv.  Makes it
  269.         easier to check for things*/
  270.       if(status) {
  271.         command_line = combine(argc,argv);
  272.         XFreeStringList(argv);
  273.       } else {
  274.            /*It is ASSUMED that if we have to save a window that
  275.             doesn't have WM_COMMAND set, it's name is WM_NAME in all
  276.             lower case (i.e. xman sets WM_NAME to Xman)*/
  277.            command_line = lower(getname(window));
  278.            save_yourself = 0;
  279.          }
  280.  
  281.       if(!save_yourself) command_line = get_geometry(window,command_line);
  282.  
  283.       /*If console checking flag was given, check each window to see
  284.         if it's a console window*/
  285.       if(console_checking)
  286.         console = is_console(window,command_line);
  287.  
  288.       /*If this window is a console window, write out the special
  289.         'if ... fi' clause*/
  290.       if(console)
  291.         fputs("if [ \"`tty`\" = \"/dev/console\" ]\nthen\n  ",fp);
  292.  
  293.       /*Check to see if window is a remote application*/
  294.       is_remote(window);
  295.  
  296.       /*Fix Xview's long label problem*/
  297.       fix_command(command_line);
  298.  
  299.       /*If saving from more than 1 screen, make sure each application
  300.         has the correct -display option to put it back onto the correct
  301.         screen*/
  302.  
  303.       /*Write out all the arguments in WM_COMMAND*/
  304.       fprintf(fp,"%s ",command_line);
  305.  
  306.       if(mult_screens) adddisplay(command_line,screen_number);
  307.  
  308.       /*If -a option given, search for any addon commands for this window*/
  309.       if(addon) addto(command_line);
  310.  
  311.       /*Write out ampersand to put command into the background*/
  312.       fputs("&\n",fp);
  313.  
  314.       if(console)
  315.         fputs("fi\n",fp);
  316.  
  317.       /*Free resources*/
  318.       free(command_line);
  319.     }
  320. }
  321.  
  322. /*This function will convert all letters in a string to lower case (if not
  323.   already lower case).
  324.  
  325.   Inputs:  string - string to turn all characters to lower case
  326.   Outputs: string - string of all lower case characters
  327.   Locals:  loop   - loop through string
  328.   Globals: none
  329. */
  330. char *lower(string)
  331. register char *string;
  332. {
  333.     register int loop;
  334.  
  335.     for(loop = 0;loop < strlen(string);++loop)
  336.       if(isupper(string[loop])) string[loop] = tolower(string[loop]);
  337.  
  338.     return(string);
  339. }
  340.  
  341.