Files
cdesktop/cde/programs/dtcm/dtcm/browser.c
2012-03-10 18:58:32 +00:00

1745 lines
50 KiB
C

/*
* CDE - Common Desktop Environment
*
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
*
* These libraries and programs are free software; you can
* redistribute them and/or modify them under the terms of the GNU
* Lesser General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* These libraries and programs are distributed in the hope that
* they will be useful, but WITHOUT ANY WARRANTY; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with these librararies and programs; if not, write
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
* Floor, Boston, MA 02110-1301 USA
*/
/* $TOG: browser.c /main/10 1999/02/23 09:42:01 mgreess $ */
/*
* (c) Copyright 1993, 1994 Hewlett-Packard Company
* (c) Copyright 1993, 1994 International Business Machines Corp.
* (c) Copyright 1993, 1994 Novell, Inc.
* (c) Copyright 1993, 1994 Sun Microsystems, Inc.
*/
#include <EUSCompat.h>
#include <stdio.h>
#include <stdlib.h>
#include <csa.h>
#include <X11/Xlib.h>
#include <Xm/Xm.h>
#include <Xm/DrawingA.h>
#include <Xm/Form.h>
#include <Xm/LabelG.h>
#include <Xm/List.h>
#include <Xm/DialogS.h>
#include <Xm/PanedW.h>
#include <Xm/Protocols.h>
#include <Xm/PushBG.h>
#include <Xm/RowColumn.h>
#include <Xm/Scale.h>
#include <Xm/SeparatoG.h>
#include <Xm/Text.h>
#include <Xm/ToggleBG.h>
#include <Xm/SashP.h>
#include <Dt/HourGlass.h>
#include <Tt/tttk.h>
#include "getdate.h"
#include "calendar.h"
#include "util.h"
#include "misc.h"
#include "timeops.h"
#include "browser.h"
#include "blist.h"
#include "format.h"
#include "datefield.h"
#include "props.h"
#include "props_pu.h"
#include "editor.h"
#include "group_editor.h"
#include "select.h"
#include "help.h"
#ifdef FNS
#include "cmfns.h"
#endif
#define DATESIZ 40
extern int debug;
static void mb_resize_proc(Widget, XtPointer, XtPointer);
static void cancel_cb(Widget, XtPointer, XtPointer);
static void popup_cb(Widget, XtPointer, XtPointer);
static void init_browser(Calendar *);
static void bcanvas_repaint(Widget, XtPointer, XtPointer);
static void bcanvas_event(Widget, XtPointer, XtPointer);
static void goto_date_cb(Widget, XtPointer, XtPointer);
static void browselist_from_browser(Widget, XtPointer, XtPointer);
static void gotomenu_cb(Widget, XtPointer, XtPointer);
static void schedule_cb(Widget, XtPointer, XtPointer);
static void mail_cb(Widget, XtPointer, XtPointer);
static void mb_box_notify(Widget, XtPointer, XtPointer);
static void mb_update_handler(CSA_session_handle, CSA_flags, CSA_buffer,
CSA_buffer, CSA_extension *);
extern void scrub_attr_list(Dtcm_appointment *);
static void
mb_init_array(Browser *b, int begin, int end) {
b->segs_in_array = BOX_SEG * (end - begin) * 7;
b->multi_array = (char*)ckalloc(b->segs_in_array);
}
static void
reset_ticks(Calendar *c, Boolean use_sel_idx) {
int beg, end;
Props *p = (Props *)c->properties;
Browser *b = (Browser*)c->browser;
beg = get_int_prop(p, CP_DAYBEGIN);
end = get_int_prop(p, CP_DAYEND);
if (b->date <= get_bot()) {
b->date = get_bot();
if (b->col_sel > 0)
b->col_sel = b->col_sel - 4;
}
if ((b->begin_week_tick = first_dow(b->date)) < get_bot())
b->begin_week_tick = get_bot();
if (use_sel_idx) {
b->begin_day_tick =
next_ndays(b->begin_week_tick, b->col_sel);
b->begin_hr_tick =
next_nhours(b->begin_day_tick, beg + b->row_sel);
} else {
b->begin_day_tick = lowerbound(b->date);
b->begin_hr_tick = next_nhours(b->begin_day_tick, beg);
}
b->end_day_tick = upperbound(b->begin_day_tick);
b->end_hr_tick = next_nhours(b->begin_hr_tick, 1);
}
extern void
br_display(Calendar *c) {
int i, *pos_list = NULL, pos_cnt;
Browser *b = (Browser *)c->browser;
BlistData *bd;
Browselist *bl = (Browselist *)c->browselist;
void mb_update_array();
if (!b)
return;
for (i = 0; i < b->segs_in_array; i++)
b->multi_array[i] = 0;
b->add_to_array = True;
XmListGetSelectedPos(b->browse_list, &pos_list, &pos_cnt);
for (i = 0; i < pos_cnt; i++) {
bd = (BlistData *)CmDataListGetData(bl->blist_data,
pos_list[i]);
destroy_paint_cache(bd->cache, bd->cache_size);
bd->cache = NULL;
bd->cache_size = 0;
if (bd)
mb_update_array(bd->name, c);
}
if (pos_list)
XtFree((XtPointer)pos_list);
mb_refresh_canvas(b, c);
}
static void
invalid_date_msg(Calendar *c, Widget widget)
{
Browser *b = (Browser*)c->browser;
char *title = XtNewString(catgets(c->DT_catd, 1, 1070,
"Calendar : Error - Compare Calendars"));
char *text = XtNewString(catgets(c->DT_catd, 1, 20,
"Invalid Date In Go To Field."));
char *ident = XtNewString(catgets(c->DT_catd, 1, 95, "Continue"));
dialog_popup(b->frame,
DIALOG_TITLE, title,
DIALOG_TEXT, text,
BUTTON_IDENT, 1, ident,
DIALOG_IMAGE, ((Props_pu *)c->properties_pu)->xm_error_pixmap,
NULL);
XtFree(ident);
XtFree(text);
XtFree(title);
}
void
set_entry_date(Calendar *c) {
char *date = NULL;
Browser *b;
Props *p;
OrderingType ot;
SeparatorType st;
Tick tick;
b = (Browser*)c->browser;
p = (Props*)c->properties;
ot = get_int_prop(p, CP_DATEORDERING);
st = get_int_prop(p, CP_DATESEPARATOR);
date = get_date_from_widget(c->view->date, b->datetext, ot, st);
if (date == NULL ) {
invalid_date_msg(c, b->message_text);
return;
}
tick = cm_getdate(date, NULL);
if (!timeok(tick)) {
invalid_date_msg(c, b->message_text);
return;
}
b->date = tick;
reset_ticks(c, False);
br_display(c);
}
/*
* A note about the browser:
* This custom dialog is built using two nested PanedWindowWidgets.
* The first child of the outer pane is itself paned (the other
* child is the dialog's action area). The inner pane is movable
* to allow users to reproportion the calendar list versus the free
* time chart. Most of the useful widget handles are stored in the
* Browser structure allocated and returned from here.
*/
extern void
make_browser(Calendar *c)
{
Browser *b;
Props *p = (Props*) c->properties;
Widget separator1;
Dimension w, h, height;
XmString xmstr;
XmString goto_label, prev_week, this_week, next_week, prev_month, next_month;
int num_children;
Widget *children;
OrderingType ord_t = get_int_prop(p, CP_DATEORDERING);
SeparatorType sep_t = get_int_prop(p, CP_DATESEPARATOR);
char buf[BUFSIZ];
Widget text_field_form;
int outpane_width, outpane_height;
int upform_min,item_count;
char *title;
if (c->browser == NULL) {
c->browser = (caddr_t)ckalloc(sizeof(Browser));
b = (Browser*)c->browser;
}
else
b = (Browser*)c->browser;
b->date = c->view->date;
mb_init_array(b, get_int_prop(p, CP_DAYBEGIN), get_int_prop(p, CP_DAYEND));
b->current_selection = (caddr_t) ckalloc(sizeof(Selection));
/* if the screen is small adjust the max size for width and height
* so the shell can be moved up and down using window facility
*/
if ((WidthOfScreen(XtScreen(c->frame)) < 360) ||
(HeightOfScreen(XtScreen(c->frame)) < 600 ))
{
outpane_width = 300;
outpane_height = 430;
item_count = 3;
upform_min = 120;
}
else
{
outpane_width = 360;
outpane_height = 600;
item_count = 8;
upform_min = 200;
}
title = XtNewString(catgets(c->DT_catd, 1, 1010,
"Calendar : Compare Calendars"));
b->frame = XtVaCreatePopupShell("frame",
xmDialogShellWidgetClass, c->frame,
XmNtitle, title,
XmNallowShellResize, True,
XmNmappedWhenManaged, False,
XmNdeleteResponse, XmDO_NOTHING,
NULL);
XtFree(title);
XtAddCallback(b->frame, XmNpopupCallback, popup_cb, (XtPointer)c);
/*
* Create the outer pane, whose upper part will hold a
* nested pane, and whose lower part will hold the actions
* and message area
*/
b->outer_pane = XtVaCreateManagedWidget("outerPane",
xmPanedWindowWidgetClass, b->frame,
XmNsashHeight, 1,
XmNsashWidth, 1,
XmNwidth, outpane_width,
XmNheight, outpane_height,
NULL);
b->inner_pane = XtVaCreateManagedWidget("innerPane",
xmPanedWindowWidgetClass, b->outer_pane,
XmNallowResize, True,
NULL);
b->upper_form = XtVaCreateManagedWidget("upperForm",
xmFormWidgetClass, b->inner_pane,
XmNallowResize, True,
XmNpaneMinimum, upform_min,
NULL);
xmstr = XmStringCreateLocalized(catgets(c->DT_catd, 1, 22, "Browse Menu Items"));
b->list_label = XtVaCreateWidget("browseMenuLabel",
xmLabelGadgetClass, b->upper_form,
XmNlabelString, xmstr,
XmNleftAttachment, XmATTACH_FORM,
XmNtopAttachment, XmATTACH_FORM,
XmNtopOffset, 10,
NULL);
XmStringFree(xmstr);
xmstr = XmStringCreateLocalized(catgets(c->DT_catd, 1, 21, "Edit List..."));
b->edit_list = XtVaCreateWidget("editList",
xmPushButtonGadgetClass, b->upper_form,
XmNlabelString, xmstr,
XmNtopAttachment, XmATTACH_FORM,
XmNrightAttachment, XmATTACH_FORM,
XmNleftAttachment, XmATTACH_WIDGET,
XmNleftWidget, b->list_label,
XmNleftOffset, 80,
NULL);
XmStringFree(xmstr);
XtAddCallback(b->edit_list, XmNactivateCallback,
browselist_from_browser, (XtPointer)c);
b->browse_list = (Widget)XmCreateScrolledList(b->upper_form,
"browseList", NULL, 0);
XtAddCallback(b->browse_list,
XmNmultipleSelectionCallback, mb_box_notify, (XtPointer)c);
XtAddCallback(b->browse_list,
XmNdefaultActionCallback, mb_box_notify, (XtPointer)c);
XtVaSetValues(b->browse_list,
XmNselectionPolicy, XmMULTIPLE_SELECT,
XmNvisibleItemCount, item_count,
NULL);
b->browse_list_sw = XtParent(b->browse_list);
XtVaSetValues(b->browse_list_sw,
XmNtopAttachment, XmATTACH_WIDGET,
XmNtopWidget, b->edit_list,
XmNleftAttachment, XmATTACH_FORM,
XmNleftOffset, 20,
XmNrightAttachment, XmATTACH_FORM,
XmNrightOffset, 20,
XmNbottomAttachment, XmATTACH_FORM,
XmNvisualPolicy, XmVARIABLE,
NULL);
/*
* Create the "go to" option menu for time navigation
*/
prev_week =
XmStringCreateLocalized(catgets(c->DT_catd, 1, 23, "Prev Week"));
this_week =
XmStringCreateLocalized(catgets(c->DT_catd, 1, 24, "This Week"));
next_week =
XmStringCreateLocalized(catgets(c->DT_catd, 1, 25, "Next Week"));
prev_month =
XmStringCreateLocalized(catgets(c->DT_catd, 1, 26, "Prev Month"));
next_month =
XmStringCreateLocalized(catgets(c->DT_catd, 1, 27, "Next Month"));
goto_label =
XmStringCreateLocalized(catgets(c->DT_catd, 1, 28, "Go To:"));
/*
* remember - this returns a RowColumn widget!
*/
b->gotomenu = XmVaCreateSimpleOptionMenu(b->upper_form,
"goToOptionMenu", goto_label, NULL, 0, gotomenu_cb,
XmVaPUSHBUTTON, prev_week, NULL, NULL, NULL,
XmVaPUSHBUTTON, this_week, NULL, NULL, NULL,
XmVaPUSHBUTTON, next_week, NULL, NULL, NULL,
XmVaPUSHBUTTON, prev_month, NULL, NULL, NULL,
XmVaPUSHBUTTON, next_month, NULL, NULL, NULL,
XmNbottomAttachment, XmATTACH_FORM,
XmNbottomOffset, 5,
XmNleftAttachment, XmATTACH_FORM,
XmNleftOffset, 20,
XmNuserData, c,
XmNnavigationType, XmTAB_GROUP,
NULL);
XmStringFree(prev_week);
XmStringFree(this_week);
XmStringFree(next_week);
XmStringFree(prev_month);
XmStringFree(next_month);
XmStringFree(goto_label);
text_field_form = XtVaCreateManagedWidget("text_field_form",
xmFormWidgetClass, b->upper_form,
XmNbottomAttachment, XmATTACH_FORM,
XmNbottomOffset, 5,
XmNleftAttachment, XmATTACH_WIDGET,
XmNleftWidget, b->gotomenu,
NULL);
b->datetext = XtVaCreateWidget("dateText",
xmTextWidgetClass, text_field_form,
NULL);
XtAddCallback(b->datetext, XmNactivateCallback, goto_date_cb,
(XtPointer)c);
/*
* We can now calc the proper offset for the bottom of scrolled
* list - allow for a small margin above and below the text field.
*/
XtVaGetValues(b->datetext, XmNheight, &height, NULL);
XtVaSetValues(b->browse_list_sw, XmNbottomOffset, (height + 10), NULL);
b->lower_form = XtVaCreateManagedWidget("lowerForm",
xmFormWidgetClass, b->inner_pane,
XmNallowResize, True,
XmNpaneMinimum, 200,
XmNtraversalOn, False,
NULL);
/*
* create drawing area for chart
*/
b->canvas = XtVaCreateManagedWidget("canvas", xmDrawingAreaWidgetClass,
b->lower_form,
XmNtopAttachment, XmATTACH_FORM,
XmNleftAttachment, XmATTACH_FORM,
XmNrightAttachment, XmATTACH_FORM,
XmNbottomAttachment, XmATTACH_FORM,
XmNtraversalOn, False,
NULL);
b->xcontext = gr_create_xcontext(c, b->canvas, gr_color,
c->xcontext->app);
XtVaSetValues(b->canvas, XmNheight, 300, NULL);
XtAddCallback(b->canvas, XmNresizeCallback, mb_resize_proc, (XtPointer)c);
XtAddCallback(b->canvas, XmNinputCallback, bcanvas_event, (XtPointer)c);
XtAddCallback(b->canvas, XmNexposeCallback, bcanvas_repaint, (XtPointer)c);
/*
* Create action area of the dialog
*/
b->action = XtVaCreateWidget("action",
xmFormWidgetClass, b->outer_pane,
NULL);
xmstr = XmStringCreateLocalized(catgets(c->DT_catd, 1, 29, "Schedule..."));
b->schedule = XtVaCreateWidget("schedule",
xmPushButtonGadgetClass, b->action,
XmNlabelString, xmstr,
XmNtopAttachment, XmATTACH_FORM,
XmNleftAttachment, XmATTACH_FORM,
NULL);
XmStringFree(xmstr);
XtAddCallback(b->schedule, XmNactivateCallback, schedule_cb, (XtPointer)c);
xmstr = XmStringCreateLocalized(catgets(c->DT_catd, 1, 30, "Mail..."));
b->mail = XtVaCreateWidget("mail",
xmPushButtonGadgetClass, b->action,
XmNlabelString, xmstr,
XmNleftAttachment, XmATTACH_WIDGET,
XmNleftWidget, b->schedule,
XmNtopAttachment, XmATTACH_FORM,
NULL);
XmStringFree(xmstr);
XtAddCallback(b->mail, XmNactivateCallback, mail_cb, (XtPointer)c);
XtSetSensitive(b->mail, c->tt_procid == NULL ? False : True);
xmstr = XmStringCreateLocalized(catgets(c->DT_catd, 1, 923, "Cancel"));
b->cancel = XtVaCreateWidget("cancel",
xmPushButtonGadgetClass, b->action,
XmNlabelString, xmstr,
XmNleftAttachment, XmATTACH_WIDGET,
XmNleftWidget, b->mail,
XmNtopAttachment, XmATTACH_FORM,
NULL);
XmStringFree(xmstr);
XtAddCallback(b->cancel, XmNactivateCallback, cancel_cb, (XtPointer)c);
xmstr = XmStringCreateLocalized(catgets(c->DT_catd, 1, 77, "Help"));
b->helpbutton = XtVaCreateWidget("help",
xmPushButtonGadgetClass, b->action,
XmNlabelString, xmstr,
XmNleftAttachment, XmATTACH_WIDGET,
XmNleftWidget, b->cancel,
XmNtopAttachment, XmATTACH_FORM,
NULL);
XmStringFree(xmstr);
XtAddCallback(b->helpbutton, XmNactivateCallback,
(XtCallbackProc)help_cb, COMPARE_CALS_HELP_BUTTON);
XtAddCallback(b->action, XmNhelpCallback,
(XtCallbackProc)help_cb, (XtPointer) COMPARE_CALS_HELP_BUTTON);
b->message_text = XtVaCreateWidget("message",
xmLabelGadgetClass, b->action,
XmNtopAttachment, XmATTACH_WIDGET,
XmNtopWidget, b->schedule,
XmNleftAttachment, XmATTACH_FORM,
XmNrightAttachment, XmATTACH_FORM,
XmNbottomAttachment, XmATTACH_FORM,
XmNalignment, XmALIGNMENT_BEGINNING,
NULL);
/*
* Fix the size of action area
*/
XtVaGetValues(b->schedule, XmNheight, &height, NULL);
XtVaSetValues(b->action,
XmNpaneMaximum, (2*height),
XmNpaneMinimum, (2*height),
NULL);
XtVaGetValues(b->outer_pane,
XmNchildren, &children,
XmNnumChildren, &num_children,
NULL);
while (num_children-- > 0) {
if (XmIsSash(children[num_children])) {
XtVaSetValues(children[num_children], XmNtraversalOn, False, NULL);
}
}
XtManageChild(b->edit_list);
XtManageChild(b->list_label);
XtManageChild(b->browse_list);
XtManageChild(b->gotomenu);
XtManageChild(b->datetext);
XtManageChild(b->schedule);
XtManageChild(b->mail);
XtManageChild(b->cancel);
XtManageChild(b->helpbutton);
XtManageChild(b->message_text);
XtManageChild(b->action);
gr_init(b->xcontext, b->canvas);
format_tick(b->date, ord_t, sep_t, buf);
XmTextSetString(b->datetext, buf);
set_entry_date(c);
/*
* set default button for dialog
*/
XtVaSetValues(b->action, XmNdefaultButton, b->schedule, NULL);
XtVaSetValues(b->upper_form, XmNdefaultButton, b->schedule, NULL);
/* We don't want a ``return'' in the text field to trigger the
* default action so we create a form around the text field and
* designate the text-field as the default button.
*/
XtVaSetValues(text_field_form, XmNdefaultButton, b->datetext, NULL);
XtVaSetValues(b->action, XmNcancelButton, b->cancel, NULL);
XtVaSetValues(b->upper_form, XmNcancelButton, b->cancel, NULL);
XmProcessTraversal(b->schedule, XmTRAVERSE_CURRENT);
XtVaSetValues(b->action, XmNinitialFocus, b->schedule, NULL);
XtVaSetValues(b->frame, XmNmappedWhenManaged, True, NULL);
XtRealizeWidget(b->frame);
/*
* Enforce a "reasonable" size.
* too narrow and the buttons are erased
* too short and the chart will look smashed
XtVaSetValues(b->frame,
XmNminWidth, 300,
XmNminHeight, 600,
NULL);
*/
/*
* Add a WM protocol callback to handle the
* case where the window manager closes the dialog.
* Pass the calendar ptr through client data to allow
* the callback to get at the shell and destroy it.
*/
setup_quit_handler(b->frame, cancel_cb, (XtPointer)c);
init_browser(c);
}
static void
browselist_from_browser(Widget w, XtPointer client_data, XtPointer call_data)
{
Calendar *c = (Calendar *)client_data;
Browselist *bl;
bl = (Browselist *)c->browselist;
show_browselist(c);
}
static void
goto_date_cb(Widget w, XtPointer client_data, XtPointer call_data)
{
Calendar *c = (Calendar *)client_data;
Browser *b;
set_entry_date(c);
}
static void
goto_unit(Calendar *c, int item_no)
{
char buf[DATESIZ];
Browser *b;
Props *p;
OrderingType ord_t;
SeparatorType sep_t;
b = (Browser*)c->browser;
p = (Props*)c->properties;
switch (item_no + 1) {
case MB_PREVWEEK:
b->date = last_ndays(b->date, 7);
break;
case MB_THISWEEK:
b->date = now();
break;
case MB_NEXTWEEK:
b->date = next_ndays(b->date, 7);
break;
case MB_NEXTMONTH:
b->date = next_ndays(b->date, 28);
break;
case MB_PREVMONTH:
b->date = last_ndays(b->date, 28);
break;
default:
b->date = now();
break;
}
reset_ticks(c, False);
ord_t = get_int_prop(p, CP_DATEORDERING);
sep_t = get_int_prop(p, CP_DATESEPARATOR);
format_tick(b->date, ord_t, sep_t, buf);
XmTextSetString(b->datetext, buf);
br_display(c);
}
static void
bcanvas_repaint(Widget w, XtPointer client_data, XtPointer call_data)
{
Calendar *c = (Calendar *)client_data;
Browser *b;
XRectangle clip;
XEvent ev;
new_XContext *xc;
XmDrawingAreaCallbackStruct *cbs = (XmDrawingAreaCallbackStruct*)call_data;
/* repair in full on final exposure (crude optimization scheme) */
if (cbs->event->xexpose.count != 0)
return;
b = (Browser *)c->browser;
if ((xc = b->xcontext)==NULL)
return;
clip.x = 0;
clip.y = 0;
XtVaGetValues(w, XmNwidth, &clip.width, XmNy, &clip.height, NULL);
gr_set_clip_rectangles(xc, 0, 0, &clip, 1, Unsorted);
gr_clear_area(b->xcontext, 0, 0, b->canvas_w, b->canvas_h);
gr_clear_clip_rectangles(xc);
mb_refresh_canvas(b, c);
XSync(XtDisplay(b->canvas), 0);
}
static void
mb_display_footermess(Browser *b, Calendar *c)
{
int num_cals;
char buf[BUFSIZ];
XtVaGetValues(b->browse_list, XmNselectedItemCount, &num_cals, NULL);
if (num_cals == 1)
sprintf(buf, "%d %s", num_cals,
catgets(c->DT_catd, 1, 31, "Calendar Displayed"));
else
sprintf(buf, "%d %s", num_cals,
catgets(c->DT_catd, 1, 32, "Calendars Displayed"));
set_message(b->message_text, buf);
}
static void
browser_to_gaccess_list(Calendar *c) {
int i, pos_cnt, *pos_list = NULL;
GEditor *ge = (GEditor *)c->geditor;
Browser *b = (Browser *)c->browser;
BlistData *bd;
Browselist *bl = (Browselist *)c->browselist;
/*
* Add selected items to list box in group appt editor
*/
XmListGetSelectedPos(b->browse_list, &pos_list, &pos_cnt);
for (i = 0; i < pos_cnt; i++) {
if (bd = (BlistData *)CmDataListGetData(bl->blist_data,
pos_list[i]))
add_to_gaccess_list(bd->name, bd->cal_handle,
bd->user_access, bd->version, ge, True);
}
add_all_gappt(ge);
if (pos_cnt > 0)
XtFree((XtPointer)pos_list);
}
void mb_update_busystatus(Browser *b, Calendar *c)
{
int i, j, r_cnt;
CSA_uint32 num_entries;
char buf[BUFSIZ + 5];
Boolean match = False;
XmString xmstr;
Browselist *bl = (Browselist *)c->browselist;
time_t start, stop;
CSA_entry_handle *entries = NULL;
BlistData *bd;
CSA_return_code stat;
CSA_enum *ops;
CSA_attribute *range_attrs;
Tick start_tick, end_tick;
j = 1;
while (bd = (BlistData *)CmDataListGetData(bl->blist_data, j)) {
if (!XmListPosSelected(b->browse_list, j++))
continue;
sprintf(buf, " %s", bd->name);
start = b->begin_day_tick;
stop = b->end_hr_tick;
if (bd->cache == NULL) {
setup_range(&range_attrs, &ops, &r_cnt, start, stop,
CSA_TYPE_EVENT, NULL, B_FALSE, bd->version);
stat = csa_list_entries(bd->cal_handle, r_cnt, range_attrs, ops, &num_entries, &entries, NULL);
free_range(&range_attrs, &ops, r_cnt);
backend_err_msg(b->frame, bd->name, stat,
((Props_pu *)c->properties_pu)->xm_error_pixmap);
if (stat != CSA_SUCCESS) {
csa_free(entries);
return;
}
allocate_paint_cache(entries, num_entries, &bd->cache);
bd->cache_size = num_entries;
csa_free(entries);
}
for (i = 0; i < bd->cache_size; i++) {
start_tick = bd->cache[i].start_time;
end_tick = bd->cache[i].end_time;
if ((start_tick+1 <= b->end_hr_tick) &&
(end_tick-1
>= b->begin_hr_tick)) {
buf[0] = '*';
break;
}
} /* end for */
xmstr = XmStringCreateLocalized(buf);
XmListDeletePos(b->browse_list, j-1);
XmListAddItem(b->browse_list, xmstr, j-1);
XmListSelectPos(b->browse_list, j-1, False);
XmStringFree(xmstr);
} /* end while */
}
static void
bcanvas_event(Widget w, XtPointer client_data, XtPointer call_data)
{
Calendar *c = (Calendar *)client_data;
Browser *b;
XmDrawingAreaCallbackStruct *cbs = (XmDrawingAreaCallbackStruct*) call_data;
XEvent *event = cbs->event;
Tick start;
static XEvent lastevent;
int x, y, boxw, boxh;
pr_pos xy;
if ((event->type == ButtonRelease) || (event == NULL))
return;
b = (Browser*)c->browser;
x = event->xbutton.x;
y = event->xbutton.y;
switch(event->type) {
case ButtonPress:
if (x > b->chart_x && y > b->chart_y &&
x < (b->chart_x + b->chart_width)
&& y < (b->chart_y + b->chart_height))
{
browser_deselect(c, b);
b->col_sel = (x - b->chart_x) / b->boxw;
b->row_sel = (y - b->chart_y) / b->boxh;
xy.x = b->col_sel;
xy.y = b->row_sel;
/*
* Don't bring up multi-browser for an invalid date
*/
if ((last_ndays(b->date, 2) <= get_bot()) &&
(b->col_sel < 3))
return;
else if ((next_ndays(b->date, 1) > get_eot()) &&
(b->col_sel > 3))
return;
reset_ticks(c, True);
browser_select(c, b, &xy);
if (ds_is_double_click(&lastevent, event)) {
_DtTurnOnHourGlass(b->frame);
show_geditor(c, b->begin_hr_tick,
b->end_hr_tick);
browser_to_gaccess_list(c);
_DtTurnOffHourGlass(b->frame);
}
/* add busyicon */
mb_update_busystatus(b, c);
}
c->general->last_canvas_touched = browser;
};
lastevent = *event;
}
static void
schedule_cb(Widget w, XtPointer client_data, XtPointer call_data)
{
Calendar *c = (Calendar *)client_data;
Browser *b;
Props *p;
OrderingType ord_t;
SeparatorType sep_t;
XmPushButtonCallbackStruct *cbs = (XmPushButtonCallbackStruct*) call_data;
b = (Browser *)c->browser;
p = (Props *)c->properties;
_DtTurnOnHourGlass(b->frame);
ord_t = get_int_prop(p, CP_DATEORDERING);
sep_t = get_int_prop(p, CP_DATESEPARATOR);
show_geditor(c, b->begin_hr_tick, b->end_hr_tick);
browser_to_gaccess_list(c);
_DtTurnOffHourGlass(b->frame);
}
static char *
get_mail_address_list(Calendar *c) {
int i, *pos_list = NULL, pos_cnt;
Browser *b = (Browser *)c->browser;
BlistData *bd;
Browselist *bl = (Browselist *)c->browselist;
int address_len;
char *address;
XmListGetSelectedPos(b->browse_list, &pos_list, &pos_cnt);
for (i = 0, address_len = 0; i < pos_cnt; i++) {
bd = (BlistData *)CmDataListGetData(bl->blist_data,
pos_list[i]);
if (bd)
address_len += strlen(bd->name) + 1;
}
address = calloc(address_len+1, 1);
address[0] = NULL;
for (i = 0; i < pos_cnt; i++) {
bd = (BlistData *)CmDataListGetData(bl->blist_data,
pos_list[i]);
if (bd) {
strcat(address, bd->name);
strcat(address, " ");
}
}
if (pos_list)
XtFree((XtPointer)pos_list);
return(address);
}
static Tt_message
reply_cb(Tt_message m, void *c_data, Tttk_op op, unsigned char *contents, int len, char *file)
{
char *client_procID = tt_message_handler(m);
if ( debug && (client_procID != NULL) ) {
fprintf(stderr, "DEBUG: reply_cb():client_procID = %s\n", client_procID);
fprintf(stderr, "DEBUG: reply_cb():message_op = %s\n", tt_message_op(m));
}
return(m);
}
static void
mail_cb(Widget w, XtPointer client_data, XtPointer call_data)
{
Calendar *c = (Calendar *)client_data;
Props *p = (Props *) c->properties;
Browser *b = (Browser *)c->browser;
Tt_message msg;
Tt_status status;
char *appointment_buf;
Dtcm_appointment *appt;
char *address = get_mail_address_list(c);
char *address_list[1];
char *mime_buf;
/* Send ToolTalk message to bring up compose GUI with buffer as attachme
nt */
appt = allocate_appt_struct(appt_write, DATAVER_ARCHIVE, NULL);
load_appt_defaults(appt, p);
appt->time->value->item.date_time_value = malloc(BUFSIZ);
_csa_tick_to_iso8601(b->begin_hr_tick, appt->time->value->item.date_time_value);
appt->end_time->value->item.date_time_value = malloc(BUFSIZ);
_csa_tick_to_iso8601(b->end_hr_tick, appt->end_time->value->item.date_time_value);
/* set up the start time from the dialog */
scrub_attr_list(appt);
appointment_buf = parse_attrs_to_string(appt, p, attrs_to_string(appt->attrs, appt->count));
free_appt_struct(&appt);
address_list[0] = appointment_buf;
mime_buf = create_rfc_message(address, "message", address_list, 1);
msg = ttmedia_load(0, (Ttmedia_load_msg_cb)reply_cb, NULL, TTME_MAIL_EDIT, "RFC_822_MESSAGE", (unsigned char *)mime_buf, strlen(mime_buf), NULL, "dtcm_appointment_attachment", 0);
status = tt_ptr_error(msg);
if (tt_is_err(status))
{
fprintf(stderr, "dtcm: ttmedia_load: %s\n",
tt_status_message(status));
}
else
{
status = tt_message_send(msg);
if (tt_is_err(status))
fprintf(stderr, "dtcm: tt_message_send: %s\n",
tt_status_message(status));
}
free(appointment_buf);
free(mime_buf);
free(address);
}
static void
gotomenu_cb(Widget w, XtPointer data, XtPointer cbs)
{
int item_no = (int) data;
/* should really be getting this from the widget */
Calendar *c = calendar;
goto_unit(c, item_no);
}
extern void
mb_update_segs(Browser *b, Tick tick, Tick dur, int *start_index, int *end_index)
{
int num_segs, i, start, start_hour, duration, nday;
Props *p;
p = (Props*)calendar->properties;
start_hour = hour(tick);
if (start_hour >= get_int_prop(p, CP_DAYEND)) {
*start_index = -1;
*end_index = -1;
return;
}
if (start_hour < get_int_prop(p, CP_DAYBEGIN)) {
start = 0;
duration = dur - ((double)(get_int_prop(p, CP_DAYBEGIN) -
((double)start_hour + (double)minute(tick)/(double)60))
* (double)hrsec);
} else{
start = ((double)(start_hour - get_int_prop(p, CP_DAYBEGIN)) *
(double)60 + (double)minute(tick));
duration = dur;
}
if (duration <= 0) {
*start_index = -1;
*end_index = -1;
return;
}
nday = (nday=dow(tick))==0? 6: nday-1;
num_segs = (double)start / (double)MINS_IN_SEG;
*start_index = (double)start / (double)MINS_IN_SEG + (nday * (b->segs_in_array/7));
if (start - (num_segs * MINS_IN_SEG) > 7)
(*start_index)++;
num_segs = ((double)duration / (double)60 / (double)MINS_IN_SEG);
*end_index = num_segs + *start_index;
if (((double)duration/(double)60-MINS_IN_SEG*num_segs) > 7)
(*end_index)++;
if (*end_index > (i = ((nday + 1) * (b->segs_in_array / 7))) )
*end_index = i;
for (i = *start_index; i < *end_index; i++)
if (b->add_to_array)
b->multi_array[i]++;
else if (b->multi_array[i] > 0)
b->multi_array[i]--;
}
void
mb_update_array(char *entry_text, Calendar *c)
{
int start_ind, end_ind, i, r_cnt;
time_t start, stop;
Browser *b = (Browser *)c->browser;
CSA_entry_handle *entries = NULL;
BlistData *bd;
CSA_return_code stat;
Browselist *bl = (Browselist *)c->browselist;
CSA_enum *ops;
CSA_attribute *range_attrs;
CSA_uint32 num_entries;
Tick start_tick, end_tick;
/*
* Search for the entry text in our list of calendar handles
*/
i = 1;
while ((bd = (BlistData *)CmDataListGetData(bl->blist_data, i++))
&& strcmp(bd->name, entry_text) != 0);
if (!bd)
return;
start = b->begin_week_tick;
stop = next_ndays(b->begin_week_tick, 7) - 1;
if (bd->cache == NULL) {
setup_range(&range_attrs, &ops, &r_cnt, start,
stop, CSA_TYPE_EVENT,
NULL, B_FALSE, bd->version);
stat = csa_list_entries(bd->cal_handle, r_cnt, range_attrs,
ops, &num_entries, &entries, NULL);
free_range(&range_attrs, &ops, r_cnt);
backend_err_msg(b->frame, bd->name, stat,
((Props_pu *)c->properties_pu)->xm_error_pixmap);
if (stat != CSA_SUCCESS)
return;
allocate_paint_cache(entries, num_entries, &bd->cache);
bd->cache_size = num_entries;
csa_free(entries);
}
for (i = 0; i < bd->cache_size; i++) {
start_tick = bd->cache[i].start_time;
end_tick = bd->cache[i].end_time;
mb_update_segs(b, start_tick,
end_tick - start_tick, &start_ind,
&end_ind);
}
}
static Boolean
register_names(char *name, Calendar *c)
{
int i;
char *user, *location;
Props_pu *p = (Props_pu *)c->properties_pu;
Browser *b = (Browser*)c->browser;
BlistData *bd = NULL;
Browselist *bl = (Browselist *)c->browselist;
CSA_return_code stat;
CSA_session_handle cal = NULL;
unsigned int user_access;
CSA_calendar_user csa_user;
CSA_flags flags = NULL;
CSA_extension cb_ext;
CSA_extension logon_ext;
char buf[BUFSIZ];
if (blank_buf(name))
return False;
i = 1;
while ((bd = (BlistData *)CmDataListGetData(bl->blist_data, i++))
&& strcmp(bd->name, name) != 0);
if (!bd) {
char *title = XtNewString(catgets(c->DT_catd, 1, 1070,
"Calendar : Error - Compare Calendars"));
char *text = XtNewString(catgets(c->DT_catd, 1, 607,
"Internal error registering calendar name."));
char *ident = XtNewString(catgets(c->DT_catd, 1, 95, "Continue"));
dialog_popup(b->frame,
DIALOG_TITLE, title,
DIALOG_TEXT, text,
BUTTON_IDENT, 1, ident,
DIALOG_IMAGE, p->xm_error_pixmap,
NULL);
XtFree(ident);
XtFree(text);
XtFree(title);
return False;
}
if (bd->cal_handle)
return True;
if (strcmp(c->calname, name) == 0) {
cal = c->my_cal_handle;
user_access = c->my_access;
} else if (strcmp(c->view->current_calendar, name) == 0) {
cal = c->cal_handle;
user_access = c->user_access;
} else {
user = cm_target2name(name);
location = cm_target2location(name);
csa_user.user_name = name;
csa_user.user_type = 0;
csa_user.calendar_user_extensions = NULL;
csa_user.calendar_address = name;
logon_ext.item_code = CSA_X_DT_GET_USER_ACCESS_EXT;
logon_ext.item_data = 0;
logon_ext.item_reference = NULL;
logon_ext.extension_flags = CSA_EXT_LAST_ELEMENT;
stat = csa_logon(NULL, &csa_user, NULL, NULL, NULL, &cal,
&logon_ext);
free(user);
free(location);
if (stat != CSA_SUCCESS) {
backend_err_msg(b->frame, name, stat,
((Props_pu *)c->properties_pu)->xm_error_pixmap);
return False;
} else
user_access = logon_ext.item_data;
}
/* register for activity notification */
flags = CSA_CB_ENTRY_ADDED | CSA_CB_ENTRY_UPDATED |
CSA_CB_ENTRY_DELETED;
cb_ext.item_code = CSA_X_XT_APP_CONTEXT_EXT;
cb_ext.item_data = (CSA_uint32)c->xcontext->app;
cb_ext.extension_flags = CSA_EXT_LAST_ELEMENT;
stat = csa_register_callback(cal, flags, mb_update_handler, NULL, &cb_ext);
if (stat != CSA_SUCCESS) {
backend_err_msg(b->frame, name, stat,
((Props_pu *)c->properties_pu)->xm_error_pixmap);
return False;
}
bd->cal_handle = cal;
bd->user_access = user_access;
/* squirrel away data model version for later */
bd->version = get_data_version(cal);
return True;
}
extern void
mb_deregister_names(char *name, Calendar *c)
{
int i;
Browser *b = (Browser *)c->browser;
Props_pu *p = (Props_pu *)c->properties_pu;
BlistData *bd;
Browselist *bl = (Browselist *)c->browselist;
CSA_return_code stat;
i = 1;
while ((bd = (BlistData *)CmDataListGetData(bl->blist_data, i))
&& strcmp(bd->name, name) != 0)
++i;
if (!bd)
return;
destroy_paint_cache(bd->cache, bd->cache_size);
bd->cache = NULL;
bd->cache_size = 0;
if (bd->cal_handle != c->my_cal_handle &&
bd->cal_handle != c->cal_handle && bd->cal_handle) {
stat = csa_logoff(bd->cal_handle, NULL);
if (stat != CSA_SUCCESS) {
backend_err_msg(b->frame, bd->name, stat,
p->xm_error_pixmap);
}
bd->cal_handle = NULL;
blist_clean(bl, False);
}
}
static void
mb_box_notify(Widget widget, XtPointer client_data, XtPointer call_data)
{
XmListCallbackStruct *cbs = (XmListCallbackStruct *)call_data;
Calendar *c = (Calendar *)client_data;
int i;
char *addr;
Browser *b;
GEditor *e;
BlistData *bd;
Browselist *bl;
XmString xmstr;
char name[BUFSIZ+5];
#ifdef FNS
int rcode;
char *fns_name, buf[256];
#endif
b = (Browser*)c->browser;
bl = (Browselist*)c->browselist;
e = (GEditor*)c->geditor;
i = 0;
while (i < cbs->selected_item_count &&
cbs->item_position != cbs->selected_item_positions[i])
++i;
b->add_to_array = (i < cbs->selected_item_count) ? True : False;
if ((bd = (BlistData *)CmDataListGetData(bl->blist_data,
cbs->item_position)) == NULL)
return;
/* erase busy status if it was busy because it was deselected */
if (!XmListPosSelected(b->browse_list, cbs->item_position)) {
sprintf(name, " %s", bd->name);
xmstr = XmStringCreateLocalized(name);
XmListDeletePos(b->browse_list, cbs->item_position);
XmListAddItem(b->browse_list, xmstr, cbs->item_position);
XmStringFree(xmstr);
}
#ifdef FNS
rcode = -1;
if (cmfns_use_fns((Props *)c->properties)) {
/* Yes! Try to use it */
rcode = cmfns_lookup_calendar(bd->name, buf, sizeof(buf));
}
if (rcode > 0)
addr = buf;
else
#endif
addr = bd->name;
_DtTurnOnHourGlass(b->frame);
if (b->add_to_array) {
if (!register_names(addr, c)) {
XmListDeselectPos(b->browse_list, cbs->item_position);
_DtTurnOffHourGlass(b->frame);
return;
}
if (geditor_showing(e)) {
add_to_gaccess_list(addr, bd->cal_handle,
bd->user_access, bd->version, e, True);
add_all_gappt(e);
}
mb_update_array(addr, c);
} else {
/*
* Must update the array before we deregister names because we
* close the calendar handle when we deregister.
*/
mb_update_array(addr, c);
mb_deregister_names(addr, c);
if (geditor_showing(e))
remove_from_gaccess_list(addr, e);
}
mb_refresh_canvas(b, c);
_DtTurnOffHourGlass(b->frame);
}
extern void
mb_clear_selected_calendar(
char *name,
Calendar *c)
{
GEditor *e = (GEditor*)c->geditor;
Browser *b = (Browser *)c->browser;
/*
* Must update the array before we deregister names because we
* close the calendar handle when we deregister.
*/
b->add_to_array = False;
mb_update_array(name, c);
if (geditor_showing(e))
remove_from_gaccess_list(name, e);
mb_deregister_names(name, c);
mb_refresh_canvas(c->browser, c);
}
extern void
mb_init_canvas(Calendar *c)
{
Browser *b = (Browser*)c->browser;
Browselist *bl = (Browselist *)c->browselist;
BlistData *bd;
int i;
b->add_to_array = True;
gr_clear_area(b->xcontext, 0, 0, b->canvas_w, b->canvas_h);
register_names(c->calname, c);
mb_update_array(c->calname, c);
/*
* Search for the entry text in our list of calendar handles
*/
i = 1;
while ((bd = (BlistData *)CmDataListGetData(bl->blist_data, i++))
&& strcmp(bd->name, c->calname) != 0);
if (!bd)
return;
XmListSelectPos(b->browse_list, i - 1, False);
}
extern void
mb_init_datefield(Browser *b, Calendar *c)
{
char *date;
Props *p = (Props *)c->properties;
OrderingType ot = get_int_prop(p, CP_DATEORDERING);
SeparatorType st = get_int_prop(p, CP_DATESEPARATOR);
date = XmTextGetString(b->datetext);
if (!date || *date == '\0') {
date = get_date_from_widget(c->view->date, b->datetext, ot, st);
if (date != NULL)
XmTextSetString(b->datetext, date);
}
}
static void
mb_init_browchart(Browser *b, Calendar *c)
{
int char_width, char_height, day_len, day_of_week;
int label_height, label_width;
Props *p = (Props *)c->properties;
Dimension canvas_width, canvas_height;
XFontSetExtents fontextents;
mb_init_datefield(b, c);
XtVaGetValues(b->canvas,
XmNwidth, &canvas_width,
XmNheight, &canvas_height,
NULL);
b->canvas_w = (int)canvas_width;
b->canvas_h = (int)canvas_height;
CalFontExtents(c->fonts->labelfont, &fontextents);
char_height = fontextents.max_ink_extent.height;
char_width = fontextents.max_ink_extent.width;
label_height = char_height * 2;
label_width = char_width + 2;
b->chart_height =
b->canvas_h - (c->view->outside_margin * 2) - label_height - 5;
b->chart_width =
b->canvas_w - (c->view->outside_margin * 2) - label_width;
b->boxw = b->chart_width / 7;
b->chart_width = b->boxw * 7;
day_len = get_int_prop(p, CP_DAYEND) - get_int_prop(p, CP_DAYBEGIN);
b->boxh = b->chart_height / day_len;
/*
* Make sure boxh is evenly divisable by BOX_SEG
*/
b->boxh -= (b->boxh % BOX_SEG);
b->chart_height = b->boxh * day_len;
b->chart_x = c->view->outside_margin + label_width;
b->chart_y = c->view->outside_margin + label_height + char_height;
}
extern void
mb_draw_chartgrid(Browser *b, Calendar *c)
{
int x, y;
int n;
Props *p = (Props*)c->properties;
XFontSetExtents fontextents;
int char_height, char_width;
char label[5], buf[160];
new_XContext *xc = b->xcontext;
int dayy, dayweek;
Tick daytick;
DisplayType dt;
int nop;
int s_width;
CalFontExtents(c->fonts->viewfont, &fontextents);
char_height = fontextents.max_logical_extent.height;
char_width = fontextents.max_logical_extent.width;
/* Draw chart. It'll be filled in later.
Draw grid lines and hourly labels. */
x = b->chart_x;
y = b->chart_y;
/* clear header */
gr_clear_area(xc, 0, 0, b->canvas_w, b->chart_y);
label[0] = '\0';
/* draw hour labels */
for (n = get_int_prop(p, CP_DAYBEGIN); n <= get_int_prop(p, CP_DAYEND); n++) {
dt = get_int_prop(p, CP_DEFAULTDISP);
if (dt == HOUR12)
sprintf(label, "%2d", n > 12 ? n - 12 : n);
else
sprintf(label, "%2d", n);
gr_text(xc, c->view->outside_margin-char_width, y+3,
c->fonts->viewfont, label, NULL);
gr_draw_line(xc, x, y, x + b->chart_width,
y, gr_solid, NULL);
y += b->boxh;
}
/*
* Draw vertical lines and day labels
*/
y = b->chart_y;
dayy = y - char_height - 4;
dayweek = dow(b->date);
daytick = last_ndays(b->date, dayweek == 0 ? 6 : dayweek-1);
/* draw month */
format_date(b->begin_week_tick+1, get_int_prop(p, CP_DATEORDERING), buf, 0, 0, 0);
gr_text(xc, c->view->outside_margin+4,
dayy-char_height-4, c->fonts->labelfont, buf, NULL);
for (n = 0; n < 7; n++) {
if (daytick >= get_bot() && daytick < get_eot()) {
CalTextExtents(c->fonts->viewfont, days3[n+1], strlen(days3[n+1]), &nop, &nop, &s_width, &nop);
gr_text(xc, b->chart_x + (b->boxw * n) + ((b->boxw - s_width)/2),
dayy, c->fonts->viewfont, days3[n+1], NULL);
CalTextExtents(c->fonts->viewfont, numbers[dom(daytick)], strlen(numbers[dom(daytick)]), &nop, &nop, &s_width, &nop);
gr_text(xc, b->chart_x + (b->boxw * n) + ((b->boxw - s_width)/2),
y - char_height / 2, c->fonts->viewfont,
numbers[dom(daytick)], NULL);
}
daytick += daysec;
gr_draw_line(xc, b->chart_x + (b->boxw * n),
y, b->chart_x + (b->boxw * n),
y + b->chart_height, gr_solid, NULL);
}
/*
* Draw box around the whole thing.
*/
gr_draw_box(xc, b->chart_x, b->chart_y, b->chart_width, b->chart_height, NULL);
gr_draw_box(xc, b->chart_x-1, b->chart_y-1, b->chart_width+2, b->chart_height+2, NULL);
}
extern void
mb_draw_appts(Browser *b, int start, int end, Calendar *c)
{
int x, y, h, i, end_of_day;
Boolean outofbounds = False;
Colormap cms;
if (next_ndays(b->date, 1) > get_eot())
outofbounds = True;
XtVaGetValues(b->canvas, XmNcolormap, &cms, NULL);
h = (b->boxh/BOX_SEG);
end_of_day = (b->segs_in_array / 7);
y = b->chart_y + (start % end_of_day) * h;
x = b->chart_x + (start/end_of_day * b->boxw);
i = start;
while (i < end) {
if (b->multi_array[i] <= 0) {
gr_clear_area(b->xcontext, x, y, b->boxw, h);
y += h;
i++;
}
else if (b->multi_array[i] == 1) {
/* batch up for one repaint */
if ( ((i+1) < b->segs_in_array)
&& b->multi_array[i+1] == 1 &&
( ((i+1) % end_of_day) != 0)) {
h += (b->boxh/BOX_SEG);
if (++i < end)
continue;
}
if ((c->xcontext->screen_depth < 8) || FAKE_MONOCHROME)
gr_make_gray(b->xcontext, x, y, b->boxw, h, 25);
else
gr_make_grayshade(b->xcontext, x, y, b->boxw, h,
LIGHTGREY);
y += h;
h = (b->boxh/BOX_SEG);
i++;
}
else if (b->multi_array[i] == 2) {
/* batch up for one repaint */
if ( ((i+1) < b->segs_in_array)
&& b->multi_array[i+1] == 2 &&
( ((i+1) % end_of_day) != 0) ) {
h += (b->boxh/BOX_SEG);
if (++i < end)
continue;
}
if ((c->xcontext->screen_depth < 8) || FAKE_MONOCHROME)
gr_make_gray(b->xcontext, x, y, b->boxw, h, 50);
else
gr_make_rgbcolor(b->xcontext, cms, x, y,
b->boxw, h, MIDGREY, MIDGREY,
MIDGREY);
y += h;
h = (b->boxh/BOX_SEG);
i++;
}
else if (b->multi_array[i] >= 3) {
/* batch up for one repaint */
if ( ((i+1) < b->segs_in_array)
&& b->multi_array[i+1] >= 3 &&
( ((i+1) % end_of_day) != 0) ) {
h += (b->boxh/BOX_SEG);
if (++i < end)
continue;
}
if ((c->xcontext->screen_depth < 8) || FAKE_MONOCHROME)
gr_make_gray(b->xcontext, x, y, b->boxw, h, 75);
else
gr_make_rgbcolor(b->xcontext, cms, x, y,
b->boxw, h, DIMGREY, DIMGREY,
DIMGREY);
y += h;
h = (b->boxh/BOX_SEG);
i++;
}
if (i != 0 && ((i % end_of_day) == 0)) {
x += b->boxw;
y = b->chart_y;
h = (b->boxh/BOX_SEG);
}
if (outofbounds && i > 4)
break;
}
browser_select(c, b, NULL);
}
extern void
mb_refresh_canvas(Browser *b, Calendar *c)
{
mb_draw_appts(b, 0, b->segs_in_array, c);
mb_draw_chartgrid(b, c);
mb_display_footermess(b, c);
}
void
mb_resize_proc(Widget w, XtPointer client_data, XtPointer call)
{
Dimension width, height;
Calendar *c = (Calendar *)client_data;
Browser *b;
XtVaGetValues(w, XmNwidth, &width, XmNheight, &height, NULL);
b = (Browser*)c->browser;
gr_clear_area(b->xcontext, 0, 0, width, height);
mb_init_browchart(b, c);
mb_refresh_canvas(b, c);
}
void
mb_refigure_chart(Calendar *c) {
mb_resize_proc(((Browser *)c->browser)->canvas, (XtPointer)c, NULL);
}
extern void
browser_reset_list(Calendar *c) {
int i;
Browser *b = (Browser *)c->browser;
BlistData *bd;
Browselist *bl = (Browselist *)c->browselist;
XmStringTable list_selected_items, selected_items;
int selected_items_count;
XtVaGetValues(b->browse_list,
XmNselectedItemCount, &selected_items_count,
XmNselectedItems, &list_selected_items,
NULL);
selected_items = (XmStringTable)calloc(selected_items_count,
sizeof(XmStringTable));
for (i = 0; i < selected_items_count; i++)
selected_items[i] = XmStringCopy(list_selected_items[i]);
XtVaSetValues(b->upper_form, XmNresizePolicy, XmRESIZE_NONE, NULL);
/*
* When a user removes a calendar from the menu we remove it
* from the multi-browser. If the calendar happens to be selected
* in the multi-browser then we must deselect it and clean up
* the browser. That's what this first loops does.
*/
for (i = 1; i <= bl->blist_data->count; i++) {
bd = (BlistData *)CmDataListGetData(bl->blist_data, i);
if (bd && bd->tag != BLIST_ACTIVE) {
mb_clear_selected_calendar(bd->name, c);
/* We need to reset this to one because the blist_data
* has changed which may cause us to miss an item.
*/
i = 1;
}
}
XmListDeleteAllItems(b->browse_list);
for (i = 1; i <= bl->blist_data->count; i++) {
bd = (BlistData *)CmDataListGetData(bl->blist_data, i);
if (bd && bd->name) {
char buf[BUFSIZ + 5];
XmString xmstr;
sprintf(buf, " %s", bd->name);
xmstr = XmStringCreateLocalized(buf);
if (!XmListItemExists(b->browse_list, xmstr))
XmListAddItem(b->browse_list, xmstr, 0);
XmStringFree(xmstr);
}
}
XtVaSetValues(b->upper_form, XmNresizePolicy, XmRESIZE_ANY, NULL);
/*
* Reselect the items that were selected before we changed the
* contents of the mb.
*/
for (i = 0; i < selected_items_count; i++) {
int *pos_list,
pos_cnt;
if (XmListGetMatchPos(b->browse_list, selected_items[i],
&pos_list, &pos_cnt))
XmListSelectPos(b->browse_list, pos_list[0], False);
XmStringFree(selected_items[i]);
}
if (selected_items)
free(selected_items);
}
extern void
init_browser(Calendar *c)
{
pr_pos xy;
Browser *b = (Browser*)c->browser;
browser_reset_list(c);
b->row_sel = b->col_sel = 0;
mb_init_browchart(b, c);
mb_init_canvas(c);
mb_refresh_canvas(b, c);
xy.x = dow(b->date) - 1;
xy.y = 0;
browser_select(c, b, &xy);
}
static void
cancel_cb(Widget w, XtPointer client, XtPointer call)
{
Calendar *c = (Calendar *)client;
Browser *b = (Browser *)c->browser;
XtPopdown(b->frame);
XtDestroyWidget(b->frame);
XtFree(b->multi_array);
XtFree(c->browser); c->browser = NULL;
}
static void
popup_cb(Widget w, XtPointer client, XtPointer call)
{
Calendar *c = (Calendar *)client;
Browser *b = (Browser *)c->browser;
Position x, y;
XtVaGetValues(c->frame, XmNx, &x, XmNy, &y, NULL);
XtVaSetValues(b->frame, XmNx, x+100, XmNy, y+100, NULL);
}
/*
* This is the CSA_callback called from the CSA library when
* an update occurs on a calendar to which we are logged on,
* and have registered interest. Registered in register_names.
* When calendar is logged off, any registered callbacks for it
* are destroyed automagically.
*/
static void
mb_update_handler(CSA_session_handle cal, CSA_flags reason,
CSA_buffer call_data, CSA_buffer client_data, CSA_extension *ext)
{
Calendar *c = calendar;
Browser *b = (Browser *)c->browser;
/* sync whatever needs sync'ing */
if (b) {
br_display(c);
if (geditor_showing((GEditor *)c->geditor))
add_all_gappt((GEditor *)c->geditor);
}
}