home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 1999 mARCH / PCWK3A99.iso / Linux / DDD331 / DDD-3_1_.000 / DDD-3_1_ / ddd-3.1.1 / ddd / Delay.C < prev    next >
C/C++ Source or Header  |  1998-04-06  |  8KB  |  309 lines

  1. // $Id: Delay.C,v 1.24 1998/04/06 12:45:02 zeller Exp $  -*- C++ -*-
  2. // Delay class -- displays an hourglass cursor until destroyed
  3.  
  4. // Copyright (C) 1995 Technische Universitaet Braunschweig, Germany.
  5. // Written by Andreas Zeller <zeller@ips.cs.tu-bs.de>.
  6. // 
  7. // This file is part of DDD.
  8. // 
  9. // DDD is free software; you can redistribute it and/or
  10. // modify it under the terms of the GNU General Public
  11. // License as published by the Free Software Foundation; either
  12. // version 2 of the License, or (at your option) any later version.
  13. // 
  14. // DDD is distributed in the hope that it will be useful,
  15. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  17. // See the GNU General Public License for more details.
  18. // 
  19. // You should have received a copy of the GNU General Public
  20. // License along with DDD -- see the file COPYING.
  21. // If not, write to the Free Software Foundation, Inc.,
  22. // 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  23. // 
  24. // DDD is the data display debugger.
  25. // For details, see the DDD World-Wide-Web page, 
  26. // `http://www.cs.tu-bs.de/softech/ddd/',
  27. // or send a mail to the DDD developers <ddd@ips.cs.tu-bs.de>.
  28.  
  29. char Delay_rcsid[] = 
  30.     "$Id: Delay.C,v 1.24 1998/04/06 12:45:02 zeller Exp $";
  31.  
  32. #ifdef __GNUG__
  33. #pragma implementation
  34. #pragma implementation "DynArray.h"
  35. #pragma implementation "VarArray.h"
  36. #endif
  37.  
  38. #define LOG_DELAY 0
  39.  
  40. #include "Delay.h"
  41. #include "assert.h"
  42. #include "longName.h"
  43. #include "HelpCB.h"
  44. #include <X11/cursorfont.h>
  45. #include <X11/StringDefs.h>
  46.  
  47. // ANSI C++ doesn't like the XtIsRealized() macro
  48. #ifdef XtIsRealized
  49. #undef XtIsRealized
  50. #endif
  51.  
  52. DEFINE_TYPE_INFO_0(_Delay);
  53. DEFINE_TYPE_INFO_0(Delay);
  54.  
  55. #define SMALL_HOURGLASS_CURSOR 1
  56.  
  57. #if SMALL_HOURGLASS_CURSOR || LARGE_HOURGLASS_CURSOR
  58. #include "icons/cursors/time16.xbm"
  59. #include "icons/cursors/time16m.xbm"
  60. #if time16_width != time16m_width || time16_height != time16m_height
  61. #error Bad mask for time16
  62. #endif
  63. #endif
  64.  
  65. #if LARGE_HOURGLASS_CURSOR
  66. #include "icons/cursors/time32.xbm"
  67. #include "icons/cursors/time32m.xbm"
  68. #if time32_width != time32m_width || time32_height != time32m_height
  69. #error Bad mask for time32
  70. #endif
  71. #endif
  72.  
  73. void (*Delay::shell_registered)(Widget w) = 0;
  74.  
  75. Cursor _Delay::hourglass_cache = 0;
  76. Cursor _Delay::current_cursor = 0;
  77.  
  78. Cursor _Delay::hourglass_cursor()
  79. {
  80.     if (hourglass_cache != 0)
  81.     return hourglass_cache;
  82.  
  83.     Display *display = XtDisplay(widget);
  84.  
  85. #if SMALL_HOURGLASS_CURSOR || LARGE_HORGLASS_CURSOR
  86.     Screen *screen = XtScreen(widget);
  87.     Window rootWindow = RootWindowOfScreen(screen);
  88.  
  89.     unsigned char *cursor_bits      = time16_bits;
  90.     unsigned char *cursor_mask_bits = time16m_bits;
  91.     unsigned int cursor_width       = time16_width;
  92.     unsigned int cursor_height      = time16_height;
  93.     unsigned int cursor_x_hot       = time16_x_hot;
  94.     unsigned int cursor_y_hot       = time16_y_hot;
  95.  
  96. #if LARGE_HOURGLASS_CURSOR
  97.     // Fetch cursor shape
  98.     unsigned int width, height;
  99.     XQueryBestCursor(display, rootWindow, 32, 32, &width, &height);
  100.     Boolean largeCursors = (width >= 32 && height >= 32);
  101.     if (largeCursors)
  102.     {
  103.     cursor_bits      = time32_bits;
  104.     cursor_mask_bits = time32m_bits;
  105.     cursor_width     = time32_width;
  106.     cursor_height    = time32_height;
  107.     cursor_x_hot     = time32_x_hot;
  108.     cursor_y_hot     = time32_y_hot;
  109.     }
  110. #endif
  111.  
  112.     Pixmap cursor_pixmap = 
  113.     XCreateBitmapFromData(display, rootWindow, (char *)cursor_bits,
  114.                   cursor_width, cursor_height);
  115.     Pixmap cursor_mask_pixmap = 
  116.     XCreateBitmapFromData(display, rootWindow, (char *)cursor_mask_bits,
  117.                   cursor_width, cursor_height);
  118.     
  119.     XColor cursor_colors[2];
  120.     cursor_colors[0].pixel = BlackPixelOfScreen(screen);
  121.     cursor_colors[1].pixel = WhitePixelOfScreen(screen);
  122.  
  123.     XQueryColors(display, DefaultColormapOfScreen(screen), 
  124.          cursor_colors, 2);
  125.  
  126.     hourglass_cache = 
  127.     XCreatePixmapCursor(display, cursor_pixmap, cursor_mask_pixmap,
  128.                 cursor_colors, cursor_colors + 1, 
  129.                 cursor_x_hot, cursor_y_hot);
  130. #else // Watch cursor
  131.     hourglass_cache = 
  132.     XCreateFontCursor(display, XC_watch);
  133. #endif
  134.  
  135.     return hourglass_cache;
  136. }
  137.  
  138. _Delay::_Delay(Widget w):
  139.     widget(w), old_cursor(0)
  140. {
  141.     if (widget == 0)
  142.     return;
  143.  
  144. #if LOG_DELAY
  145.     clog << "Setting " << XtName(widget) << " delay cursor\n";
  146. #endif
  147.  
  148.     Display *display = XtDisplay(widget);
  149.  
  150.     if (current_cursor == 0)
  151.     {
  152.     // XC_left_ptr is the default cursor in OSF/Motif.
  153.     // (How do we determine the current cursor? - FIXME)
  154.     current_cursor = XCreateFontCursor(display, XC_left_ptr);
  155.     }
  156.  
  157.     old_cursor = current_cursor;
  158.  
  159.     if (XtIsRealized(widget))
  160.     {
  161.     XDefineCursor(display, XtWindow(widget), hourglass_cursor());
  162.     XFlush(display);
  163.     }
  164.  
  165.     XtAddCallback(widget, XtNdestroyCallback, _Delay::DestroyCB, this);
  166. }
  167.  
  168. _Delay::~_Delay()
  169. {
  170.     if (widget == 0 || old_cursor == 0)
  171.     return;
  172.  
  173. #if LOG_DELAY
  174.     clog << "Removing " << XtName(widget) << " delay cursor\n";
  175. #endif
  176.  
  177.     if (XtIsRealized(widget))
  178.     {
  179.     XDefineCursor(XtDisplay(widget), XtWindow(widget), old_cursor);
  180.     XFlush(XtDisplay(widget));
  181.     }
  182.  
  183.     current_cursor = old_cursor;
  184.     XtRemoveCallback(widget, XtNdestroyCallback, _Delay::DestroyCB, this);
  185. }
  186.  
  187. // Make sure we do not attempt to delete a delay on a destroyed widget
  188. void _Delay::DestroyCB(Widget, XtPointer client_data, XtPointer)
  189. {
  190.     _Delay *delay = (_Delay *)client_data;
  191.     assert(ptr_cast(_Delay, delay));
  192.  
  193.     delay->widget     = 0;
  194.     delay->old_cursor = 0;
  195. }
  196.  
  197.  
  198. int Delay::delay_count = 0;
  199. WidgetArray Delay::_shells;
  200. DelayArray Delay::delays;
  201.  
  202. Delay::Delay(Widget w):
  203.     _Delay(w)
  204. {
  205.     assert(delays.size() == _shells.size());
  206.  
  207.     if (delay_count++ == 0)
  208.     {
  209.     for (int i = 0; i < delays.size(); i++)
  210.     {
  211.         assert(delays[i] == 0);
  212.         if (_shells[i])
  213.         {
  214. #if LOG_DELAY
  215.         clog << "Slot " << i << ": ";
  216. #endif
  217.         delays[i] = new _Delay(_shells[i]);
  218.         }
  219.     }
  220.     }
  221. }
  222.  
  223. // Make sure the shell is unregistered when destroyed
  224. void Delay::DestroyCB(Widget widget, XtPointer, XtPointer)
  225. {
  226.     assert(delays.size() == _shells.size());
  227.  
  228.     // Unregister shell
  229.     for (int i = 0; i < _shells.size(); i++)
  230.     if (_shells[i] == widget)
  231.     {
  232.         _shells[i] = 0;
  233.         if (delays[i])
  234.         {
  235.         delete delays[i];
  236.         delays[i] = 0;
  237.         }
  238. #if LOG_DELAY
  239.         clog << "Unregistering " << XtName(widget) 
  240.          << " in slot " << i << "\n";
  241. #endif
  242.     }
  243. }
  244.  
  245. void Delay::register_shell(Widget widget)
  246. {
  247.     assert(delays.size() == _shells.size());
  248.  
  249.     // Check if the shell is already registered
  250.     int i;
  251.     for (i = 0; i < _shells.size(); i++)
  252.     if (_shells[i] == widget)
  253.         return;
  254.  
  255.     // Look for an empty slot
  256.     for (i = 0; i < _shells.size() && _shells[i] != 0; i++)
  257.     ;
  258.  
  259.     XtAddCallback(widget, XtNdestroyCallback, DestroyCB, XtPointer(0));
  260.  
  261.     _Delay *new_delay = 0;
  262.     if (delay_count)
  263.     new_delay = new _Delay(widget);
  264.  
  265.     if (i == _shells.size())
  266.     {
  267.     _shells += Widget(0);
  268.     delays  += (_Delay *)0;
  269.     }
  270.  
  271.     assert(_shells[i] == 0);
  272.     assert(delays[i] == 0);
  273.     
  274.     _shells[i] = widget;
  275.     delays[i]  = new_delay;
  276.  
  277. #if LOG_DELAY
  278.     clog << "Registering " << XtName(widget) << " in slot " << i << "\n";
  279. #endif
  280.  
  281.     if (shell_registered != 0)
  282.     shell_registered(widget);
  283.  
  284.     assert(delays.size() == _shells.size());
  285. }
  286.  
  287. Delay::~Delay()
  288. {
  289.     assert(delays.size() == _shells.size());
  290.  
  291.     if (--delay_count == 0)
  292.     {
  293.     for (int i = 0; i < delays.size(); i++)
  294.     {
  295.         if (delays[i])
  296.         {
  297. #if LOG_DELAY
  298.         clog << "Slot " << i << ": ";
  299. #endif
  300.         delete delays[i];
  301.         delays[i] = 0;
  302.         }
  303.     }
  304.     }
  305. }
  306.  
  307.  
  308. // bullmann@fzi.de (Joerg Bullmann) says a dummy comment is required here...
  309.