File: helper.c

package info (click to toggle)
grafix 1.6-5
  • links: PTS
  • area: main
  • in suites: woody
  • size: 1,156 kB
  • ctags: 1,962
  • sloc: ansic: 20,183; makefile: 186; sh: 3
file content (96 lines) | stat: -rw-r--r-- 3,458 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
//  *** new helper feature 1-4/99
// to enable delayed popup (with signals : asynchr) open a new Display connection
// where to show the popups, closing is done from *any* Xevent in "handle_event" !!
// (if asynchronuous popups do not work: set twait = 0;)

// little problem : when pointer moves over helpwin -> LeaveNotify event (of the button) unmaps it
// then EnterNotify maps it again 

class dhelper;
static dhelper *acthlp = 0; // the one and only active helper window

#include <signal.h>
#include <unistd.h>
#include <sys/time.h>

static void schedule(int tw, void (*handler)(int)) { // calls handler after tw microseconds
  signal(SIGALRM,handler); // alarm(tw); works, but 1 sec is too slow ->
  itimerval itv = { { 0, 0 }, {0, tw } } ;
  setitimer(ITIMER_REAL,&itv,0);
}

static void show_help(int);
static void clear_help();

class dhelper { // for dynamic help on EnterCB
  char **text; // to display in popup 
  int w,h,nl,xp,yp; // window size, line nr, position
  Window Win;
  unsigned twait; // time to wait for map (in microseconds)
  Display *hdisplay;
public:
  dhelper(char** text, Display *hdisplay) : text(text), hdisplay(hdisplay) { 
    int cl;   
    compute_text_size(text,cl,nl);
    w = cl*6 + 10; h = nl*14 + 6;
    Win = 0;
    if (hdisplay) twait = 200000; // 0.2 sec delay (only if we have new display variable)
    else { hdisplay = display; twait = 0; } 
  }  
  void popup(int x, int y)  { // prepare for popup : after twait sec delay
    xp = x; yp = y;
    clear_help();
    acthlp = this; // fprintf(stderr,"<");
    if (twait > 0) schedule(twait,show_help);
    else map(); // undelayed display
  }
  void map() {                // if called from alarm_popup = asynchron !!
    unsigned backgr = 0xfff8; // light yellow
    Win = XCreateSimpleWindow(hdisplay, DefaultRootWindow(hdisplay),xp,yp,w,h,1, black, backgr); 
    XSetWindowAttributes attr; 
    attr.override_redirect = TRUE; // not handled by window manager
    attr.save_under = TRUE;
    XChangeWindowAttributes(hdisplay, Win, CWOverrideRedirect | CWSaveUnder, &attr); 
    XMapWindow(hdisplay, Win);
    static XGCValues gcv = { GXcopy, 0, black };  
    static GC gc = XCreateGC(hdisplay, DefaultRootWindow(hdisplay),GCFunction | GCForeground, &gcv); 
    for (int l = 0, y = 0; l < nl; l++) {
      char *tt = text[l]; y += 14; 
      XDrawString(hdisplay, Win, gc, 5, y, tt, strlen(tt));
    }
    XFlush(hdisplay);

  }
  void close() { 
    if (Win) { XDestroyWindow(hdisplay,Win); Win = 0; XFlush(hdisplay); }
    acthlp = 0; // fprintf(stderr,">");
  }
};

void clear_help() { if (acthlp) acthlp->close(); } // active helper !!
void show_help(int) { if (acthlp) acthlp->map(); } // asynch. from alarm !! 

void window::add_help(char* help[]) {
  static Display *hdisplay = XOpenDisplay("");
  dhlp = new dhelper(help,hdisplay);
  selection_mask |= EnterWindowMask | LeaveWindowMask;
  XSelectInput(display, Win, selection_mask);
}

void window::add_help(char* arg0, ...) {
  va_list args; va_start(args,arg0); 
  char *cp[50];
  int nl = 1; cp[0] = arg0;
  while ((cp[nl++] = va_arg(args,char*)) != NULL) if (nl == 50) break;
  cp[nl-1] = 0;
  //  for (int i=0; i<nl; i++) printf("%s\n",cp[i]);
  char **help = new char*[nl];
  for (int i=0; i<nl; i++) help[i] = cp[i];
  add_help(help);
  va_end(args);
}

void window::Enter_CB(XCrossingEvent ev) { // clearing is done in handle_event
  if (dhlp) dhlp->popup(ev.x_root + 10, ev.y_root + 5);
}