~ubuntu-branches/debian/lenny/italc/lenny

« back to all changes in this revision

Viewing changes to ica/x11/libvncserver/selbox.c

  • Committer: Bazaar Package Importer
  • Author(s): Patrick Winnertz
  • Date: 2008-06-17 13:46:54 UTC
  • mfrom: (1.2.1 upstream) (4.1.1 gutsy)
  • Revision ID: james.westby@ubuntu.com-20080617134654-cl0gi4u524cv1ici
Tags: 1:1.0.9~rc3-1
* Package new upstream version
  - upstream ported the code to qt4.4 (Closes: #481974)

Show diffs side-by-side

added added

removed removed

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