marquee.c 8.38 KB
Newer Older
1
#define NCURSES_NOMACROS
2 3 4 5
#include <cdk_int.h>

/*
 * $Author: tom $
6 7
 * $Date: 2016/11/20 19:14:46 $
 * $Revision: 1.82 $
8 9
 */

10
DeclareCDKObjects (MARQUEE, Marquee, setCdk, Unknown);
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
static void discardWin (WINDOW **winp)
{
   if (*winp != 0)
   {
      werase (*winp);
      wrefresh (*winp);
      delwin (*winp);
      *winp = 0;
   }
}

static void layoutWidget (CDKMARQUEE *widget,
			  int xpos,
			  int ypos)
{
   /* *INDENT-EQLS* */
   CDKSCREEN *cdkscreen = ScreenOf (widget);
   int parentWidth      = getmaxx (cdkscreen->window);
   WINDOW *window;
   int boxHeight;
   int boxWidth;

   discardWin (&(widget->win));
   discardWin (&(widget->shadowWin));

   boxWidth = setWidgetDimension (parentWidth, widget->width, 0);
   boxHeight = (BorderOf (widget) * 2) + 1;

   /* Rejustify the x and y positions if we need to. */
   alignxy (cdkscreen->window, &xpos, &ypos, boxWidth, boxHeight);
   window = newwin (boxHeight, boxWidth, ypos, xpos);

   if (window != 0)
   {
      /* *INDENT-EQLS* */
      widget->win          = window;
      widget->boxHeight    = boxHeight;
      widget->boxWidth     = boxWidth;

      keypad (widget->win, TRUE);

      /* Do we want a shadow? */
      if (widget->shadow)
      {
	 widget->shadowWin = subwin (cdkscreen->window,
				     boxHeight, boxWidth,
				     ypos + 1, xpos + 1);
      }
   }
}

63 64 65
/*
 * This creates a marquee widget.
 */
66
CDKMARQUEE *newCDKMarquee (CDKSCREEN *cdkscreen,
67 68
			   int xpos,
			   int ypos,
69 70 71
			   int width,
			   boolean Box,
			   boolean shadow)
72
{
73 74
   /* *INDENT-EQLS* */
   CDKMARQUEE *widget   = 0;
75

76 77
   if ((widget = newCDKObject (CDKMARQUEE, &my_funcs)) == 0)
        return (0);
78

79 80 81 82 83 84 85
   /* *INDENT-EQLS* Create the widget pointer. */
   ScreenOf (widget)    = cdkscreen;
   widget->parent       = cdkscreen->window;
   widget->win          = newwin (1, 1, ypos, xpos);
   widget->active       = TRUE;
   widget->width        = width;
   widget->shadow       = shadow;
86

87
   setCDKMarqueeBox (widget, Box);
88 89

   /* Is the window null??? */
90
   if (widget->win == 0)
91
   {
92
      destroyCDKObject (widget);
93 94 95
      return (0);
   }

96
   registerCDKObject (cdkscreen, vMARQUEE, widget);
97

98
   return (widget);
99 100 101
}

/*
102
 * This activates the widget.
103
 */
104
int activateCDKMarquee (CDKMARQUEE *widget,
105
			const char *mesg,
106 107 108
			int delay,
			int repeat,
			boolean Box)
