1a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#include <ctype.h>
2a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#include <rfb/rfb.h>
3a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#include <rfb/keysym.h>
4a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
5a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehattypedef struct {
6a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  rfbScreenInfoPtr screen;
7a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  rfbFontDataPtr font;
8a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  char** list;
9a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  int listSize;
10a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  int selected;
11a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  int displayStart;
12a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  int x1,y1,x2,y2,textH,pageH;
13a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  int xhot,yhot;
14a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  int buttonWidth,okBX,cancelBX,okX,cancelX,okY;
15a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  rfbBool okInverted,cancelInverted;
16a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  int lastButtons;
17a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  rfbPixel colour,backColour;
18a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  SelectionChangedHookPtr selChangedHook;
19a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  enum { SELECTING, OK, CANCEL } state;
20a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat} rfbSelectData;
21a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
22a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatstatic const char* okStr="OK";
23a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatstatic const char* cancelStr="Cancel";
24a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
25a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatstatic void selPaintButtons(rfbSelectData* m,rfbBool invertOk,rfbBool invertCancel)
26a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat{
27a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  rfbScreenInfoPtr s = m->screen;
28a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  rfbPixel bcolour = m->backColour;
29a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  rfbPixel colour = m->colour;
30a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
31a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  rfbFillRect(s,m->x1,m->okY-m->textH,m->x2,m->okY,bcolour);
32a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
33a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  if(invertOk) {
34a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbFillRect(s,m->okBX,m->okY-m->textH,m->okBX+m->buttonWidth,m->okY,colour);
35a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbDrawStringWithClip(s,m->font,m->okX+m->xhot,m->okY-1+m->yhot,okStr,
36a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			  m->x1,m->okY-m->textH,m->x2,m->okY,
37a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			  bcolour,colour);
38a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  } else
39a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbDrawString(s,m->font,m->okX+m->xhot,m->okY-1+m->yhot,okStr,colour);
40a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
41a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  if(invertCancel) {
42a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbFillRect(s,m->cancelBX,m->okY-m->textH,
43a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	     m->cancelBX+m->buttonWidth,m->okY,colour);
44a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbDrawStringWithClip(s,m->font,m->cancelX+m->xhot,m->okY-1+m->yhot,
45a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			  cancelStr,m->x1,m->okY-m->textH,m->x2,m->okY,
46a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			  bcolour,colour);
47a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  } else
48a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbDrawString(s,m->font,m->cancelX+m->xhot,m->okY-1+m->yhot,cancelStr,colour);
49a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
50a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  m->okInverted = invertOk;
51a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  m->cancelInverted = invertCancel;
52a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat}
53a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
54a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat/* line is relative to displayStart */
55a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatstatic void selPaintLine(rfbSelectData* m,int line,rfbBool invert)
56a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat{
57a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  int y1 = m->y1+line*m->textH, y2 = y1+m->textH;
58a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  if(y2>m->y2)
59a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    y2=m->y2;
60a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  rfbFillRect(m->screen,m->x1,y1,m->x2,y2,invert?m->colour:m->backColour);
61a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  if(m->displayStart+line<m->listSize)
62a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    rfbDrawStringWithClip(m->screen,m->font,m->x1+m->xhot,y2-1+m->yhot,
63a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			  m->list[m->displayStart+line],
64a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			  m->x1,y1,m->x2,y2,
65a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			  invert?m->backColour:m->colour,
66a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat			  invert?m->backColour:m->colour);
67a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat}
68a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
69a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatstatic void selSelect(rfbSelectData* m,int _index)
70a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat{
71a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  int delta;
72a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
73a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  if(_index==m->selected || _index<0 || _index>=m->listSize)
74a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    return;
75a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
76a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  if(m->selected>=0)
77a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    selPaintLine(m,m->selected-m->displayStart,FALSE);
78a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
79a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  if(_index<m->displayStart || _index>=m->displayStart+m->pageH) {
80a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    /* targetLine is the screen line in which the selected line will
81a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat       be displayed.
82a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat       targetLine = m->pageH/2 doesn't look so nice */
83a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    int targetLine = m->selected-m->displayStart;
84a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    int lineStart,lineEnd;
85a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
86a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    /* scroll */
87a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    if(_index<targetLine)
88a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      targetLine = _index;
89a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    else if(_index+m->pageH-targetLine>=m->listSize)
90a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      targetLine = _index+m->pageH-m->listSize;
91a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    delta = _index-(m->displayStart+targetLine);
92a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
93a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    if(delta>-m->pageH && delta<m->pageH) {
94a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      if(delta>0) {
95a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	lineStart = m->pageH-delta;
96a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	lineEnd = m->pageH;
97a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	rfbDoCopyRect(m->screen,m->x1,m->y1,m->x2,m->y1+lineStart*m->textH,
98a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		      0,-delta*m->textH);
99a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      } else {
100a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	lineStart = 0;
101a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	lineEnd = -delta;
102a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	rfbDoCopyRect(m->screen,
103a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		      m->x1,m->y1+lineEnd*m->textH,m->x2,m->y2,
104a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		      0,-delta*m->textH);
105a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      }
106a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    } else {
107a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      lineStart = 0;
108a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      lineEnd = m->pageH;
109a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    }
110a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    m->displayStart += delta;
111a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    for(delta=lineStart;delta<lineEnd;delta++)
112a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      if(delta!=_index)
113a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	selPaintLine(m,delta,FALSE);
114a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  }
115a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
116a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  m->selected = _index;
117a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  selPaintLine(m,m->selected-m->displayStart,TRUE);
118a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
119a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  if(m->selChangedHook)
120a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    m->selChangedHook(_index);
121a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
122a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  /* todo: scrollbars */
123a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat}
124a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
125a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatstatic void selKbdAddEvent(rfbBool down,rfbKeySym keySym,rfbClientPtr cl)
126a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat{
127a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  if(down) {
128a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    if(keySym>' ' && keySym<0xff) {
129a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      int i;
130a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      rfbSelectData* m = (rfbSelectData*)cl->screen->screenData;
131a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      char c = tolower(keySym);
132a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
133a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      for(i=m->selected+1;m->list[i] && tolower(m->list[i][0])!=c;i++);
134a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      if(!m->list[i])
135a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	for(i=0;i<m->selected && tolower(m->list[i][0])!=c;i++);
136a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      selSelect(m,i);
137a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    } else if(keySym==XK_Escape) {
138a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      rfbSelectData* m = (rfbSelectData*)cl->screen->screenData;
139a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      m->state = CANCEL;
140a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    } else if(keySym==XK_Return) {
141a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      rfbSelectData* m = (rfbSelectData*)cl->screen->screenData;
142a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      m->state = OK;
143a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    } else {
144a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      rfbSelectData* m = (rfbSelectData*)cl->screen->screenData;
145a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      int curSel=m->selected;
146a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      if(keySym==XK_Up) {
147a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if(curSel>0)
148a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	  selSelect(m,curSel-1);
149a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      } else if(keySym==XK_Down) {
150a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if(curSel+1<m->listSize)
151a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	  selSelect(m,curSel+1);
152a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      } else {
153a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	if(keySym==XK_Page_Down) {
154a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	  if(curSel+m->pageH<m->listSize)
155a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    selSelect(m,curSel+m->pageH);
156a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	  else
157a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    selSelect(m,m->listSize-1);
158a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	} else if(keySym==XK_Page_Up) {
159a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	  if(curSel-m->pageH>=0)
160a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    selSelect(m,curSel-m->pageH);
161a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	  else
162a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    selSelect(m,0);
163a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	}
164a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      }
165a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    }
166a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  }
167a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat}
168a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
169a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatstatic void selPtrAddEvent(int buttonMask,int x,int y,rfbClientPtr cl)
170a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat{
171a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  rfbSelectData* m = (rfbSelectData*)cl->screen->screenData;
172a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  if(y<m->okY && y>=m->okY-m->textH) {
173a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    if(x>=m->okBX && x<m->okBX+m->buttonWidth) {
174a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      if(!m->okInverted)
175a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	selPaintButtons(m,TRUE,FALSE);
176a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      if(buttonMask)
177a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	m->state = OK;
178a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    } else if(x>=m->cancelBX && x<m->cancelBX+m->buttonWidth) {
179a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      if(!m->cancelInverted)
180a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	selPaintButtons(m,FALSE,TRUE);
181a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      if(buttonMask)
182a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	m->state = CANCEL;
183a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    } else if(m->okInverted || m->cancelInverted)
184a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      selPaintButtons(m,FALSE,FALSE);
185a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  } else {
186a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    if(m->okInverted || m->cancelInverted)
187a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      selPaintButtons(m,FALSE,FALSE);
188a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    if(!m->lastButtons && buttonMask) {
189a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      if(x>=m->x1 && x<m->x2 && y>=m->y1 && y<m->y2)
190a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	selSelect(m,m->displayStart+(y-m->y1)/m->textH);
191a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    }
192a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  }
193a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  m->lastButtons = buttonMask;
194a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
195a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  /* todo: scrollbars */
196a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat}
197a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
198a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatstatic rfbCursorPtr selGetCursorPtr(rfbClientPtr cl)
199a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat{
200a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  return NULL;
201a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat}
202a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
203a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatint rfbSelectBox(rfbScreenInfoPtr rfbScreen,rfbFontDataPtr font,
204a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		 char** list,
205a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		 int x1,int y1,int x2,int y2,
206a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		 rfbPixel colour,rfbPixel backColour,
207a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		 int border,SelectionChangedHookPtr selChangedHook)
208a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat{
209a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat   int bpp = rfbScreen->bitsPerPixel/8;
210a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat   char* frameBufferBackup;
211a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat   void* screenDataBackup = rfbScreen->screenData;
212a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat   rfbKbdAddEventProcPtr kbdAddEventBackup = rfbScreen->kbdAddEvent;
213a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat   rfbPtrAddEventProcPtr ptrAddEventBackup = rfbScreen->ptrAddEvent;
214a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat   rfbGetCursorProcPtr getCursorPtrBackup = rfbScreen->getCursorPtr;
215a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat   rfbDisplayHookPtr displayHookBackup = rfbScreen->displayHook;
216a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat   rfbSelectData selData;
217a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat   int i,j,k;
218a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat   int fx1,fy1,fx2,fy2; /* for font bbox */
219a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
220a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat   if(list==0 || *list==0)
221a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat     return(-1);
222a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
223a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat   rfbWholeFontBBox(font, &fx1, &fy1, &fx2, &fy2);
224a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat   selData.textH = fy2-fy1;
225a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat   /* I need at least one line for the choice and one for the buttons */
226a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat   if(y2-y1<selData.textH*2+3*border)
227a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat     return(-1);
228a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat   selData.xhot = -fx1;
229a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat   selData.yhot = -fy2;
230a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat   selData.x1 = x1+border;
231a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat   selData.y1 = y1+border;
232a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat   selData.y2 = y2-selData.textH-3*border;
233a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat   selData.x2 = x2-2*border;
234a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat   selData.pageH = (selData.y2-selData.y1)/selData.textH;
235a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
236a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat   i = rfbWidthOfString(font,okStr);
237a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat   j = rfbWidthOfString(font,cancelStr);
2381d80c6a8d34f59543f7df1963c22d7efa292bcb0Greg Hartman   selData.buttonWidth= k = 4*border+(i<j?j:i);
239a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat   selData.okBX = x1+(x2-x1-2*k)/3;
240a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat   if(selData.okBX<x1+border) /* too narrow! */
241a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat     return(-1);
242a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat   selData.cancelBX = x1+k+(x2-x1-2*k)*2/3;
243a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat   selData.okX = selData.okBX+(k-i)/2;
244a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat   selData.cancelX = selData.cancelBX+(k-j)/2;
245a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat   selData.okY = y2-border;
246a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
247a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat   frameBufferBackup = (char*)malloc(bpp*(x2-x1)*(y2-y1));
248a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
249a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat   selData.state = SELECTING;
250a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat   selData.screen = rfbScreen;
251a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat   selData.font = font;
252a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat   selData.list = list;
253a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat   selData.colour = colour;
254a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat   selData.backColour = backColour;
255a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat   for(i=0;list[i];i++);
256a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat   selData.selected = i;
257a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat   selData.listSize = i;
258a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat   selData.displayStart = i;
259a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat   selData.lastButtons = 0;
260a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat   selData.selChangedHook = selChangedHook;
261a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
262a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat   rfbScreen->screenData = &selData;
263a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat   rfbScreen->kbdAddEvent = selKbdAddEvent;
264a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat   rfbScreen->ptrAddEvent = selPtrAddEvent;
265a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat   rfbScreen->getCursorPtr = selGetCursorPtr;
266a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat   rfbScreen->displayHook = NULL;
267a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
268a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat   /* backup screen */
269a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat   for(j=0;j<y2-y1;j++)
270a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat     memcpy(frameBufferBackup+j*(x2-x1)*bpp,
271a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    rfbScreen->frameBuffer+j*rfbScreen->paddedWidthInBytes+x1*bpp,
272a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    (x2-x1)*bpp);
273a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
274a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat   /* paint list and buttons */
275a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat   rfbFillRect(rfbScreen,x1,y1,x2,y2,colour);
276a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat   selPaintButtons(&selData,FALSE,FALSE);
277a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat   selSelect(&selData,0);
278a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
279a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat   /* modal loop */
280a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat   while(selData.state == SELECTING)
281a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat     rfbProcessEvents(rfbScreen,20000);
282a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
283a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat   /* copy back screen data */
284a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat   for(j=0;j<y2-y1;j++)
285a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat     memcpy(rfbScreen->frameBuffer+j*rfbScreen->paddedWidthInBytes+x1*bpp,
286a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    frameBufferBackup+j*(x2-x1)*bpp,
287a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	    (x2-x1)*bpp);
288a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat   free(frameBufferBackup);
289a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat   rfbMarkRectAsModified(rfbScreen,x1,y1,x2,y2);
290a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat   rfbScreen->screenData = screenDataBackup;
291a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat   rfbScreen->kbdAddEvent = kbdAddEventBackup;
292a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat   rfbScreen->ptrAddEvent = ptrAddEventBackup;
293a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat   rfbScreen->getCursorPtr = getCursorPtrBackup;
294a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat   rfbScreen->displayHook = displayHookBackup;
295a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
296a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat   if(selData.state==CANCEL)
297a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat     selData.selected=-1;
298a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat   return(selData.selected);
299a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat}
300a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
301