~geballin/ical-tcl/ical-tcl

1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
1
/* Copyright (c) 1993 by Sanjay Ghemawat */
2
#include <assert.h>
3
#include <stdlib.h>
4
#include <string.h>
5
6
#include "WeekDay.h"
7
8
#include "basic.h"
9
#include "arrays.h"
10
#include "cal_tcl.h"
11
#include "calfile.h"
12
#include "calendar.h"
13
#include "ical.h"
14
#include "item_tcl.h"
15
#include "dispatch.h"
16
17
/*
18
 * Item* -> Item_Tcl* map.
19
 */
20
static Tcl_HashTable itemMap;
21
static int itemMapInited = 0;
22
23
static int check_permission(Tcl_Interp* tcl, Item_Tcl* item);
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
24
// effects      If "item" can be modified legally, then mark
25
//              containing calendar as modified and return true.
26
//              Else store an error message in "tcl->result"
27
//              and return false.
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
28
29
static void trigger_item(Tcl_Interp* tcl, Item_Tcl* item,
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
30
                         char const* = "change");
31
// effects      If "item" belongs to a calendar, generate a trigger message
32
//              for it.  The generate trigger is of type "change" by default,
33
//              but that can be overridden by providing a different value for
34
//              the optional last argument.
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
35
36
Item_Tcl::Item_Tcl(Tcl_Interp* tcl, Item* i, CalFile* c)
37
    : Object(tcl, "Item")
38
{
39
    item = i;
40
    cal = c;
41
42
    if (! itemMapInited) {
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
43
        itemMapInited = 1;
44
        Tcl_InitHashTable(&itemMap, TCL_ONE_WORD_KEYS);
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
45
    }
46
    int newentry;
47
    Tcl_HashEntry* entry = Tcl_CreateHashEntry(&itemMap,(char*)item,&newentry);
48
    assert(newentry);
49
    Tcl_SetHashValue(entry, (ClientData)this);
50
}
51
52
Item_Tcl::~Item_Tcl() {
53
    Tcl_HashEntry* entry = Tcl_FindHashEntry(&itemMap, (char*)item);
54
    assert((entry != 0) && (Tcl_GetHashValue(entry) == ((ClientData) this)));
55
    Tcl_DeleteHashEntry(entry);
56
}
57
58
Item_Tcl* Item_Tcl::find(Item* item) {
59
    Tcl_HashEntry* entry = Tcl_FindHashEntry(&itemMap, (char*)item);
60
    return ((entry == 0) ? 0 : ((Item_Tcl*) Tcl_GetHashValue(entry)));
61
}
62
63
/*
64
 * Forward declaration of handler procedures.
65
 */
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
66
static int item_length    (ClientData, Tcl_Interp*, int, const char**);
11 by Sergei Golubchik
timezone support: lots of changes
67
static int item_starttime (ClientData, Tcl_Interp*, int, const char**);
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
68
static int item_timezone  (ClientData, Tcl_Interp*, int, const char**);
69
static int item_clone     (ClientData, Tcl_Interp*, int, const char**);
70
static int item_is        (ClientData, Tcl_Interp*, int, const char**);
71
static int item_delete    (ClientData, Tcl_Interp*, int, const char**);
72
static int item_cal       (ClientData, Tcl_Interp*, int, const char**);
73
static int item_text      (ClientData, Tcl_Interp*, int, const char**);
74
static int item_uid       (ClientData, Tcl_Interp*, int, const char**);
75
static int item_early     (ClientData, Tcl_Interp*, int, const char**);
76
static int item_owner     (ClientData, Tcl_Interp*, int, const char**);
77
static int item_owned     (ClientData, Tcl_Interp*, int, const char**);
78
static int item_own       (ClientData, Tcl_Interp*, int, const char**);
79
static int item_hilite    (ClientData, Tcl_Interp*, int, const char**);
80
static int item_todo      (ClientData, Tcl_Interp*, int, const char**);
81
static int item_is_done   (ClientData, Tcl_Interp*, int, const char**);
82
static int item_done      (ClientData, Tcl_Interp*, int, const char**);
83
static int item_alarms    (ClientData, Tcl_Interp*, int, const char**);
84
static int item_option    (ClientData, Tcl_Interp*, int, const char**);
85
static int item_doption   (ClientData, Tcl_Interp*, int, const char**);
86
static int item_empty     (ClientData, Tcl_Interp*, int, const char**);
87
static int item_repeat    (ClientData, Tcl_Interp*, int, const char**);
88
static int item_first     (ClientData, Tcl_Interp*, int, const char**);
89
static int item_type      (ClientData, Tcl_Interp*, int, const char**);
90
static int item_desc      (ClientData, Tcl_Interp*, int, const char**);
91
static int item_cont      (ClientData, Tcl_Interp*, int, const char**);
92
static int item_next      (ClientData, Tcl_Interp*, int, const char**);
93
static int item_range     (ClientData, Tcl_Interp*, int, const char**);
94
static int item_date      (ClientData, Tcl_Interp*, int, const char**);
95
static int item_start     (ClientData, Tcl_Interp*, int, const char**);
96
static int item_finish    (ClientData, Tcl_Interp*, int, const char**);
97
static int item_ondel     (ClientData, Tcl_Interp*, int, const char**);
98
static int item_dayr      (ClientData, Tcl_Interp*, int, const char**);
99
static int item_wdays     (ClientData, Tcl_Interp*, int, const char**);
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
100
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
101
static int item_monthr    (ClientData, Tcl_Interp*, int, const char**);
102
static int item_mday      (ClientData, Tcl_Interp*, int, const char**);
103
static int item_mlday     (ClientData, Tcl_Interp*, int, const char**);
104
static int item_mworkday  (ClientData, Tcl_Interp*, int, const char**);
105
static int item_mlworkday (ClientData, Tcl_Interp*, int, const char**);
106
static int item_mweekday  (ClientData, Tcl_Interp*, int, const char**);
107
static int item_mlweekday (ClientData, Tcl_Interp*, int, const char**);
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
108
109
static Dispatch_Entry item_dispatch[] = {
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
110
    { "delete",                 0, 0, item_delete       },
111
    { "clone",                  0, 0, item_clone        },
112
113
    { "length",                 0, 1, item_length       },
11 by Sergei Golubchik
timezone support: lots of changes
114
    { "starttime",              1, 2, item_starttime    },
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
115
    { "timezone",               0, 2, item_timezone     },
116
    { "alarms",                 0, 1, item_alarms       },
117
    { "option",                 1, 2, item_option       },
118
    { "delete_option",          1, 1, item_doption      },
119
120
    { "is",                     1, 1, item_is           },
121
    { "calendar",               0, 0, item_cal          },
122
    { "text",                   0, 1, item_text         },
123
    { "uid",                    0, 0, item_uid          },
124
    { "earlywarning",           0, 1, item_early        },
125
    { "owner",                  0, 1, item_owner        },
126
    { "owned",                  0, 0, item_owned        },
127
    { "own",                    0, 0, item_own          },
128
    { "hilite",                 0, 1, item_hilite       },
129
    { "todo",                   0, 1, item_todo         },
130
    { "is_done",                0, 0, item_is_done      },
131
    { "done",                   1, 1, item_done         },
132
133
    { "contains",               1, 1, item_cont         },
134
    { "empty",                  0, 0, item_empty        },
135
    { "repeats",                0, 0, item_repeat       },
136
    { "first",                  0, 0, item_first        },
137
    { "next",                   1, 1, item_next         },
138
    { "range",                  2, 3, item_range        },
139
    { "type",                   0, 0, item_type         },
140
    { "describe_repeat",        0, 1, item_desc         },
141
142
    { "date",                   1, 1, item_date         },
143
    { "dayrepeat",              2, 2, item_dayr         },
144
145
    { "monthrepeat",            2, 2, item_monthr       },
146
    { "month_day",              1, 3, item_mday         },
147
    { "month_last_day",         1, 3, item_mlday        },
148
    { "month_work_day",         1, 3, item_mworkday     },
149
    { "month_last_work_day",    1, 3, item_mlworkday    },
150
    { "month_week_day",         2, 4, item_mweekday     },
151
    { "month_last_week_day",    2, 4, item_mlweekday    },
152
153
    { "weekdays",               0, -1, item_wdays       },
11 by Sergei Golubchik
timezone support: lots of changes
154
    { "start",                  1,  2, item_start       },
155
    { "finish",                 1,  2, item_finish      },
156
    { "deleteon",               1,  1, item_ondel       },
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
157
158
    { 0,                        0, 0, 0                 }
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
159
};
160
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
161
int Item_Tcl::method(int argc, const char** argv) {
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
162
    return Dispatch(item_dispatch, (ClientData)this, tcl(), argc, argv);
163
}
164
165
/*
166
 * Handler procedures.
167
 */