109
{
110 111 112 113 114 115 116
   /* *INDENT-EQLS* */
   int mesgLength       = 0;
   int startPos         = 0;
   int firstChar        = 0;
   int lastChar         = 1;
   int repeatCount      = 0;
   int viewSize         = 0;
117 118
   int viewLimit;
   int padding;
119
   chtype *message;
120
   int x, junk, oldcurs;
121
   bool firstTime       = TRUE;
122 123 124 125 126 127 128

   /* Make sure the message has some content. */
   if (mesg == 0 || *mesg == '\0')
   {
      return (-1);
   }

129 130
   /* Keep the box info, setting BorderOf () */
   setCDKMarqueeBox (widget, Box);
131

132
   padding = (mesg[strlen (mesg) - 1] == ' ') ? 0 : 1;
133 134 135 136

   /* Translate the char * to a chtype * */
   message = char2Chtype (mesg, &mesgLength, &junk);

137 138 139
   /* Draw in the widget. */
   drawCDKMarquee (widget, ObjOf (widget)->box);
   viewLimit = widget->width - (2 * BorderOf (widget));
140 141

   /* Start doing the marquee thing... */
142 143
   oldcurs = curs_set (0);
   while (widget->active)
144
   {
145 146
      int y;

147 148 149 150 151
      if (firstTime)
      {
	 firstChar = 0;
	 lastChar = 1;
	 viewSize = lastChar - firstChar;
152
	 startPos = widget->width - viewSize - BorderOf (widget);
153 154 155 156 157 158

	 firstTime = FALSE;
      }

      /* Draw in the characters. */
      y = firstChar;
159
      for (x = startPos; x < (startPos + viewSize); x++)
160 161
      {
	 chtype ch = (y < mesgLength) ? message[y] : ' ';
162
	 mvwaddch (widget->win, BorderOf (widget), x, ch);
163 164
	 y++;
      }
165
      wrefresh (widget->win);
166 167 168 169 170 171

      /* Set my variables. */
      if (mesgLength < viewLimit)
      {
	 if (lastChar < (mesgLength + padding))
	 {
172 173 174
	    lastChar++;
	    viewSize++;
	    startPos = widget->width - viewSize - BorderOf (widget);
175
	 }
176
	 else if (startPos > BorderOf (widget))
177 178
	 {
	    /* This means the whole string is visible. */
179
	    startPos--;
180 181 182 183
	    viewSize = mesgLength + padding;
	 }
	 else
	 {
184 185 186 187
	    /* We have to start chopping the viewSize */
	    startPos = BorderOf (widget);
	    firstChar++;
	    viewSize--;
188 189 190 191
	 }
      }
      else
      {
192
	 if (startPos > BorderOf (widget))
193
	 {
194 195 196
	    lastChar++;
	    viewSize++;
	    startPos--;
197 198 199
	 }
	 else if (lastChar < (mesgLength + padding))
	 {
200 201 202
	    firstChar++;
	    lastChar++;
	    startPos = BorderOf (widget);
203 204 205 206
	    viewSize = viewLimit;
	 }
	 else
	 {
207
	    startPos = BorderOf (widget);
208 209 210 211 212 213 214 215 216 217 218 219 220 221 222
	    firstChar++;
	    viewSize--;
	 }
      }

      /* OK, lets check if we have to start over. */
      if (viewSize <= 0 && firstChar == mesgLength + padding)
      {
	 /* Check if we repeat a specified number, or loop indefinitely. */
	 if ((repeat > 0) && (++repeatCount >= repeat))
	 {
	    break;
	 }

	 /* Time to start over.  */
223 224
	 mvwaddch (widget->win, BorderOf (widget), BorderOf (widget), ' ');
	 wrefresh (widget->win);
225 226 227 228 229 230 231 232
	 firstTime = TRUE;
      }

      /* Now sleep */
      napms (delay * 10);
   }
   if (oldcurs < 0)
      oldcurs = 1;
233
   curs_set (oldcurs);
234 235 236 237 238 239 240
   freeChtype (message);
   return (0);
}

/*
 * This de-activates a marquee widget.
 */
241
void deactivateCDKMarquee (CDKMARQUEE *widget)
242
{
243
   widget->active = FALSE;
244 245 246 247 248
}

/*
 * This moves the marquee field to the given location.
 */
249 250 251 252 253
static void _moveCDKMarquee (CDKOBJS *object,
			     int xplace,
			     int yplace,
			     boolean relative,
			     boolean refresh_flag)
