Updated PCI IDs to latest snapshot.
[tangerine.git] / workbench / classes / zune / calendar / calendar.c
blob72a4d172e52879b08993457798e0dcea60ffbcd0
1 /*
2 Copyright © 1995-2003, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 #include <exec/types.h>
7 #include <utility/date.h>
8 #include <libraries/mui.h>
10 #include <proto/muimaster.h>
11 #include <proto/graphics.h>
12 #include <proto/intuition.h>
13 #include <proto/utility.h>
14 #include <proto/locale.h>
15 #include <proto/timer.h>
17 #include <aros/debug.h>
18 #include <aros/asmcall.h>
20 #include <string.h>
21 #include <stdio.h>
23 #include "calendar.h"
24 #include "calendar_private.h"
26 #define CELL_EXTRAWIDTH 6
27 #define CELL_EXTRAHEIGHT 4
29 STRPTR def_daylabels[] =
31 "Sun",
32 "Mon",
33 "Tue",
34 "Wed",
35 "Thu",
36 "Fri",
37 "Sat"
40 /*** Methods ****************************************************************/
42 IPTR Calendar__OM_NEW(Class *cl, Object *obj, struct opSet *msg)
44 struct Calendar_DATA *data;
45 struct TagItem *ti;
47 obj = (Object *)DoSuperMethodA(cl, obj, (Msg)msg);
48 if (!obj) return 0;
50 data = INST_DATA(cl, obj);
52 data->daylabels = (STRPTR *)GetTagData(MUIA_Calendar_DayLabels, 0, msg->ops_AttrList);
53 if (!data->daylabels)
55 struct Locale *locale;
56 WORD i;
58 locale = LocaleBase ? OpenLocale(NULL) : NULL;
60 data->daylabels = data->defdaylabels;
61 for(i = 0; i < 12; i++)
63 if (locale)
65 data->defdaylabels[i] = GetLocaleStr(locale, ABDAY_1 + i);
66 data->firstweekday = locale->loc_CalendarType;
68 else
70 data->defdaylabels[i] = def_daylabels[i];
71 data->firstweekday = 0;
75 if (locale) CloseLocale(locale);
78 if ((ti = FindTagItem(MUIA_Calendar_Date, msg->ops_AttrList)))
80 struct ClockData *cd = (struct ClockData *)ti->ti_Data;
82 data->clockdata = *cd;
84 else
86 struct timeval tv;
88 GetSysTime(&tv);
89 Amiga2Date(tv.tv_secs, &data->clockdata);
92 data->ehn.ehn_Events = IDCMP_MOUSEBUTTONS | IDCMP_RAWKEY;
93 data->ehn.ehn_Priority = 0;
94 data->ehn.ehn_Flags = 0;
95 data->ehn.ehn_Object = obj;
96 data->ehn.ehn_Class = cl;
98 return (IPTR)obj;
102 IPTR Calendar__OM_DISPOSE(Class *cl, Object *obj, Msg msg)
104 return DoSuperMethodA(cl, obj, msg);
107 LONG NumMonthDays(struct ClockData *cd)
109 struct ClockData cd2;
110 ULONG secs;
111 LONG monthday = 28;
113 cd2 = *cd;
115 while(monthday < 32)
117 cd2.mday = monthday;
119 secs = Date2Amiga(&cd2);
120 secs += 24 * 60 * 60; /* day++ */
122 Amiga2Date(secs, &cd2);
124 if (cd2.month != cd->month) break;
126 monthday++;
129 return monthday;
132 IPTR Calendar__OM_SET(Class *cl, Object *obj, struct opSet *msg)
134 struct Calendar_DATA *data = INST_DATA(cl, obj);
135 struct ClockData old_clockdata;
136 const struct TagItem *tags = msg->ops_AttrList;
137 struct TagItem *tag;
138 BOOL redraw = FALSE;
140 old_clockdata = data->clockdata;
142 while ((tag = NextTagItem(&tags)) != NULL)
144 switch(tag->ti_Tag)
146 case MUIA_Calendar_Date:
147 data->clockdata = *(struct ClockData *)tag->ti_Data;
148 redraw = TRUE;
149 break;
151 case MUIA_Calendar_Year:
152 data->clockdata.year = tag->ti_Data;
153 redraw = TRUE;
154 break;
156 case MUIA_Calendar_Month:
157 data->clockdata.month = tag->ti_Data;
158 redraw = TRUE;
159 break;
161 case MUIA_Calendar_Month0:
162 data->clockdata.month = tag->ti_Data + 1;
163 redraw = TRUE;
164 break;
166 case MUIA_Calendar_MonthDay:
167 data->clockdata.mday = tag->ti_Data;
168 redraw = TRUE;
169 break;
171 case MUIA_Calendar_MonthDay0:
172 data->clockdata.mday = tag->ti_Data + 1;
173 redraw = TRUE;
174 break;
176 } /* switch(tag->ti_Tag) */
178 } /* while ((tag = NextTagItem(&tags)) != NULL) */
180 if (redraw)
182 struct ClockData cd2;
183 ULONG secs;
185 cd2 = data->clockdata;
186 cd2.mday = 1;
188 if (data->clockdata.mday > NumMonthDays(&cd2))
190 data->clockdata.mday = NumMonthDays(&cd2);
193 secs = Date2Amiga(&data->clockdata);
195 Amiga2Date(secs, &data->clockdata);
197 if ((data->clockdata.year != old_clockdata.year) ||
198 (data->clockdata.month != old_clockdata.month) ||
199 (data->clockdata.mday != old_clockdata.mday))
201 if ((data->clockdata.year == old_clockdata.year) &&
202 (data->clockdata.month == old_clockdata.month))
204 data->old_mday = old_clockdata.mday;
206 MUI_Redraw(obj, MADF_DRAWUPDATE);
207 data->old_mday = 0;
211 return DoSuperMethodA(cl, obj, (Msg)msg);
215 IPTR Calendar__OM_GET(Class *cl, Object *obj, struct opGet *msg)
217 struct Calendar_DATA *data = INST_DATA(cl, obj);
218 IPTR retval = TRUE;
220 switch(msg->opg_AttrID)
222 case MUIA_Calendar_Date:
223 *(struct ClockData **)msg->opg_Storage = &data->clockdata;
224 break;
226 case MUIA_Calendar_MonthDay:
227 *msg->opg_Storage = data->clockdata.mday;
228 break;
230 case MUIA_Calendar_MonthDay0:
231 *msg->opg_Storage = data->clockdata.mday - 1;
232 break;
234 case MUIA_Calendar_Month:
235 *msg->opg_Storage = data->clockdata.month;
236 break;
238 case MUIA_Calendar_Month0:
239 *msg->opg_Storage = data->clockdata.month - 1;
240 break;
242 case MUIA_Calendar_Year:
243 *msg->opg_Storage = data->clockdata.year;
244 break;
246 default:
247 retval = DoSuperMethodA(cl, obj, (Msg)msg);
248 break;
252 return retval;
256 IPTR Calendar__MUIM_Setup(Class *cl, Object *obj, struct MUIP_Setup *msg)
258 struct Calendar_DATA *data = INST_DATA(cl, obj);
259 struct RastPort rp;
260 WORD i, w;
262 if (!DoSuperMethodA(cl, obj, (Msg)msg)) return FALSE;
264 InitRastPort(&rp);
265 SetFont(&rp, _font(obj));
267 data->cellheight = _font(obj)->tf_YSize + CELL_EXTRAHEIGHT;
269 SetSoftStyle(&rp, FSF_BOLD, AskSoftStyle(&rp));
271 for(i = 0; i < 7; i++)
273 w = TextLength(&rp, data->daylabels[i], strlen(data->daylabels[i]));
274 if (w > data->cellwidth) data->cellwidth = w;
277 SetSoftStyle(&rp, FS_NORMAL, AskSoftStyle(&rp));
279 for(i = 1; i <= 31; i++)
281 char s[3];
283 sprintf(s, "%d", i);
285 w = TextLength(&rp, s, strlen(s));
286 if (w > data->cellwidth) data->cellwidth = w;
289 DeinitRastPort(&rp);
291 data->cellwidth += CELL_EXTRAWIDTH;
293 data->base_cellwidth = data->cellwidth;
294 data->base_cellheight = data->cellheight;
296 DoMethod(_win(obj), MUIM_Window_AddEventHandler, (IPTR) &data->ehn);
298 return TRUE;
302 IPTR Calendar__MUIM_Cleanup(Class *cl, Object *obj, struct MUIP_Cleanup *msg)
304 struct Calendar_DATA *data = INST_DATA(cl, obj);
306 DoMethod(_win(obj), MUIM_Window_RemEventHandler, (IPTR) &data->ehn);
308 return DoSuperMethodA(cl, obj, (Msg)msg);
312 IPTR Calendar__MUIM_AskMinMax(Class *cl, Object *obj, struct MUIP_AskMinMax *msg)
314 struct Calendar_DATA *data = INST_DATA(cl, obj);
316 DoSuperMethodA(cl, obj, (Msg)msg);
318 msg->MinMaxInfo->MinWidth += data->cellwidth * 7 + 2;
319 msg->MinMaxInfo->MinHeight += data->cellheight * 7 + 1;
320 msg->MinMaxInfo->DefWidth += data->cellwidth * 7 + 2;
321 msg->MinMaxInfo->DefHeight += data->cellheight * 7 + 1;
322 msg->MinMaxInfo->MaxWidth = MUI_MAXMAX;
323 msg->MinMaxInfo->MaxHeight = MUI_MAXMAX;
326 return TRUE;
330 IPTR Calendar__MUIM_Draw(Class *cl, Object *obj, struct MUIP_Draw *msg)
332 struct Calendar_DATA *data = INST_DATA(cl, obj);
333 struct Region *region;
334 struct Rectangle rect;
335 APTR clip = NULL;
336 WORD x, y, offx, offy, day, mdays;
338 x = (_mwidth(obj) - 2) / 7;
339 y = x * data->base_cellheight / data->base_cellwidth;
341 data->cellheight = (_mheight(obj) - 1) / 7;
342 data->cellwidth = data->cellheight * data->base_cellwidth / data->base_cellheight;
344 if ((data->cellwidth > x) || (data->cellheight > y))
346 data->cellwidth = x;
347 data->cellheight = y;
350 offx = _mleft(obj) + (_mwidth(obj) - data->cellwidth * 7 - 2) / 2 + 1;
351 offy = _mtop(obj) + (_mheight(obj) - data->cellheight * 7 - 1) / 2;
353 region = NewRegion();
354 if (region)
356 rect.MinX = _left(obj);
357 rect.MinY = _top(obj);
358 rect.MaxX = _right(obj);
359 rect.MaxY = _bottom(obj);
361 OrRectRegion(region, &rect);
363 rect.MinX = offx - 1;
364 rect.MinY = offy;
365 rect.MaxX = offx + data->cellwidth * 7;
366 rect.MaxY = offy + data->cellheight * 7;
368 ClearRectRegion(region, &rect);
370 clip = MUI_AddClipRegion(muiRenderInfo(obj), region);
373 DoSuperMethodA(cl, obj, (Msg)msg);
375 if (region)
377 MUI_RemoveClipRegion(muiRenderInfo(obj), clip);
380 if (!(msg->flags & (MADF_DRAWOBJECT | MADF_DRAWUPDATE))) return 0;
382 data->mwday =
383 (data->clockdata.wday - (data->clockdata.mday - 1) % 7 + 7) % 7;
385 mdays = NumMonthDays(&data->clockdata);
387 //kprintf("actdate = %d.%d.%d wday = %d\n", data->clockdata.mday, data->clockdata.month, data->clockdata.year, data->clockdata.wday);
389 //kprintf("mwday = %d mdays = %d\n", data->mwday, mdays);
391 day = data->firstweekday - data->mwday + 1 - 7;
392 if (day > -6) day -= 7;
394 SetFont(_rp(obj), _font(obj));
395 SetDrMd(_rp(obj), JAM1);
397 if (!(msg->flags & MADF_DRAWUPDATE))
399 SetAPen(_rp(obj), _dri(obj)->dri_Pens[SHADOWPEN]);
400 Move(_rp(obj), offx - 1,
401 offy);
402 Draw(_rp(obj), offx - 1,
403 offy + data->cellheight * 7);
404 Draw(_rp(obj), offx + data->cellwidth * 7,
405 offy + data->cellheight * 7);
406 Draw(_rp(obj), offx + data->cellwidth * 7,
407 offy);
410 for(y = 0; y < 7; y++)
412 if (!y && (msg->flags & MADF_DRAWUPDATE))
414 day += 7;
415 continue;
418 for(x = 0; x < 7; x++)
420 STRPTR text;
421 UBYTE buf[3];
423 if (data->old_mday && (day != data->old_mday) && (day != data->clockdata.mday))
425 day++;
426 continue;
429 text = NULL;
430 if (day == data->clockdata.mday)
432 SetAPen(_rp(obj), _pens(obj)[MPEN_FILL]);
434 else
436 SetAPen(_rp(obj), _dri(obj)->dri_Pens[y ? SHINEPEN : SHADOWPEN]);
439 RectFill(_rp(obj), x * data->cellwidth + 1 + offx,
440 y * data->cellheight + 1 + offy,
441 x * data->cellwidth + data->cellwidth - 2 + offx,
442 y * data->cellheight + data->cellheight - 2 + offy);
444 SetAPen(_rp(obj), _dri(obj)->dri_Pens[SHADOWPEN]);
445 Move(_rp(obj), x * data->cellwidth + offx,
446 y * data->cellheight + offy);
447 Draw(_rp(obj), x * data->cellwidth + data->cellwidth - 1 + offx,
448 y * data->cellheight + offy);
449 Draw(_rp(obj), x * data->cellwidth + data->cellwidth - 1 + offx,
450 y * data->cellheight + data->cellheight - 1 + offy);
451 Draw(_rp(obj), x * data->cellwidth + offx,
452 y * data->cellheight + data->cellheight - 1 + offy);
453 Draw(_rp(obj), x * data->cellwidth + offx,
454 y * data->cellheight + offy);
456 if (y > 0)
458 if ((day >= 1) && (day <= mdays))
460 sprintf(buf, "%d", day);
461 SetSoftStyle(_rp(obj), FS_NORMAL, AskSoftStyle(_rp(obj)));
462 SetAPen(_rp(obj), _dri(obj)->dri_Pens[day == data->clockdata.mday ? SHADOWPEN : FILLTEXTPEN]);
463 text = buf;
466 else
468 SetSoftStyle(_rp(obj), FSF_BOLD, AskSoftStyle(_rp(obj)));
469 SetAPen(_rp(obj), _dri(obj)->dri_Pens[SHINEPEN]);
471 text = data->daylabels[(x + data->firstweekday) % 7];
474 if (text)
476 WORD tx, ty, tw;
478 tw = TextLength(_rp(obj), text, strlen(text));
479 tx = offx + x * data->cellwidth + (data->cellwidth - tw) / 2;
480 ty = offy + y * data->cellheight + (data->cellheight - _font(obj)->tf_YSize) / 2;
482 Move(_rp(obj), tx, ty + _font(obj)->tf_Baseline);
483 Text(_rp(obj), text, strlen(text));
486 day++;
488 } /* for(x = 0; x < 7; x++) */
490 } /* for(y = 0; y < 7; y++) */
492 return 0;
496 static WORD DayUnderMouse(Object *obj, struct Calendar_DATA *data, struct IntuiMessage *imsg)
498 WORD x, y, offx, offy, i;
500 offx = (_mwidth(obj) - data->cellwidth * 7 - 2) / 2 + 1;
501 offy = (_mheight(obj) - data->cellheight * 7 - 1) / 2 + data->cellheight;
503 x = imsg->MouseX - _mleft(obj) - offx;
504 y = imsg->MouseY - _mtop(obj) - offy;
506 if (x < 0) x = 0;
507 if (y < 0) y = 0;
508 if (x >= data->cellwidth * 7) x = data->cellwidth * 7 - 1;
509 if (y >= data->cellheight * 6) y = data->cellheight * 6 - 1;
511 x /= data->cellwidth;
512 y /= data->cellheight;
514 i = data->firstweekday - data->mwday + 1;
515 if (i > 1) i -= 7;
517 i += y * 7 + x;
519 if (i < 1)
521 i = 1;
523 else if (i > NumMonthDays(&data->clockdata))
525 i = NumMonthDays(&data->clockdata);
528 return i;
532 #define _between(a,x,b) ((x)>=(a) && (x)<=(b))
535 IPTR Calendar__MUIM_HandleEvent(Class *cl, Object *obj, struct MUIP_HandleEvent *msg)
537 struct Calendar_DATA *data = INST_DATA(cl, obj);
539 if (msg->muikey != MUIKEY_NONE)
541 UWORD day = data->clockdata.mday;
543 switch(msg->muikey)
545 case MUIKEY_LEFT:
546 if (day > 1)
548 set(obj, MUIA_Calendar_MonthDay, day - 1);
549 return MUI_EventHandlerRC_Eat;
551 break;
553 case MUIKEY_RIGHT:
554 if (day < NumMonthDays(&data->clockdata))
556 set(obj, MUIA_Calendar_MonthDay, day + 1);
557 return MUI_EventHandlerRC_Eat;
559 break;
561 case MUIKEY_UP:
563 UWORD newday = (day > 7) ? day - 7 : 1;
565 if (newday != day)
567 set(obj, MUIA_Calendar_MonthDay, newday);
568 return MUI_EventHandlerRC_Eat;
571 break;
573 case MUIKEY_DOWN:
575 UWORD newday = (day < NumMonthDays(&data->clockdata) - 7) ?
576 day + 7 : NumMonthDays(&data->clockdata);
578 if (newday != day)
580 set(obj, MUIA_Calendar_MonthDay, newday);
581 return MUI_EventHandlerRC_Eat;
584 break;
586 case MUIKEY_TOP:
587 case MUIKEY_LINESTART:
588 if (day != 1)
590 set(obj, MUIA_Calendar_MonthDay, 1);
591 return MUI_EventHandlerRC_Eat;
593 break;
595 case MUIKEY_BOTTOM:
596 case MUIKEY_LINEEND:
597 if (day != NumMonthDays(&data->clockdata))
599 set(obj, MUIA_Calendar_MonthDay, NumMonthDays(&data->clockdata));
600 return MUI_EventHandlerRC_Eat;
602 break;
606 else
608 WORD x1 = _mleft(obj) + (_mwidth(obj) - data->cellwidth * 7 - 2) / 2 + 1;
609 WORD y1 = _mtop(obj) + (_mheight(obj) - data->cellheight * 7 - 1) / 2 + data->cellheight;
610 WORD x2 = x1 + data->cellwidth * 7 - 1;
611 WORD y2 = y1 + data->cellheight * 6 - 1;
612 WORD day;
614 BOOL in = _between(x1, msg->imsg->MouseX, x2) && _between(y1, msg->imsg->MouseY, y2);
616 switch(msg->imsg->Class)
618 case IDCMP_MOUSEBUTTONS:
619 switch(msg->imsg->Code)
621 case SELECTDOWN:
622 if (in)
624 day = DayUnderMouse(obj, data, msg->imsg);
625 if (day != data->clockdata.mday)
627 set(obj, MUIA_Calendar_MonthDay, day);
629 DoMethod(_win(obj), MUIM_Window_RemEventHandler, (IPTR)&data->ehn);
630 data->ehn.ehn_Events |= IDCMP_MOUSEMOVE;
631 DoMethod(_win(obj), MUIM_Window_AddEventHandler, (IPTR)&data->ehn);
632 return 0;
634 break;
636 case SELECTUP:
637 if (data->ehn.ehn_Events & IDCMP_MOUSEMOVE)
639 DoMethod(_win(obj), MUIM_Window_RemEventHandler, (IPTR)&data->ehn);
640 data->ehn.ehn_Events &= ~IDCMP_MOUSEMOVE;
641 DoMethod(_win(obj), MUIM_Window_AddEventHandler, (IPTR)&data->ehn);
642 return 0;
644 break;
646 break;
648 case IDCMP_MOUSEMOVE:
649 if (data->ehn.ehn_Events & IDCMP_MOUSEMOVE)
651 day = DayUnderMouse(obj, data, msg->imsg);
652 if (day != data->clockdata.mday)
654 set(obj, MUIA_Calendar_MonthDay, day);
656 return 0;
658 break;
660 } /* switch(msg->imsg->Class) */
662 } /* if (msg->muikey == MUIKEY_NONE) */
664 return 0;