168
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
169
static int item_length(ClientData c, Tcl_Interp* tcl, int argc, const char** argv) {
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
170
    Item_Tcl* item = (Item_Tcl*) c;
171
172
    Appointment* appt = item->value()->AsAppointment();
173
    if (appt != 0) {
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
174
        if (argc == 0) {
175
            char buffer[100];
176
            sprintf(buffer, "%d", appt->GetLength());
177
            Tcl_SetResult(tcl, buffer, TCL_VOLATILE);
178
            return TCL_OK;
179
        }
180
181
        int length;
182
        if ((Tcl_GetInt(tcl, argv[0], &length) != TCL_OK) ||
183
            (length < 1) ||
184
            (length > 24*60)) {
185
            TCL_Error(tcl, "invalid appointment length");
186
        }
187
        if (! check_permission(tcl, item)) return TCL_ERROR;
188
189
        appt->SetLength(length);
190
        trigger_item(tcl, item);
191
192
        TCL_Return(tcl, "");
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
193
    }
194
195
    TCL_Error(tcl, "unknown command");
196
}
197
11 by Sergei Golubchik
timezone support: lots of changes
198
static int item_starttime(ClientData c, Tcl_Interp* tcl, int argc, const char** argv) {
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
199
    Item_Tcl* item = (Item_Tcl*) c;
11 by Sergei Golubchik
timezone support: lots of changes
200
    int date;
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
201
202
    Appointment* appt = item->value()->AsAppointment();
203
    if (appt == 0) {
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
204
        TCL_Error(tcl, "unknown command");
205
    }
206
11 by Sergei Golubchik
timezone support: lots of changes
207
    if (strcmp(argv[0], "native") == 0) {
208
        date = -1;
209
    } else {
210
        if (Tcl_GetInt(tcl, argv[0], &date) != TCL_OK || date < 0) {
211
            TCL_Error(tcl, "invalid starttime's date");
212
        }
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
213
    }
214
11 by Sergei Golubchik
timezone support: lots of changes
215
    if (argc == 1) {
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
216
        char buffer[100];
11 by Sergei Golubchik
timezone support: lots of changes
217
        sprintf(buffer, "%d", appt->GetStart(date));
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
218
        Tcl_SetResult(tcl, buffer, TCL_VOLATILE);
219
        return TCL_OK;
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
220
    }
221
222
    int start;
12 by Sergei Golubchik
oops, starttime didn't work
223
    if ((Tcl_GetInt(tcl, argv[1], &start) != TCL_OK) ||
11 by Sergei Golubchik
timezone support: lots of changes
224
        (start < 0) || (start >= (24*60))) {
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
225
        TCL_Error(tcl, "invalid appointment start");
226
    }
227
    if (! check_permission(tcl, item)) return TCL_ERROR;
228
11 by Sergei Golubchik
timezone support: lots of changes
229
    appt->SetStart(date, start);
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
230
    trigger_item(tcl, item);
231
232
    TCL_Return(tcl, "");
233
}
234
235
static int item_timezone(ClientData c, Tcl_Interp* tcl, int argc, const char** argv) {
236
    Item_Tcl* item = (Item_Tcl*) c;
11 by Sergei Golubchik
timezone support: lots of changes
237
    bool convert_remote=false;
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
238
239
    Appointment* appt = item->value()->AsAppointment();
240
    if (appt == 0) {
241
        TCL_Error(tcl, "unknown command");
242
    }
243
244
    if (argc == 0) {
245
        TCL_Return(tcl, (char*) appt->GetTimezone());
246
    }
247
10 by Sergei Golubchik
bugfix: no timezones in notices
248
    if (argc > 1 && strcmp(argv[0], "-convert") == 0) {
11 by Sergei Golubchik
timezone support: lots of changes
249
        convert_remote=true;
10 by Sergei Golubchik
bugfix: no timezones in notices
250
        argc--;
251
        argv++;
252
    }
253
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
254
    if (! check_permission(tcl, item)) return TCL_ERROR;
11 by Sergei Golubchik
timezone support: lots of changes
255
    appt->SetTimezone(argv[0], convert_remote);
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
256
    trigger_item(tcl, item);
257
258
    TCL_Return(tcl, "");
259
}
260
261
static int item_clone(ClientData c, Tcl_Interp* tcl, int argc, const char** argv) {
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
262
    Item_Tcl* item = (Item_Tcl*) c;
263
    Item_Tcl* clone = new Item_Tcl(tcl, item->value()->Clone(), 0);
264
    TCL_Return(tcl, (char*) clone->handle());
265
}
266
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
267
static int item_is(ClientData c, Tcl_Interp* tcl, int argc, const char** argv) {
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
268
    Item_Tcl* item = (Item_Tcl*) c;
269
270
    if ((strcmp(argv[0], "note") == 0) && (item->value()->AsNotice() != 0)) {
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
271
        TCL_Return(tcl, "1");
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
272
    }
273
274
    if ((strcmp(argv[0], "appt") == 0) && (item->value()->AsAppointment()!=0)){
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
275
        TCL_Return(tcl, "1");
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
276
    }
277
278
    TCL_Return(tcl, "0");
279
}
280
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
281
static int item_delete(ClientData c, Tcl_Interp* tcl, int argc, const char** argv) {
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
282
    Item_Tcl* item = ((Item_Tcl*) c);
283
    if (! check_permission(tcl, item)) return TCL_ERROR;
284
285
    CalFile* file = item->calendar();
286
    if (file != 0) {
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
287
        item->set_calendar(0);
288
        file->GetCalendar()->Remove(item->value());
289
        file->Modified();
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
290
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
291
        // XXX Only send triggers when deleting an item from a calendar???
292
        trigger(tcl, "delete", item->handle());
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
293
    }
294
295
    delete item->value();
296
    delete item;
297
298
    TCL_Return(tcl, "");
299
}
300
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
301
static int item_cal(ClientData c, Tcl_Interp* tcl, int argc, const char** argv) {
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
302
    Item_Tcl* item = (Item_Tcl*) c;
303
304
    CalFile* cal = item->calendar();
305
    if (cal == 0) {
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
306
        TCL_Error(tcl, "item not in calendar");
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
307
    }
308
    TCL_Return(tcl, (char*)(cal->GetName()));
309
}
310
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
311
static int item_text(ClientData c, Tcl_Interp* tcl, int argc, const char** argv) {
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
312
    Item_Tcl* item = (Item_Tcl*) c;
313
314
    if (argc == 0) {
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
315
        TCL_Return(tcl, (char*) item->value()->GetText());
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
316
    }
317
318
    if (! check_permission(tcl, item)) return TCL_ERROR;
319
    item->value()->SetText(argv[0]);
320
    trigger_item(tcl, item, "text");
321
322
    TCL_Return(tcl, "");
323
}
324
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
325
static int item_uid(ClientData c, Tcl_Interp* tcl, int argc, const char** argv) {
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
326
    Item_Tcl* item = (Item_Tcl*) c;
327
    TCL_Return(tcl, (char*) item->value()->GetUid());
328
}
329
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
330
static int item_early(ClientData c, Tcl_Interp* tcl, int argc, const char** argv) {
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
331
    Item_Tcl* item = (Item_Tcl*) c;
332
333
    if (argc == 0) {
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
334
        char buffer[100];
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
335
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
336
        sprintf(buffer, "%d", item->value()->GetRemindStart());
337
        Tcl_SetResult(tcl, buffer, TCL_VOLATILE);
338
        return TCL_OK;
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
339
    }
340
341
    int warn;
342
    if (Tcl_GetInt(tcl, argv[0], &warn) != TCL_OK) {
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
343
        TCL_Error(tcl, "invalid early warning option");
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
344
    }
345
    if (! check_permission(tcl, item)) return TCL_ERROR;
346
    item->value()->SetRemindStart(warn);
347
    trigger_item(tcl, item);
348
349
    TCL_Return(tcl, "");
350
}
351
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
352
static int item_owner(ClientData c, Tcl_Interp* tcl, int argc, const char** argv) {
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
353
    Item_Tcl* item = (Item_Tcl*) c;
354
355
    if (argc == 0) {
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
356
        TCL_Return(tcl, (char*) item->value()->GetOwner());
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
357
    }
358
359
    if (! check_permission(tcl, item)) return TCL_ERROR;
360
    item->value()->SetOwner(argv[0]);
361
    trigger_item(tcl, item);
362
363
    TCL_Return(tcl, "");
364
}
365
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
366
static int item_owned(ClientData c, Tcl_Interp* tcl, int argc, const char** argv) {
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
367
    Item_Tcl* item = (Item_Tcl*) c;
368
    TCL_Return(tcl, (item->value()->IsMine() ? "1" : "0"));
369
}
370
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
371
static int item_own(ClientData c, Tcl_Interp* tcl, int argc, const char** argv) {
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
372
    Item_Tcl* item = (Item_Tcl*) c;
373
    if (! check_permission(tcl, item)) return TCL_ERROR;
374
    item->value()->MakeOwner();
375
    trigger_item(tcl, item);
376
377
    TCL_Return(tcl, "");
378
}
379
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
380
static int item_hilite(ClientData c, Tcl_Interp* tcl, int argc, const char** argv) {
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
381
    Item_Tcl* item = (Item_Tcl*) c;
382
383
    if (argc == 0) {
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
384
        Tcl_SetResult(tcl, (char*) (item->value()->Hilite()), TCL_VOLATILE);
385
        return TCL_OK;
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
386
    }
387
388
    if (! check_permission(tcl, item)) return TCL_ERROR;
389
    item->value()->Hilite(argv[0]);
390
    trigger_item(tcl, item);
391
392
    TCL_Return(tcl, "");
393
}
394
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
395
static int item_todo(ClientData c, Tcl_Interp* tcl, int argc, const char** argv) {
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
396
    Item_Tcl* item = (Item_Tcl*) c;
397
398
    if (argc == 0) {
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
399
        TCL_Return(tcl, (char*)(item->value()->IsTodo() ? "1" : "0"));
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
400
    }
401
402
    int todo;
403
    if (Tcl_GetBoolean(tcl, argv[0], &todo) != TCL_OK) {
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
404
        TCL_Error(tcl, "invalid value for todo flag");
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
405
    }
406
    if (! check_permission(tcl, item)) return TCL_ERROR;
407
    item->value()->SetTodo(todo);
408
    trigger_item(tcl, item);
409
410
    TCL_Return(tcl, "");
411
}
412
413
static int item_is_done(ClientData c, Tcl_Interp* tcl,int argc,const char* argv[]) {
414
    Item_Tcl* item = (Item_Tcl*) c;
415
    TCL_Return(tcl, (char*)(item->value()->IsDone() ? "1" : "0"));
416
}
417
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
418
static int item_done(ClientData c, Tcl_Interp* tcl, int argc, const char** argv) {
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
419
    Item_Tcl* item = (Item_Tcl*) c;
420
    if (! check_permission(tcl, item)) return TCL_ERROR;
421
422
    int done;
423
    if (Tcl_GetBoolean(tcl, argv[0], &done) != TCL_OK) {
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
424
        TCL_Error(tcl, "invalid value for done flag");
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
425
    }
426
427
    item->value()->SetDone(done);
428
    trigger_item(tcl, item);
429
430
    TCL_Return(tcl, "");
431
}
432
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
433
static int item_alarms(ClientData c, Tcl_Interp* tcl, int argc, const char** argv) {
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
434
    Item_Tcl* item = (Item_Tcl*) c;
435
436
    Appointment* appt = item->value()->AsAppointment();
437
    if (appt == 0) {
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
438
        TCL_Error(tcl, "unknown command");
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
439
    }
440
441
    if (argc == 0) {
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
442
        intArray* alarms = appt->GetAlarms();
443
        if (alarms == 0) {
444
            TCL_Error(tcl, "no alarms");
445
        }
446
447
        // Make Tcl string out of integers
448
        // (We allocate an array one larger than necessary to avoid
449
        // zero length allocation).
450
451
        int i;
452
        char** str = new char*[alarms->size()+1];
453
        for (i = 0; i < alarms->size(); i++) {
454
            int x = alarms->slot(i);
455
456
            str[i] = new char[100];
457
            sprintf(str[i], "%d", x);
458
        }
459
        char* list = Tcl_Merge(alarms->size(), str);
460
        for (i = 0; i < alarms->size(); i++) {
461
            delete [] str[i];
462
        }
463
        delete [] str;
464
465
        Tcl_SetResult(tcl, list, TCL_DYNAMIC);
466
        return TCL_OK;
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
467
    }
468
469
    int count;
470
    const char** list;
471
    if (Tcl_SplitList(tcl, argv[0], &count, &list) != TCL_OK) {
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
472
        TCL_Error(tcl, "invalid alarm list");
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
473
    }
474
475
    intArray* alarms = new intArray(count);
476
    for (int i = 0; i < count; i++) {
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
477
        int x;
478
        if ((Tcl_GetInt(tcl, list[i], &x) != TCL_OK) || (x < 0) || (x > 60)) {
479
            Tcl_Free((char*) list);
480
            delete alarms;
481
            TCL_Error(tcl, "invalid alarm time");
482
        }
483
        alarms->append(x);
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
484
    }
485
    Tcl_Free((char*) list);
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
486
            
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
487
    if (! check_permission(tcl, item)) {
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
488
        delete alarms;
489
        return TCL_ERROR;
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
490
    }
491
492
    appt->SetAlarms(alarms);
493
    delete alarms;
494
    trigger_item(tcl, item);
495
496
    TCL_Return(tcl, "");
497
}
498
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
499
static int item_option(ClientData c, Tcl_Interp* tcl, int argc, const char** argv) {
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
500
    Item_Tcl* item = (Item_Tcl*) c;
501
502
    if (argc == 1) {
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
503
        char const* val = item->value()->GetOption(argv[0]);
504
        if (val == 0) TCL_Error(tcl, "unknown item option");
505
        Tcl_SetResult(tcl, (char*) val, TCL_VOLATILE);
506
        return TCL_OK;
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
507
    }
508
509
    if (! check_permission(tcl, item)) return TCL_ERROR;
510
    item->value()->SetOption(argv[0], argv[1]);
511
    trigger_item(tcl, item);
512
    TCL_Return(tcl, "");
513
}
514
515
static int item_doption(ClientData c, Tcl_Interp* tcl, int argc,const char* argv[]) {
516
    Item_Tcl* item = (Item_Tcl*) c;
517
518
    if (! check_permission(tcl, item)) return TCL_ERROR;
519
520
    // Check whether option exists
521
    char const* val = item->value()->GetOption(argv[0]);
522
    if (val == 0) TCL_Error(tcl, "unknown item option");
523
524
    item->value()->RemoveOption(argv[0]);
525
    trigger_item(tcl, item);
526
    TCL_Return(tcl, "");
527
}
528
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
529
static int item_empty(ClientData c, Tcl_Interp* tcl, int argc, const char** argv) {
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
530
    Item_Tcl* item = (Item_Tcl*) c;
531
    TCL_Return(tcl, (item->value()->empty()?"1":"0"));
532
}
533
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
534
static int item_repeat(ClientData c, Tcl_Interp* tcl, int argc, const char** argv) {
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
535
    Item_Tcl* item = (Item_Tcl*) c;
536
    TCL_Return(tcl,(item->value()->repeats()?"1":"0"));
537
}
538
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
539
static int item_first(ClientData c, Tcl_Interp* tcl, int argc, const char** argv) {
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
540
    Item_Tcl* item = (Item_Tcl*) c;
541
    Date d;
542
    if (! item->value()->first(d)) {
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
543
        TCL_Error(tcl, "item does not occur");
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
544
    }
545
546
    char buffer[100];
547
    sprintf(buffer, "%d", d.EpochDays());
548
    Tcl_SetResult(tcl, buffer, TCL_VOLATILE);
549
    return TCL_OK;
550
}
551
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
552
static int item_type(ClientData c, Tcl_Interp* tcl, int argc, const char** argv) {
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
553
    Item_Tcl* item = (Item_Tcl*) c;
36 by Sergei Golubchik
silly typo that prevented '$item owned' from working
554
    const char* result;
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
555
    switch (item->value()->repeat_type()) {
556
      case DateSet::None:
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
557
        result = "";
558
        break;
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
559
      case DateSet::Daily:
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
560
        result = "Daily";
561
        break;
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
562
      case DateSet::Weekly:
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
563
        result = "Weekly";
564
        break;
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
565
      case DateSet::BiWeekly:
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
566
        result = "Every Two Weeks";
567
        break;
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
568
      case DateSet::ThreeWeekly:
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
569
        result = "Every Three Weeks";
570
        break;
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
571
      case DateSet::FourWeekly:
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
572
        result = "Every Four Weeks";
573
        break;
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
574
      case DateSet::Monthly:
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
575
        result = "Monthly";
576
        break;
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
577
      case DateSet::TwoMonthly:
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
578
        result = "Every Two Months";
579
        break;
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
580
      case DateSet::ThreeMonthly:
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
581
        result = "Every Three Months";
582
        break;
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
583
      case DateSet::FourMonthly:
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
584
        result = "Every Four Months";
585
        break;
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
586
      case DateSet::SixMonthly:
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
587
        result = "Every Six Months";
588
        break;
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
589
      case DateSet::Annual:
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
590
        result = "Annual";
591
        break;
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
592
      default:
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
593
        result = "Complex";
594
        break;
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
595
    }
596
    TCL_Return(tcl, result);
597
}
598
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
599
static int item_desc(ClientData c, Tcl_Interp* tcl, int argc, const char** argv) {
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
600
    Item_Tcl* item = (Item_Tcl*) c;
601
    charArray buffer;
3 by Sergei Golubchik
apply alarm-arrow, autoflags, context-menus, expose-repeating-events patches
602
603
    if (argc == 0)
604
        item->value()->describe(&buffer);
605
    else
606
      if (argc == 1 && strcmp(argv[0], "-terse") == 0)
607
        item->value()->describe_terse(&buffer);
608
      else
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
609
        TCL_Error(tcl, "invalid argument(s)");
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
610
    buffer.append('\0');
611
    Tcl_SetResult(tcl, buffer.as_pointer(), TCL_VOLATILE);
612
    return TCL_OK;
613
}
614
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
615
static int item_cont(ClientData c, Tcl_Interp* tcl, int argc, const char** argv) {
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
616
    Item_Tcl* item = (Item_Tcl*) c;
617
    int dateDays;
618
    if (Tcl_GetInt(tcl, argv[0], &dateDays) != TCL_OK) {
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
619
        TCL_Error(tcl, "invalid date");
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
620
    }
621
    Date date(dateDays);
622
    TCL_Return(tcl, (item->value()->contains(date)?"1":"0"));
623
}
624
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
625
static int item_next(ClientData c, Tcl_Interp* tcl, int argc, const char** argv) {
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
626
    Item_Tcl* item = (Item_Tcl*) c;
627
    int dateDays;
628
    if (Tcl_GetInt(tcl, argv[0], &dateDays) != TCL_OK) {
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
629
        TCL_Error(tcl, "invalid date");
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
630
    }
631
    Date date(dateDays);
632
    Date next;
633
    if (! item->value()->next(date, next)) {
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
634
        TCL_Error(tcl, "no next occurrence for item");
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
635
    }
636
637
    char buffer[100];
638
    sprintf(buffer, "%d", next.EpochDays());
639
    Tcl_SetResult(tcl, buffer, TCL_VOLATILE);
640
    return TCL_OK;
641
}
642
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
643
static int item_range(ClientData c, Tcl_Interp* tcl, int argc, const char** argv) {
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
644
    Item_Tcl* item = (Item_Tcl*) c;
645
646
    Date s, f;
11 by Sergei Golubchik
timezone support: lots of changes
647
    if (item->value()->range(s, f)) {
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
648
        char buffer[100];
649
        sprintf(buffer, "%d", s.EpochDays());
650
        if (Tcl_SetVar(tcl, argv[0], buffer, 0) == NULL)
651
            TCL_Error(tcl, "could not set range start variable");
652
        sprintf(buffer, "%d", f.EpochDays());
653
        if (Tcl_SetVar(tcl, argv[1], buffer, 0) == NULL)
654
            TCL_Error(tcl, "could not set range finish variable");
655
        TCL_Return(tcl, "1");
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
656
    }
657
    else {
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
658
        TCL_Return(tcl, "0");
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
659
    }
660
}
661
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
662
static int item_date(ClientData c, Tcl_Interp* tcl, int argc, const char** argv) {
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
663
    Item_Tcl* item = (Item_Tcl*) c;
664
    int dateDays;
665
    if (Tcl_GetInt(tcl, argv[0], &dateDays) != TCL_OK) {
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
666
        TCL_Error(tcl, "invalid date");
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
667
    }
668
    Date date(dateDays);
669
    if (! check_permission(tcl, item)) return TCL_ERROR;
670
    item->value()->set_date(date);
671
    trigger_item(tcl, item);
672
673
    TCL_Return(tcl, "");
674
}
675
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
676
static int item_start(ClientData c, Tcl_Interp* tcl, int argc, const char** argv) {
677
    Item_Tcl* item = (Item_Tcl*) c;
678
    int dateDays;
679
680
    if (Tcl_GetInt(tcl, argv[0], &dateDays) != TCL_OK) {
681
        TCL_Error(tcl, "invalid date");
682
    }
683
684
    Date date(dateDays);
685
    if (! check_permission(tcl, item)) return TCL_ERROR;
11 by Sergei Golubchik
timezone support: lots of changes
686
    item->value()->set_start(date);
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
687
    trigger_item(tcl, item);
688
689
    TCL_Return(tcl, "");
690
}
691
692
static int item_finish(ClientData c, Tcl_Interp* tcl, int argc, const char** argv) {
693
    Item_Tcl* item = (Item_Tcl*) c;
694
    int dateDays;
695
696
    if (Tcl_GetInt(tcl, argv[0], &dateDays) != TCL_OK) {
697
        TCL_Error(tcl, "invalid date");
698
    }
699
700
    Date date(dateDays);
701
    if (! check_permission(tcl, item)) return TCL_ERROR;
11 by Sergei Golubchik
timezone support: lots of changes
702
    item->value()->set_finish(date);
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
703
    trigger_item(tcl, item);
704
705
    TCL_Return(tcl, "");
706
}
707
708
static int item_ondel(ClientData c, Tcl_Interp* tcl, int argc, const char** argv) {
709
    Item_Tcl* item = (Item_Tcl*) c;
710
    int dateDays;
711
    if (Tcl_GetInt(tcl, argv[0], &dateDays) != TCL_OK) {
712
        TCL_Error(tcl, "invalid date");
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
713
    }
714
    Date date(dateDays);
715
    if (! check_permission(tcl, item)) return TCL_ERROR;
716
    item->value()->delete_occurrence(date);
717
    trigger_item(tcl, item);
718
719
    TCL_Return(tcl, "");
720
}
721
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
722
static int item_dayr(ClientData c, Tcl_Interp* tcl, int argc, const char** argv) {
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
723
    Item_Tcl* item = (Item_Tcl*) c;
724
725
    int interval;
726
    if ((Tcl_GetInt(tcl, argv[0], &interval) != TCL_OK) || (interval < 1)) {
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
727
        TCL_Error(tcl, "invalid interval");
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
728
    }
729
730
    int anchorDays;
731
    if (Tcl_GetInt(tcl, argv[1], &anchorDays) != TCL_OK) {
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
732
        TCL_Error(tcl, "invalid anchor date");
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
733
    }
734
    Date anchor(anchorDays);
735
736
    if (! check_permission(tcl, item)) return TCL_ERROR;
737
    item->value()->set_day_based_repeat(interval, anchor);
738
    trigger_item(tcl, item);
739
740
    TCL_Return(tcl, "");
741
}
742
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
743
static int item_monthr(ClientData c, Tcl_Interp* tcl, int argc, const char** argv) {
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
744
    Item_Tcl* item = (Item_Tcl*) c;
745
746
    int interval;
747
    if ((Tcl_GetInt(tcl, argv[0], &interval) != TCL_OK) || (interval < 1)) {
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
748
        TCL_Error(tcl, "invalid interval");
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
749
    }
750
751
    int anchorDays;
752
    if (Tcl_GetInt(tcl, argv[1], &anchorDays) != TCL_OK) {
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
753
        TCL_Error(tcl, "invalid anchor date");
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
754
    }
755
    Date anchor(anchorDays);
756
757
    if (! check_permission(tcl, item)) return TCL_ERROR;
758
    item->value()->set_month_based_repeat(interval, anchor);
759
    trigger_item(tcl, item);
760
761
    TCL_Return(tcl, "");
762
}
763
764
// Helper routine for "set_monthly" interfaces.
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
765
// modifies     "n", "anchor", "interval".
766
// effects      Parses "n", "anchor" and "interval" from the command
767
//              arguments.  Returns TCL_OK iff successful.  If "anchor"
768
//              and "interval" are not specified in the command arguments,
769
//              then "anchor" is set to today and "interval" is set to "1".
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
770
static int parse_month_args(Tcl_Interp* tcl, int argc, const char* argv[],
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
771
                            int& n, Date& anchor, int& interval)
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
772
{
773
    if ((argc != 1) && (argc != 3)) TCL_Error(tcl,"wrong number of arguments");
774
    if ((Tcl_GetInt(tcl, argv[0], &n) != TCL_OK) || (n < 1))
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
775
        TCL_Error(tcl, "invalid count");
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
776
777
    // Get anchor and interval
778
    if (argc == 1) {
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
779
        anchor = Date::Today();
780
        interval = 1;
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
781
    }
782
    else {
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
783
        int anchorDays;
784
        if (Tcl_GetInt(tcl, argv[1], &anchorDays) != TCL_OK)
785
            TCL_Error(tcl, "invalid anchor date");
786
        anchor = Date(anchorDays);
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
787
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
788
        if ((Tcl_GetInt(tcl, argv[2], &interval) != TCL_OK) || (interval < 1))
789
            TCL_Error(tcl, "invalid interval");
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
790
    }
791
792
    return TCL_OK;
793
}
794
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
795
static int item_mday(ClientData c, Tcl_Interp* tcl, int argc, const char** argv) {
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
796
    Item_Tcl* item = (Item_Tcl*) c;
797
798
    int n, interval;
799
    Date anchor;
800
    if (parse_month_args(tcl, argc, argv, n, anchor, interval) != TCL_OK)
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
801
        return TCL_ERROR;
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
802
803
    if (! check_permission(tcl, item)) return TCL_ERROR;
804
    item->value()->set_monthly_by_days(n, interval, anchor, 0);
805
    trigger_item(tcl, item);
806
807
    TCL_Return(tcl, "");
808
}
809
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
810
static int item_mlday(ClientData c, Tcl_Interp* tcl, int argc, const char** argv) {
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
811
    Item_Tcl* item = (Item_Tcl*) c;
812
813
    int n, interval;
814
    Date anchor;
815
    if (parse_month_args(tcl, argc, argv, n, anchor, interval) != TCL_OK)
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
816
        return TCL_ERROR;
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
817
818
    if (! check_permission(tcl, item)) return TCL_ERROR;
819
    item->value()->set_monthly_by_days(n, interval, anchor, 1);
820
    trigger_item(tcl, item);
821
822
    TCL_Return(tcl, "");
823
}
824
825
static int item_mworkday(ClientData c, Tcl_Interp* tcl,
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
826
                         int argc, const char** argv) {
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
827
    Item_Tcl* item = (Item_Tcl*) c;
828
829
    int n, interval;
830
    Date anchor;
831
    if (parse_month_args(tcl, argc, argv, n, anchor, interval) != TCL_OK)
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
832
        return TCL_ERROR;
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
833
834
    if (! check_permission(tcl, item)) return TCL_ERROR;
835
    item->value()->set_monthly_by_workdays(n, interval, anchor, 0);
836
    trigger_item(tcl, item);
837
838
    TCL_Return(tcl, "");
839
}
840
841
static int item_mlworkday(ClientData c, Tcl_Interp* tcl,
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
842
                          int argc, const char** argv) {
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
843
    Item_Tcl* item = (Item_Tcl*) c;
844
845
    int n, interval;
846
    Date anchor;
847
    if (parse_month_args(tcl, argc, argv, n, anchor, interval) != TCL_OK)
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
848
        return TCL_ERROR;
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
849
850
    if (! check_permission(tcl, item)) return TCL_ERROR;
851
    item->value()->set_monthly_by_workdays(n, interval, anchor, 1);
852
    trigger_item(tcl, item);
853
854
    TCL_Return(tcl, "");
855
}
856
857
static int item_mweekday(ClientData c, Tcl_Interp* tcl,
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
858
                         int argc, const char** argv) {
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
859
    Item_Tcl* item = (Item_Tcl*) c;
860
861
    int wday;
862
    if ((Tcl_GetInt(tcl,argv[0],&wday) != TCL_OK) || (wday < 1) || (wday > 7))
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
863
        TCL_Error(tcl, "invalid weekday");
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
864
    WeekDay w = WeekDay::First() + (wday - 1);
865
866
    int n, interval;
867
    Date anchor;
868
    if (parse_month_args(tcl, argc-1, argv+1, n, anchor, interval) != TCL_OK)
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
869
        return TCL_ERROR;
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
870
871
    if (! check_permission(tcl, item)) return TCL_ERROR;
872
    item->value()->set_monthly_by_weeks(n, w, interval, anchor, 0);
873
    trigger_item(tcl, item);
874
875
    TCL_Return(tcl, "");
876
}
877
878
static int item_mlweekday(ClientData c, Tcl_Interp* tcl,
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
879
                          int argc, const char** argv) {
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
880
    Item_Tcl* item = (Item_Tcl*) c;
881
882
    int wday;
883
    if ((Tcl_GetInt(tcl,argv[0],&wday) != TCL_OK) || (wday < 1) || (wday > 7))
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
884
        TCL_Error(tcl, "invalid weekday");
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
885
    WeekDay w = WeekDay::First() + (wday - 1);
886
887
    int n, interval;
888
    Date anchor;
889
    if (parse_month_args(tcl, argc-1, argv+1, n, anchor, interval) != TCL_OK)
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
890
        return TCL_ERROR;
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
891
892
    if (! check_permission(tcl, item)) return TCL_ERROR;
893
    item->value()->set_monthly_by_weeks(n, w, interval, anchor, 1);
894
    trigger_item(tcl, item);
895
896
    TCL_Return(tcl, "");
897
}
898
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
899
static int item_wdays(ClientData c, Tcl_Interp* tcl, int argc, const char** argv) {
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
900
    Item_Tcl* item = (Item_Tcl*) c;
901
902
    /* Collect weekdays */
903
    int i;
904
    SmallIntSet set;
905
    set.Clear();
906
    for (i = 0; i < argc; i++) {
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
907
        int weekday;
908
        if ((Tcl_GetInt(tcl, argv[i], &weekday) != TCL_OK) ||
909
            (weekday < 1) ||
910
            (weekday > 7)) {
911
            TCL_Error(tcl, "invalid weekday");
912
        }
913
        set.Insert(weekday);
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
914
    }
915
916
    if (! check_permission(tcl, item)) return TCL_ERROR;
917
918
    /* Repeat every month */
919
    SmallIntSet months;
920
    months.Clear();
921
    for (i = 1; i <= 12; i++) {
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
922
        months.Insert(i);
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
923
    }
924
925
    item->value()->set_week_set(set, months);
926
    trigger_item(tcl, item);
927
928
    TCL_Return(tcl, "");
929
}
930
931
static int check_permission(Tcl_Interp* tcl, Item_Tcl* item) {
932
    CalFile* file = item->calendar();
933
    if (file == 0) return 1;
934
935
    if (file->GetCalendar()->ReadOnly()) {
36 by Sergei Golubchik
silly typo that prevented '$item owned' from working
936
        Tcl_SetResult(tcl, const_cast<char*>("item is in readonly calendar"),
937
                TCL_STATIC);
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
938
        return 0;
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
939
    }
940
941
    file->Modified();
942
    return 1;
943
}
944
945
static void trigger_item(Tcl_Interp* tcl, Item_Tcl* item, char const* t) {
946
    if (item->calendar() != 0)
9 by Sergei Golubchik
cleanup, retab. "item timezone" in tcl
947
        trigger(tcl, t, item->handle());
1 by Sergei Golubchik
initial checkin, as of ical-2.3.3
948
}