254
{
255
   CDKMARQUEE *widget = (CDKMARQUEE *)object;
256
   /* *INDENT-EQLS* */
257 258
   int currentX = getbegx (widget->win);
   int currentY = getbegy (widget->win);
259 260 261 262
   int xpos     = xplace;
   int ypos     = yplace;
   int xdiff    = 0;
   int ydiff    = 0;
263 264 265 266 267 268 269

   /*
    * If this is a relative move, then we will adjust where we want
    * to move to.
    */
   if (relative)
   {
270 271
      xpos = getbegx (widget->win) + xplace;
      ypos = getbegy (widget->win) + yplace;
272 273 274
   }

   /* Adjust the window if we need to. */
275
   alignxy (WindowOf (widget), &xpos, &ypos, widget->boxWidth, widget->boxHeight);
276 277 278 279 280 281

   /* Get the difference. */
   xdiff = currentX - xpos;
   ydiff = currentY - ypos;

   /* Move the window to the new location. */
282 283
   moveCursesWindow (widget->win, -xdiff, -ydiff);
   moveCursesWindow (widget->shadowWin, -xdiff, -ydiff);
284 285

   /* Touch the windows so they 'move'. */
286
   refreshCDKWindow (WindowOf (widget));
287 288 289 290

   /* Redraw the window, if they asked for it. */
   if (refresh_flag)
   {
291
      drawCDKMarquee (widget, ObjOf (widget)->box);
292 293 294 295 296 297 298 299
   }
}

/*
 * This draws the marquee widget on the screen.
 */
static void _drawCDKMarquee (CDKOBJS *object, boolean Box)
{
300
   CDKMARQUEE *widget = (CDKMARQUEE *)object;
301 302

   /* Keep the box information. */
303
   ObjOf (widget)->box = Box;
304 305

   /* Do we need to draw a shadow??? */
306
   if (widget->shadowWin != 0)
307
   {
308
      drawShadow (widget->shadowWin);
309 310 311 312 313
   }

   /* Box it if needed. */
   if (Box)
   {
314
      drawObjBox (widget->win, ObjOf (widget));
315
   }
316 317 318 319
   else
   {
      touchwin (widget->win);
   }
320 321

   /* Refresh the window. */
322
   wrefresh (widget->win);
323 324 325
}

/*
326
 * This destroys the widget.
327 328 329 330 331
 */
static void _destroyCDKMarquee (CDKOBJS *object)
{
   if (object != 0)
   {
332
      CDKMARQUEE *widget = (CDKMARQUEE *)object;
333 334

      /* Clean up the windows. */
335 336 337 338 339
      deleteCursesWindow (widget->shadowWin);
      deleteCursesWindow (widget->win);

      /* Clean the key bindings. */
      cleanCDKObjectBindings (vMARQUEE, widget);
340 341

      /* Unregister this object. */
342
      unregisterCDKObject (vMARQUEE, widget);
343 344 345 346
   }
}

/*
347
 * This erases the widget.
348 349 350 351 352
 */
static void _eraseCDKMarquee (CDKOBJS *object)
{
   if (validCDKObject (object))
   {
353
      CDKMARQUEE *widget = (CDKMARQUEE *)object;
354

355 356
      eraseCursesWindow (widget->win);
      eraseCursesWindow (widget->shadowWin);
357 358 359 360 361 362
   }
}

/*
 * This sets the widgets box attribute.
 */
363
void setCDKMarqueeBox (CDKMARQUEE *widget, boolean Box)
364
{
365 366 367
   int xpos = widget->win ? getbegx (widget->win) : 0;
   int ypos = widget->win ? getbegy (widget->win) : 0;

368 369
   ObjOf (widget)->box = Box;
   ObjOf (widget)->borderSize = Box ? 1 : 0;
370 371

   layoutWidget (widget, xpos, ypos);
372
}
373
boolean getCDKMarqueeBox (CDKMARQUEE *widget)
374
{
375
   return ObjOf (widget)->box;
376 377 378 379 380 381 382 383 384
}

/*
 * This sets the background attribute of the widget.
 */
static void _setBKattrMarquee (CDKOBJS *object, chtype attrib)
{
   if (object != 0)
   {
385
      CDKMARQUEE *widget = (CDKMARQUEE *)object;
386

387
      wbkgd (widget->win, attrib);
388 389 390
   }
}

391
dummyInject (Marquee)
392

393
dummyFocus (Marquee)
394

395
dummyUnfocus (Marquee)
396

397
dummyRefreshData (Marquee)
398

399
dummySaveData (Marquee)