axe-6.1.2.orig/ 40755 243 144 0 5600546377 11705 5ustar joostusersaxe-6.1.2.orig/Help/ 40755 243 144 0 5600546744 12573 5ustar joostusersaxe-6.1.2.orig/Help/Axinfo.ad.sed100644 243 144 2756 5550557107 15205 0ustar joostusersAxinfo.version: VERSION *infoPath: AXINFOLIBDIR *hyperwin.title: axinfo *hyperwin.iconName: axinfo *hyperwin.translations: #override \n\ WM_PROTOCOLS:delete-hyper() *view.allowVert: True *view.forceBars: True *hyper.rows: 24 *hyper.columns: 80 *Hyper.normalFont: 7x13 *Hyper.highlightFont: 7x13bold *Hyper.margin: 4 *hpane*Command.translations: #override \n\ : highlight() show-info() \n\ : reset() clear-info() *last.label: Last *map.label: Tree *treewin.title: axinfo *treewin.iconName: axinfo-tree *treewin.translations: #override \n\ WM_PROTOCOLS:delete-tree() *Paned*showGrip: False *porthole.width: 450 *porthole.height: 326 *porthole.borderWidth: 0 *tree.translations: #override \n\ : show-info() \n\ : clear-info() \n\ : start-drag() \n\ : drag() *treewin*Command.translations: #override \n\ : highlight() show-info() \n\ : reset() clear-info() *quit.label: Quit *close.label: Delete *info.label: *Confirmer*Label.borderWidth: 0 *Confirmer*Box.orientation: horizontal *Confirmer*Box.borderWidth: 0 *Confirmer*Box.vSpace: 2 *Confirmer*confirm.accelerators:Ctrla: set() notify() reset() *Confirmer*alternative.accelerators:Ctrlb: set() notify() reset() *Confirmer*cancel.label: cancel (^C) *Confirmer*cancel.accelerators: Ctrlc: set() notify() reset() *listen.translations: #override \n\ AXE_AXINFO: notify() axe-6.1.2.orig/Help/Hyper.c100644 243 144 116542 5550557110 14165 0ustar joostusers/*==================================================================*/ /* */ /* HyperWidget */ /* */ /* B.Raoult (mab@ecmwf.co.uk) Oct.91 */ /* */ /* */ /* Hyper text like widget. */ /* */ /* (c) B.Raoult 91 */ /*==================================================================*/ #include #include #include #include #include #include #include #include #include "Hyper.h" #include "HyperP.h" #define ABS(a) ((a)>=0?(a):-(a)) #define MIN(a,b) ((a)>(b)?(b):(a)) #define NORMAL 0 #define HIGHLIGHT 1 #define NEWLINE 2 #define MAX_LINE_SIZE 1024 /* Private functions */ static void free_text(); static void create_gcs(); static void create_new_text(); /* static void select(); */ static void Select(); /* type clash from under SunOS 5 */ static void cursor(); static void activate(); static void add_to_text (); static void calc_new_size (); static void zoom_open (); static void show_selection(); /* Widget class methods */ static void Initialize(); static void Redisplay(); static void Resize(); static void Destroy(); static Boolean SetValues(); static char defaultTranslations[] = ":select()\n: activate()\n:cursor()"; static XtActionsRec actionsList[] = { { "select", (XtActionProc) Select}, { "activate", (XtActionProc) activate}, { "cursor", (XtActionProc) cursor}, }; static XtResource resources[] = { {XtNhighlightFont, XtCFont, XtRFontStruct, sizeof (XFontStruct *), XtOffset(HyperWidget, hyper.highlight_font), XtRString, "Fixed"}, {XtNnormalFont, XtCFont, XtRFontStruct, sizeof (XFontStruct *), XtOffset(HyperWidget, hyper.normal_font), XtRString, "Fixed"}, {XtNhighlightColor, XtCColor, XtRPixel, sizeof (Pixel), XtOffset(HyperWidget, hyper.highlight_color),XtRString, "Red"}, {XtNselectColor, XtCColor, XtRPixel, sizeof (Pixel), XtOffset(HyperWidget, hyper.select_color),XtRString, "Blue"}, {XtNnormalColor, XtCColor, XtRPixel, sizeof (Pixel), XtOffset(HyperWidget, hyper.normal_color),XtRString,"Black"}, {XtNactivateCallback,XtCCallback,XtRCallback,sizeof(caddr_t), XtOffset (HyperWidget, hyper.activate),XtRCallback,NULL}, {XtNhyperCallback,XtCCallback,XtRCallback,sizeof(caddr_t), XtOffset (HyperWidget, hyper.hyper_callbacks),XtRCallback,NULL}, {XtNzoomEffect,XtCZoom,XtRBoolean,sizeof(Boolean), XtOffset (HyperWidget, hyper.zoom),XtRImmediate,(XtPointer)TRUE}, #ifndef XDESIGNER {XtNstartHighlight,XtCTagChar,XtRUnsignedChar,sizeof(unsigned char), XtOffset(HyperWidget,hyper.start_of_highlight),XtRImmediate, (XtPointer)'{'}, {XtNendHighlight,XtCTagChar,XtRUnsignedChar,sizeof(unsigned char), XtOffset (HyperWidget, hyper.end_of_highlight),XtRImmediate, (XtPointer)'}'}, #endif {XtNzoomSpeed,XtCZoomSpeed,XtRInt,sizeof(int), XtOffset (HyperWidget, hyper.speed),XtRImmediate,(XtPointer)4}, {XtNmargin,XtCMargin,XtRInt,sizeof(int), XtOffset (HyperWidget, hyper.margin),XtRImmediate,(XtPointer)10}, }; /*---------------------------------------------------------------*/ /* Static initialisation of the class record */ /*---------------------------------------------------------------*/ HyperClassRec hyperClassRec = { { #ifdef MOTIF (WidgetClass) &xmPrimitiveClassRec, /* superclass */ #else (WidgetClass) &widgetClassRec, /* superclass */ #endif "Hyper", /* class_name */ sizeof(HyperRec), /* widget_size */ NULL, /* class_initialize */ NULL, /* class_part_initialize */ FALSE, /* class_inited */ Initialize, /* initialize */ NULL, /* initialize_hook */ XtInheritRealize, /* realize */ actionsList, /* actions */ XtNumber(actionsList), /* num_actions */ resources, /* resources */ XtNumber(resources), /* num_resources */ NULLQUARK, /* xrm_class */ TRUE, /* compress_motion */ XtExposeCompressMultiple, /* compress_exposure */ TRUE, /* compress_enterleave */ TRUE, /* visible_interest */ Destroy, /* destroy */ Resize, /* resize */ Redisplay, /* expose */ SetValues, /* set_values */ NULL, /* set_values_hook */ XtInheritSetValuesAlmost, /* set_values_almost */ NULL, /* get_values_hook */ NULL, /* accept_focus */ XtVersion, /* version */ NULL, /* callback private */ defaultTranslations, /* tm_table */ NULL, /* query_geometry */ NULL, /* display_accelerator */ NULL, /* extension */ }, #ifdef MOTIF { (XtWidgetProc)_XtInherit, /* border_highlight */ (XtWidgetProc)_XtInherit, /* border_unhighligh */ XtInheritTranslations, /* translations */ (XtActionProc)_XtInherit, /* arm_and_activate */ NULL, /* syn_resources */ 0, /* num_syn_resources */ NULL, /* extension */ }, #endif { 0, /* ignore */ } }; WidgetClass hyperWidgetClass = (WidgetClass) &hyperClassRec; /*---------------------------------------------------------------*/ /* Create the two GCs needed */ /*---------------------------------------------------------------*/ static void create_gcs(w) Widget w; { HyperWidget hw = (HyperWidget) w; XGCValues values; XtGCMask valueMask; valueMask = GCForeground | GCBackground | GCFont; values.background = hw->core.background_pixel; values.foreground = hw->hyper.highlight_color; values.font = hw->hyper.highlight_font->fid; hw->hyper.highlight_gc = XtGetGC (w, valueMask, &values); values.foreground = hw->hyper.select_color; hw->hyper.select_gc = XtGetGC (w, valueMask, &values); values.foreground = hw->hyper.normal_color; values.font = hw->hyper.normal_font->fid; hw->hyper.normal_gc = XtGetGC (w, valueMask, &values); valueMask = GCBackground | GCForeground | GCFunction; values.background = hw->core.background_pixel; values.foreground = hw->hyper.normal_color; values.function = GXxor; hw->hyper.xor_gc = XtGetGC (w, valueMask, &values); } /*--------------------------------------------------------------*/ /* Initialize: Create the GCs */ /*--------------------------------------------------------------*/ static void Initialize (request, new) HyperWidget request, new; { /* Check the size of the widget */ if (request->core.width == 0) new->core.width = 100; if (request->core.height == 0) new->core.height = 100; /* Create the GCs */ create_gcs(new); /* No text yet */ new->hyper.first_seg = new->hyper.last_selected = new->hyper.last_cursor = NULL; new->hyper.hand = XCreateFontCursor(XtDisplay(new),XC_hand2); /* Nothing found */ new->hyper.grep_seg = NULL; new->hyper.grep_txt = NULL; new->hyper.grep_len = 0; new->hyper.grep_off = 0; } /*--------------------------------------------------------------*/ /* Free all memory allocated for the text segments */ /*--------------------------------------------------------------*/ static void free_text(s) text_segment *s; { while(s) { text_segment *p=s->next; if(s->text) XtFree(s->text); XtFree((char *) s); s = p; } } /*--------------------------------------------------------------*/ /* Destroy the widget: release all memory alocated */ /*--------------------------------------------------------------*/ static void Destroy (w) Widget w; { HyperWidget hw = (HyperWidget) w; free_text(hw->hyper.first_seg); XtReleaseGC (w, hw->hyper.normal_gc); XtReleaseGC (w, hw->hyper.highlight_gc); XtReleaseGC (w, hw->hyper.xor_gc); XtReleaseGC (w, hw->hyper.select_gc); XtRemoveAllCallbacks (w,XtNactivateCallback); } /*--------------------------------------------------------------*/ /* Resize : not implemented */ /*--------------------------------------------------------------*/ static void Resize (w) HyperWidget w; { /* For futur implementation May be for text warp ... */ } /*--------------------------------------------------------------*/ /* Redisplay : redraw the text */ /*--------------------------------------------------------------*/ static void Redisplay (w, event, region) HyperWidget w; XEvent *event; Region region; { if(w->core.visible) { text_segment *s = w->hyper.first_seg; int x = w->hyper.margin; int y = 0; Boolean newline = TRUE; while(s) { /* change line on new lines */ if(newline) { x = w->hyper.margin; y += s->height; } /* redraw only what is needed */ if(XRectInRegion(region,x,y-s->height+s->desc,s->width,s->height) != RectangleOut) { XDrawImageString(XtDisplay (w), XtWindow (w), s->gc, x, y, s->text, s->length); } x += s->width; newline = (s->type == NEWLINE); s = s->next; } if(w->hyper.grep_seg) { if(XRectInRegion(region, w->hyper.grep_x, w->hyper.grep_y, w->hyper.grep_width, w->hyper.grep_height) != RectangleOut) XFillRectangle(XtDisplay(w),XtWindow(w), w->hyper.xor_gc, w->hyper.grep_x, w->hyper.grep_y, w->hyper.grep_width, w->hyper.grep_height); } } } /*------------------------------------------------------------------*/ /* SetValues : redraw only for font or color changes */ /*------------------------------------------------------------------*/ static Boolean SetValues (current, request, new) Widget current, request, new; { HyperWidget hcurrent = (HyperWidget) current; HyperWidget hnew = (HyperWidget) new; Boolean redraw = FALSE; #define HAS_CHANGED(a) (hnew->a != hcurrent->a) if( HAS_CHANGED(core.background_pixel) || HAS_CHANGED(hyper.select_color) || HAS_CHANGED(hyper.highlight_color) || HAS_CHANGED(hyper.highlight_font) || HAS_CHANGED(hyper.normal_color) || HAS_CHANGED(hyper.normal_font) ) { XtReleaseGC (new, hnew->hyper.normal_gc); XtReleaseGC (new, hnew->hyper.highlight_gc); XtReleaseGC (new, hnew->hyper.xor_gc); XtReleaseGC (new, hnew->hyper.select_gc); create_gcs(new); /* rebuild text */ /* if(HAS_CHANGED(hyper.normal_font) || HAS_CHANGED(hyper.highlight_font)) */ create_new_text(hnew); redraw = TRUE; } return (redraw); #undef HAS_CHANGED } /*------------------------------------------------------------------*/ /* Calculate the size of the widget */ /*------------------------------------------------------------------*/ static void calc_new_size (w) Widget w; { HyperWidget hw = (HyperWidget) w; text_segment *s = hw->hyper.first_seg; int x = hw->hyper.margin; int y = 0; int last_height = 0; Boolean newline = TRUE; Dimension maxWidth = hw->hyper.margin; Dimension maxHeight = hw->hyper.margin; XtGeometryResult result; Dimension replyWidth = 0, replyHeight = 0; /* Get the size of the widget */ while(s) { if(newline) { if(x>maxWidth) maxWidth=x; x = hw->hyper.margin; y += s->height; if(y>maxHeight) maxHeight=y; } s->x = x; s->y = y - s->height; x += s->width; newline = (s->type == NEWLINE); last_height = s->height; s = s->next; } x+= hw->hyper.margin; y+= last_height; if(x>maxWidth ) maxWidth=x; if(y>maxHeight) maxHeight=y; /* Tell our parent we want a new size */ if(hw->core.width != maxWidth || hw->core.height != maxHeight) { result = XtMakeResizeRequest(w,maxWidth,maxHeight, &replyWidth, &replyHeight) ; if (result == XtGeometryAlmost) XtMakeResizeRequest (w, replyWidth, replyHeight,NULL, NULL); } } /*-----------------------------------------------------------------------*/ /* Find the "visible" part of a widget as the intersection of all the */ /* windows of it's parents' windows */ /*-----------------------------------------------------------------------*/ static void find_visible_part(w,x,y,width,height) Widget w; Position *x; Position *y; Dimension *width; Dimension *height; { Position root_x,root_y; Widget p = w; *width = w->core.width; *height = w->core.height; XtTranslateCoords(w,0,0,&root_x,&root_y); *x = 0; *y = 0; while(p = XtParent(p)) { Position rx,ry; Dimension w,h; /* make all computations in the root's coordinate system */ XtTranslateCoords(p,0,0,&rx,&ry); w = p->core.width; h = p->core.height; /* use the smallest rectangle */ if(w < *width) *width = w; if(h < *height) *height = h; if(rx>root_x) root_x = rx; if(ry>root_y) root_y = ry; /* stop when reach a shell, don't go to top level shell */ if(XtIsShell(p)) break; } /* Back to the widget's coordinate system */ XtTranslateCoords(w,0,0,x,y); *x = root_x - *x; *y = root_y - *y; } /*-----------------------------------------------------------------------*/ /* Do an "zoom" effect animation, from the selected text segment to the */ /* visible part of the widget */ /*-----------------------------------------------------------------------*/ static void zoom_open(w,s) HyperWidget w; text_segment *s; { int dx1,dx2,dy1,dy2; Position x ; Position y ; Dimension width ; Dimension height ; /* selected rectangle */ Position xs = s->x; Position ys = s->y; Dimension ws = s->width; Dimension hs = s->height; /* get the rectangle we want to zoom to */ find_visible_part(w,&x,&y,&width,&height); /* make sure selected rectangle in visible */ if(xs x+width) ws = x+width-xs; if(ys+hs > y+height) hs = y+height-ys; /* get the offsets in each directions */ dx1 = x-xs; dy1 = y-ys; dx2 = ((x+width)-(xs+ws)); dy2 = ((y+height)-(ys+hs)); /* in the rectangles are differents */ if(dx1 || dy1 || dx2 || dy2) { int min = 32000; /* <-- Can be buggy */ /* work in "left,top,bottom,right" rectangles (Mac) rather than "x,y,width,height" (X) It's easier for the animation */ int xws = xs+ws; int yhs = ys+hs; int xw = x + width; int yh = y + height; /* Get smallest non-null offset */ if(dx1) min = MIN(min,ABS(dx1)); if(dx2) min = MIN(min,ABS(dx2)); if(dy1) min = MIN(min,ABS(dy1)); if(dy2) min = MIN(min,ABS(dy2)); /* Scale offsets so minimun offset is 1 pixel */ dx1 /= min; dx2 /= min; dy1 /= min; dy2 /= min; /* Use speed .. */ dx1 *= w->hyper.speed; dx2 *= w->hyper.speed; dy1 *= w->hyper.speed; dy2 *= w->hyper.speed; /* Animate */ while(min--) { XDrawRectangle(XtDisplay(w),XtWindow(w), w->hyper.xor_gc,xs,ys,xws-xs,yhs-ys); /* Needed, otherwise X calls are buffered */ XSync(XtDisplay(w),False); XDrawRectangle(XtDisplay(w),XtWindow(w), w->hyper.xor_gc,xs,ys,xws-xs,yhs-ys); xs += dx1; ys += dy1; xws += dx2; yhs += dy2; } } } /*----------------------------------------------------------------------*/ /* Find the text segment at point (x,y) */ /*----------------------------------------------------------------------*/ text_segment *find_segment(w,x,y) HyperWidget w; int x,y; { text_segment *s = w->hyper.first_seg; while(s) { if( s->type == HIGHLIGHT && x >= s->x && y >= s->y && x <= s->x + s->width && y <= s->y + s->height ) return s; s = s->next; } return NULL; } /*----------------------------------------------------------------------*/ /* highlight text under cursor */ /*----------------------------------------------------------------------*/ static void hilite(w,on) HyperWidget w; Boolean on; { text_segment *s = w->hyper.last_selected; if(s) XDrawImageString(XtDisplay (w), XtWindow (w), on?w->hyper.select_gc:s->gc, s->x, s->y+s->height, s->text, s->length); } /*-----------------------------------------------------------------------*/ /* Check for mouse down */ /*-----------------------------------------------------------------------*/ static void Select (w, event, args, n_args) HyperWidget w; XEvent *event; char *args[]; int n_args; { text_segment *s; /* Find if the used clicked in an highlighted text */ if(s = w->hyper.last_selected = find_segment(w,event->xbutton.x,event->xbutton.y)) hilite(w,TRUE); } /*-----------------------------------------------------------------------*/ /* Check for mouse up */ /*-----------------------------------------------------------------------*/ static void activate (w, event, args, n_args) Widget w; XEvent *event; char *args[]; int n_args; { HyperWidget hw = (HyperWidget) w; hyperCallbackStruct cb; text_segment *s; /* Find if the used clicked in an highlighted text */ if((s = find_segment(hw,event->xbutton.x,event->xbutton.y)) && (s == hw->hyper.last_selected)) { hilite(hw,FALSE); /* zoom if required */ if(hw->hyper.zoom) zoom_open(hw,s); /* Fill callback struct */ cb.text = s->text; cb.length = s->length; cb.reason = HYPER_REASON; cb.event = event; /* call callbacks */ XtCallCallbacks (w, XtNactivateCallback, &cb); } hw->hyper.last_selected = NULL; } /*-----------------------------------------------------------------------*/ /* Check for mouse moves */ /*-----------------------------------------------------------------------*/ static void cursor (w, event, args, n_args) HyperWidget w; XEvent *event; char *args[]; int n_args; { text_segment *s; hyperCallbackStruct cb; s = find_segment(w,event->xbutton.x,event->xbutton.y); if(s != w->hyper.last_cursor) { if(s) { XDefineCursor(XtDisplay(w),XtWindow(w),w->hyper.hand); cb.text = s->text; cb.length = s->length; cb.reason = HYPER_REASON; cb.event = event; XtCallCallbackList((Widget) w, w->hyper.hyper_callbacks, &cb); } else { XUndefineCursor(XtDisplay(w),XtWindow(w)); XtCallCallbackList((Widget) w, w->hyper.hyper_callbacks, (hyperCallbackStruct *) 0); } hilite(w,s == w->hyper.last_selected); w->hyper.last_cursor = s; } } /*-----------------------------------------------------------------------*/ /* Add a new text segment to the text */ /*-----------------------------------------------------------------------*/ static void add_to_text(w,word,type) HyperWidget w; char *word; int type; { text_segment *s = XtNew(text_segment); XCharStruct char_info; int dir,ascent,desc; text_segment *p,*q; s->next = NULL; s->text = (word?XtNewString(word):NULL); s->type = type; s->gc = (type == HIGHLIGHT ? w->hyper.highlight_gc : w->hyper.normal_gc); s->x = s->y = s->width = s->height = 0; s->length = (word?strlen(word):0); XTextExtents( (type == HIGHLIGHT ? w->hyper.highlight_font : w->hyper.normal_font), word, s->length, &dir,&ascent,&desc,&char_info); s->height = ascent + desc; s->desc = desc; s->width = char_info.width; if(p = w->hyper.first_seg) { while(p) { q=p; p=p->next; } q->next = s; } else w->hyper.first_seg = s; } /*-----------------------------------------------------------------------*/ /* Rebuild the text structure. Called when the font changes */ /*-----------------------------------------------------------------------*/ static void create_new_text(w) HyperWidget w; { text_segment *s = w->hyper.first_seg; w->hyper.first_seg = w->hyper.last_selected = w->hyper.last_cursor = NULL; while(s) { add_to_text(w,s->text,s->type); s = s->next; } free_text(s); calc_new_size(w); } /*-----------------------------------------------------------------------*/ /* Build the text. Gets the chars from the funtion "get_next_char" */ /* using "data" as a parameter */ /*-----------------------------------------------------------------------*/ static void set_text(w,get_next_char,data) Widget w; char (*get_next_char)(); XtPointer data; { HyperWidget hw = (HyperWidget) w; char word[MAX_LINE_SIZE]; int i = 0; char soh = hw->hyper.start_of_highlight; char eoh = hw->hyper.end_of_highlight; char c; int mode = NORMAL; free_text(hw->hyper.first_seg); hw->hyper.first_seg = hw->hyper.last_selected = hw->hyper.last_cursor = NULL; hw->hyper.grep_seg = NULL; hw->hyper.grep_txt = NULL; hw->hyper.grep_len = 0; hw->hyper.grep_off = 0; while(c = (get_next_char)(&data)) { /* New line */ if(c == '\n') { word[i]=0; if(i) add_to_text(hw,word,mode); add_to_text(hw,NULL,NEWLINE); i = 0; } /* Start of highlight */ else if(c == soh) { word[i]=0; if(i) add_to_text(hw,word,mode); mode = HIGHLIGHT; i = 0; } /* End of highlight */ else if(c == eoh) { word[i]=0; if(i) add_to_text(hw,word,mode); mode = NORMAL; i = 0; } else { if(c=='\t') c = ' '; word[i++] = c; if(i==MAX_LINE_SIZE) { word[--i]=0; add_to_text(hw,word,mode); i=0; word[i++] = c; } } } /* flush .. */ if(i) { word[i]=0; add_to_text(hw,word,mode); } calc_new_size(hw); if (XtIsRealized(w)) { XClearArea(XtDisplay(w), XtWindow(w), 0, 0, w->core.width, w->core.height, True); } } /*-----------------------------------------------------------------------*/ /* Create a new HyperWidget */ /*-----------------------------------------------------------------------*/ Widget CreateHyper(parent,name,al,ac) Widget parent; char *name; ArgList al; int ac; { return XtCreateWidget(name,hyperWidgetClass,parent,al,ac); } /*-----------------------------------------------------------------------*/ /* Load the text from a file */ /*-----------------------------------------------------------------------*/ /* provides chars to "set_text" routine */ static char get_from_file(f) FILE **f; { int n = getc(*f); return (n==EOF?0:(char)n); } /* Public routine */ void HyperLoadFile(hyper,fname) HyperWidget hyper; char *fname; { Widget widget = (Widget) hyper; extern char *sys_errlist[]; FILE *f = fopen(fname,"r"); if(f) { set_text(hyper,get_from_file,(XtPointer)f); fclose(f); } else { char msg[1024]; sprintf(msg,"%s: %s",fname,sys_errlist[errno]); XtWarning(msg); } } /*-----------------------------------------------------------------------*/ /* Load text from memory buffer */ /*-----------------------------------------------------------------------*/ /* provides chars to "set_text" routine */ static char get_from_buffer(buffer) char **buffer; { char c = **buffer; (*buffer)++; return c; } /* Public routine */ void HyperSetText(widget,text) HyperWidget widget; char *text; { set_text(widget,get_from_buffer,(XtPointer)text); } /*-----------------------------------------------------------------------*/ /* Specifies start and end of highlignt chars */ /*-----------------------------------------------------------------------*/ #ifdef _NO_PROTO void HyperSetTags(widget,start_highlight,end_highlight) HyperWidget widget; unsigned char start_highlight; unsigned char end_highlight; #else void HyperSetTags(HyperWidget widget, unsigned char start_highlight, unsigned char end_highlight) #endif { widget->hyper.start_of_highlight = start_highlight; widget->hyper.end_of_highlight = end_highlight; } /*-----------------------------------------------------------------------*/ /* convert a string to lower case */ /*-----------------------------------------------------------------------*/ static void lowcase(p) register char *p; { while(*p) { if(isupper(*p)) *p += 32; p++; } } /*-----------------------------------------------------------------------*/ /* Returns the text of the widget */ /* the memory is allocated. It must be freed by the application */ /* If include_tags if FALSE, the special characters are not returned */ /*-----------------------------------------------------------------------*/ #ifdef _NO_PROTO char *HyperGetText(widget,include_tags) HyperWidget widget; Boolean include_tags; #else char *HyperGetText(HyperWidget widget,Boolean include_tags) #endif { char *p ; text_segment *s = widget->hyper.first_seg; int len = 1; char soh[2]; char eoh[2]; soh[0] = widget->hyper.start_of_highlight; eoh[0] = widget->hyper.end_of_highlight; soh[1] = eoh[1] = 0; /* Get size of text */ while(s) { len += s->length?s->length:1; if(include_tags && s->type == HIGHLIGHT) len += 2; s = s->next; } p = XtMalloc(len); *p = 0; s = widget->hyper.first_seg; while(s) { if(s->length) { if(include_tags && s->type == HIGHLIGHT) strcat(p,soh); strcat(p,s->text); if(include_tags && s->type == HIGHLIGHT) strcat(p,eoh); } else strcat(p,"\n"); s=s->next; } return p; } /*-----------------------------------------------------------------------*/ /* Only for Motif */ /* If the widget is in a XmScrolledWindow, scroll it so the selection is */ /* visible */ /*-----------------------------------------------------------------------*/ static void show_selection(h) HyperWidget h; { #ifdef MOTIF #define SetArg(a,b) XtSetArg(al[ac],a,b);ac++ #define GetValues(w) XtGetValues(w,al,ac);ac=0 #define SetValues(w) XtSetValues(w,al,ac);ac=0 Widget clip = XtParent(h); Widget swin; Widget h_scroll; Widget v_scroll; int ac = 0; Position x_parent,y_parent; Position x_grep,y_grep; Dimension h_grep,w_grep; Position x_clip,y_clip; Dimension h_clip,w_clip; Position dv=0,dh=0; int min,max; int v_val,v_size,v_inc,v_page; int h_val,h_size,h_inc,h_page; Position x,y; Arg al[5]; /* check if selection exists */ if(!h->hyper.grep_seg) return; /* check if the widget is in a scrolled window */ /* the XnScrolledWindow creates a clip window */ /* The widget's parent is the clip window */ if(!clip) return; swin = XtParent(clip); if(!swin || !XmIsScrolledWindow(swin)) return; /* Get window scroll bars */ SetArg(XmNhorizontalScrollBar, &h_scroll); SetArg(XmNverticalScrollBar , &v_scroll); GetValues(swin); /* Get size of clip window and selection rect */ w_clip = clip->core.width; h_clip = clip->core.height; w_grep = h->hyper.grep_width; h_grep = h->hyper.grep_height; /* Get global coordinates of clip and selection rect */ XtTranslateCoords(clip,0,0,&x_clip,&y_clip); XtTranslateCoords(h,h->hyper.grep_x,h->hyper.grep_y,&x_grep,&y_grep); /* offset of selection within clip window */ x = x_grep - x_clip; y = y_grep - y_clip; /* selection y coordinate is not visible */ if( y < 0 || y + h_grep > h_clip) { /* the widget must be moved verticaly by dv pixels */ dv = (y + h_grep / 2) - h_clip / 2; SetArg(XmNminimum,&min); SetArg(XmNmaximum,&max); GetValues(v_scroll); XmScrollBarGetValues(v_scroll,&v_val,&v_size,&v_inc,&v_page); max -= v_size; if( dv + v_val > max ) dv = max - v_val; if( dv + v_val < min ) dv = min - v_val; } /* selection x coordinate is not visible */ if( x < 0 || x + w_grep > w_clip) { /* the widget must be moved horizontaly by dh pixels */ dh = (x + w_grep / 2) - w_clip / 2; SetArg(XmNminimum,&min); SetArg(XmNmaximum,&max); GetValues(h_scroll); XmScrollBarGetValues(h_scroll,&h_val,&h_size,&h_inc,&h_page); max -= h_size; if( dh + h_val > max ) dh = max - h_val; if( dh + h_val < min ) dh = min - h_val; } /* if the widget must be moved */ if(dv || dh) { Position x = h->core.x-dh; Position y = h->core.y-dv; /* move it */ SetArg(XmNx,x); SetArg(XmNy,y); SetValues(h); /* update scroll bars */ if(dv) XmScrollBarSetValues(v_scroll,v_val+dv,v_size,v_inc, v_page,TRUE); if(dh) XmScrollBarSetValues(h_scroll,h_val+dh,h_size,h_inc, h_page,TRUE); } #endif /* MOTIF */ } /*-----------------------------------------------------------------------*/ /* Clear previous selection */ /*-----------------------------------------------------------------------*/ static void clear_selection(hw) HyperWidget hw; { Widget w = (Widget) hw; if(hw->hyper.grep_seg) { if(XtIsRealized(w)) /* force a redraw */ XClearArea(XtDisplay(w),XtWindow(w), hw->hyper.grep_x, hw->hyper.grep_y, hw->hyper.grep_width, hw->hyper.grep_height, TRUE); } hw->hyper.grep_seg = NULL; } /*-----------------------------------------------------------------------*/ /* Set the new selection */ /*-----------------------------------------------------------------------*/ static void set_selection(w) HyperWidget w; { Widget widget = (Widget) w; if(w->hyper.grep_seg) { text_segment *s = w->hyper.grep_seg; char *p = s->text; XCharStruct char_info; int dir,ascent,desc; /* get size of the begining of the segment, up to the found string */ XTextExtents( (s->type == HIGHLIGHT ? w->hyper.highlight_font : w->hyper.normal_font), s->text, w->hyper.grep_off, &dir,&ascent,&desc,&char_info); w->hyper.grep_x = s->x + char_info.width; w->hyper.grep_y = s->y + desc; w->hyper.grep_height = s->height; /* Get size of the selection */ XTextExtents( (s->type == HIGHLIGHT ? w->hyper.highlight_font : w->hyper.normal_font), w->hyper.grep_txt, w->hyper.grep_len, &dir,&ascent,&desc,&char_info); w->hyper.grep_width = char_info.width; /* force update */ if(XtIsRealized(widget)) XClearArea(XtDisplay(widget),XtWindow(widget), w->hyper.grep_x, w->hyper.grep_y, w->hyper.grep_width, w->hyper.grep_height, TRUE); } } /* size of regexp buffer */ #define ESIZE 1024 /*-----------------------------------------------------------------------*/ /* if you have regexp, define USE_REGEXP */ /* NOTE : since regexp variables and functions are not static */ /* you can have some problems if you use the same names or include */ /* regexp somewhere else */ /*-----------------------------------------------------------------------*/ #ifdef USE_REGEXP /* regexp macros ... see "man regexp" */ #define INIT register char *sp = instring; #define GETC() (*sp++) #define PEEKC() (*sp) #define UNGETC(c) (--sp) #define RETURN(c) return; #define ERROR(c) printf(stderr,"Warning regexp error %d\n",c) #include #else /*-----------------------------------------------------------------------*/ /* If we don't have regexp mimic it. */ /* Just find plain text using strncmp. no regular expression matching */ /*-----------------------------------------------------------------------*/ static char *loc1,*loc2; static int len; static compile(w,buf,end) char *w,*buf; int end; { strcpy(buf,w); len = strlen(w); } static step(w,buf) char *w; char *buf; { loc1 = w; while(*loc1) { if(strncmp(loc1,buf,len) == 0) { loc2 = loc1+len; return TRUE; } loc1++; } return FALSE; } #endif /*-----------------------------------------------------------------------*/ /* Select a word in the hyper widget */ /* word : word to find ( or regular expression if USE_REGEX is defined) */ /* ignore_case : if TRUE ignore case in comparaison */ /* from_start : if TRUE search from start of text, else search from */ /* current selection */ /* wrap: if TRUE, continue search from the begining of text if the end */ /* is reached */ /*-----------------------------------------------------------------------*/ #ifdef _NO_PROTO Boolean HyperGrep(widget,word,ignore_case,from_start,wrap) HyperWidget widget; char *word; Boolean ignore_case; Boolean from_start; Boolean wrap; #else Boolean HyperGrep(HyperWidget widget, char *word, Boolean ignore_case, Boolean from_start, Boolean wrap) #endif { char *w = word; char *p; int offset,from,to; text_segment *s; char expbuf[ESIZE]; if(!widget->hyper.first_seg) return; if(ignore_case) { /* if ignore case, change word to lower case */ w = XtNewString(word); lowcase(w); } /* compile the regular expression */ compile(w,expbuf,&expbuf[ESIZE],'\0'); if(ignore_case) XtFree(w); /* if from_start or no previous selection, start from first segment */ if(from_start || widget->hyper.grep_seg == NULL) { offset=0; wrap = FALSE; s = widget->hyper.first_seg; } else { /* start from last selection */ offset = widget->hyper.grep_off + widget->hyper.grep_len; s = widget->hyper.grep_seg; } for(;;) { if(s->text) { if(ignore_case) { /* if ignore case, change segment to lower case */ p = XtNewString(s->text); lowcase(p); } /* search the string */ if(step(p+offset,expbuf)) { /* if found ...*/ /* clear previous selection */ clear_selection(widget); widget->hyper.grep_seg = s; widget->hyper.grep_off = offset + (loc1-(p+offset)); widget->hyper.grep_txt = s->text + widget->hyper.grep_off; widget->hyper.grep_len = loc2-loc1; /* set new selection */ set_selection(widget); /* make it visible */ show_selection(widget); if(ignore_case) XtFree(p); return TRUE; } if(ignore_case) XtFree(p); } offset = 0; s = s->next; /* if end of text and wrap mode, go to start of text */ if(!s) if(wrap) { wrap = FALSE; s = widget->hyper.first_seg; } else break; } return FALSE; } axe-6.1.2.orig/Help/Hyper.h100644 243 144 6261 5550743646 14141 0ustar joostusers/*==================================================================*/ /* */ /* HyperWidget */ /* */ /* B.Raoult (mab@ecmwf.co.uk) Oct.91 */ /* */ /* Hyper text like widget. */ /* */ /*==================================================================*/ #ifndef HYPER_H #define HYPER_H /* If you define MOTIF, the widget will inherit proprieties from the XmPrimitive class : Help Callback, user data, ... */ /* #define MOTIF */ /* If your machine got regexp.h */ /*#define USE_REGEXP*/ extern WidgetClass hyperWidgetClass; typedef struct _HyperClassRec * HyperWidgetClass; typedef struct _HyperRec * HyperWidget; /* * Define resource strings for the Hyper widget. */ #define XtNhighlightFont "highlightFont" #define XtNnormalFont "normalFont" #define XtNhighlightColor "highlightColor" #define XtNselectColor "selectColor" #define XtNnormalColor "normalColor" #define XtNactivateCallback "activateCallback" #define XtNhyperCallback "hyperCallback" #define XtNzoomEffect "zoomEffect" #define XtCZoom "Zoom" #define XtNstartHighlight "startHighlight" #define XtNendHighlight "endHighlight" #define XtCTagChar "TagChar" #define XtNzoomSpeed "zoomSpeed" #define XtCZoomSpeed "ZoomSpeed" /* Same as in StringDfs.h, so expect to get it form there (JKW) #define XtCMargin "Margin" */ #define XtNmargin "margin" /* Callback structure */ #define HYPER_REASON 1 typedef struct { int reason; /* always = HYPER_REASON */ XEvent *event; /* event */ char *text; /* pointer on highlighted text selected (read only) */ int length; /* length of selected text */ } hyperCallbackStruct; #ifdef _NO_PROTO extern Widget CreateHyper(); extern void HyperLoadFile(); extern void HyperSetText(); extern void HyperSetTags(); extern Boolean HyperFind(); extern char *HyperGetText(); #else #if defined(__cplusplus) || defined(c_plusplus) extern "C" { #endif extern Widget CreateHyper(Widget parent, char *name, ArgList al, int ac); extern void HyperLoadFile(HyperWidget widget, char *fname); extern void HyperSetText(HyperWidget widget, char *text); extern void HyperSetTags (HyperWidget widget, unsigned char start_highlight, unsigned char end_highlight); Boolean HyperGrep(HyperWidget widget, char *word, Boolean ignore_case, Boolean from_start, Boolean wrap); char *HyperGetText(HyperWidget widget, Boolean include_tags); #if defined(__cplusplus) || defined(c_plusplus) } #endif #endif /* _NO_PROTO */ #define XtIsHyper(w) XtIsSubclass(w,hyperWidgetClass) #endif /* HYPER_H */ axe-6.1.2.orig/Help/HyperP.h100644 243 144 6622 5550743650 14255 0ustar joostusers/*==================================================================*/ /* */ /* HyperWidget */ /* */ /* B.Raoult (mab@ecmwf.co.uk) Oct.91 */ /* */ /* Hyper text like widget. */ /* */ /*==================================================================*/ #ifndef HYPERP_H #define HYPERP_H #ifdef MOTIF #include #endif /* Hyper class : no new fileds */ typedef struct _HyperClassPart{ int ignore; } HyperClassPart; typedef struct _HyperClassRec{ CoreClassPart core_class; #ifdef MOTIF XmPrimitiveClassPart primitive_class; #endif HyperClassPart hyper_class; } HyperClassRec; extern HyperClassRec hyperClassRec; /* Text segment */ typedef struct text_segment { struct text_segment *next; /* Next segment */ int type; /* NEWLINE, NORMAL or HIGHLIGHT */ char *text; /* pointer to text */ int length; /* length of text */ int desc; /* font descent */ GC gc; /* GC used to draw text */ Position x,y; /* Position of drawn text */ Dimension width,height; /* Size of drawn text */ } text_segment; typedef struct _HyperPart { Cursor hand; /* Selecting cursor shape */ Pixel normal_color; /* Color of the normal text */ Pixel highlight_color; /* Color of the highlighted text */ Pixel select_color; /* Color of the selected text */ XFontStruct *normal_font; /* Font of the normal text */ XFontStruct *highlight_font; /* Font of the highlighted text */ GC normal_gc; /* Gc for the normal text */ GC highlight_gc; /* Gc for the highlighted text */ GC xor_gc; /* Gc for zoom */ GC select_gc; /* Gc for select */ Boolean zoom; /* zoom effect when selected */ int speed; /* zoom speed */ char start_of_highlight; /* start of highlighted text mark */ char end_of_highlight; /* end of highlighted text mark */ int margin; /* margins size */ text_segment *grep_seg; /* segment where found text is */ char *grep_txt; /* pointer to found text */ int grep_len; /* length of found text */ int grep_off; /* offset of found text */ Position grep_x; /* rectangle of founf text*/ Position grep_y; Dimension grep_width; Dimension grep_height; text_segment *first_seg; /* the text segments */ text_segment *last_selected; /* last selected segment */ text_segment *last_cursor; /* last under cursor segment */ XtCallbackList activate; /* callback list */ XtCallbackList hyper_callbacks; } HyperPart; typedef struct _HyperRec { CorePart core; #ifdef MOTIF XmPrimitivePart primitive; #endif HyperPart hyper; } HyperRec; #endif /* HYPERP_H */ axe-6.1.2.orig/Help/Imakefile100644 243 144 3207 5550743651 14503 0ustar joostusers#include "../Axe.tmpl" #include "../Axe.rules" SRCS = axinfo.c Hyper.c OBJS = axinfo.o Hyper.o DEFINES = -D_NO_PROTO EXTRA_INCLUDES = -I../Widgets LOCAL_LDFLAGS = ${XAW3D_LDFLAGS} ${TABLE_LDFLAGS} LOCAL_LIBRARIES = ../Widgets/libaxe.a ${XAW3D_LIBS} ${TABLE_LIBS} SYS_LIBRARIES = XawClientLibs DEPLIBS = ../Widgets/libaxe.a XawClientDepLibs ComplaxeProgramTarget(axinfo,${InfoBindir},${InfoMandir}) InstallAxeDefaults(Axinfo,${InfoAppdir}) InstallMultiple(axe.info axe.info-1 axe.info-2,${InfoLibdir}) /* * It ought to be possible to use NullParameter in place of * -DDUMMY but that doesn't work everywhere, e.g. HP-UX 8.07 */ SpecialObjectRule(axinfo.o,version.h,-DDUMMY) all:: Axinfo.ad MakeXaw3d(axinfo) Axinfo.ad: Axinfo.ad.sed version.h ../Axe.tmpl sed -e "s/VERSION/`sed -e 's/.*VERSION \(.*\)/\1/;q' Axinfo.ad info: axe.texi.sed axis.texi gnrl.texi bind.texi cust.texi lang.texi chng.texi sed -e 's/^A4//' axe.texi ${HOME}/texinfo-3.1/makeinfo/makeinfo axe.texi A4: axe.texi.sed gnrl.texi bind.texi cust.texi lang.texi sed -e 's/^A4//' axe.texi ${HOME}/texinfo-3.1/util/texi2dvi axe.texi letter: axe.texi.sed gnrl.texi bind.texi cust.texi lang.texi sed -e 's/^A4/@c/' axe.texi ${HOME}/texinfo-3.1/util/texi2dvi axe.texi A4ps: A4 dvips -M axe psselect -p1,29,2-28 axe.ps axe.A4.ps letterps: letter dvips -M axe psselect -p1,31,2-30 axe.ps axe.letter.ps A4book: A4ps psbook axe.A4.ps | psnup -2 | psbind -2s >A4book.ps A4master:A4ps psbook axe.A4.ps | psnup -2 >A4master.ps axe-6.1.2.orig/Help/axe.info100644 243 144 2213 5550557107 14317 0ustar joostusersThis is Info file axe.info, produced by Makeinfo-1.55 from the input file axe.texi.  Indirect: axe.info-1: 85 axe.info-2: 45461  Tag Table: (Indirect) Node: Top85 Node: Axinfo3339 Node: HyperText4315 Node: Tree7216 Node: AxinfoCmd8921 Node: CustomAxinfo10582 Node: CustomHyper11463 Node: CustomTree13759 Node: InfoReader14445 Node: Introduction15205 Node: Window16069 Node: Editing19151 Node: Selection20926 Node: Buttons24171 Node: Keyboard25228 Node: Bindings26641 Node: Customise29025 Node: Resources29790 Node: AppRsrcs33813 Node: AxeWinRsrcs35599 Node: AxeEdRsrcs36367 Node: AxeTextRsrcs40718 Node: AxeiiTextRsrcs41562 Node: SampRsrcs44223 Node: Actions45461 Node: SampBinds50819 Node: Minibuffer53269 Node: Minimenu59161 Node: Macro62440 Node: Undo64346 Node: Server66481 Node: Popups68731 Node: Nominator69421 Node: NumPad73147 Node: ControlCode73951 Node: Confirmer75026 Node: Preferences76258 Node: Help77149 Node: Language78238 Node: Builtins80592 Node: Utilities81831 Node: UseLang83267 Node: Changes87165 Node: Change 187835 Node: Change 288570 Node: Change 389001 Node: Change 490189  End Tag Table axe-6.1.2.orig/Help/axe.info-1100644 243 144 130625 5550557107 14526 0ustar joostusersThis is Info file axe.info, produced by Makeinfo-1.55 from the input file axe.texi.  File: axe.info, Node: Top, Next: Axinfo Index to Help System for aXe 6.0 ******************************** The information in this on-line help is also available in enhanced form as a printable User Guide. Check availability with your system administrator. Click mouse button 1 when the mouse pointer is over (it will change to a pointing hand) the highlighted text *Axinfo* at the top of the menu below or beside *Next:* towards the bottom of the window for instructions on how to use axinfo, aXe's help system, if you have not used it before. * Menu: * Axinfo:: About this program * Introduction:: Chapter 1 : A beginner's guide to aXe * Customise:: Chapter 2 : How to customise aXe * Popups:: Chapter 3 : Secondary popup windows * Language:: Chapter 4 : Extension language * Changes:: Changes since the previous release About this program * HyperText:: The hypertext window * Tree:: The tree window * AxinfoCmd:: The axinfo command * CustomAxinfo:: How to customise axinfo How to customise axinfo * CustomHyper:: How to customise the hypertext window * CustomTree:: How to customise the tree window * InfoReader:: Using axinfo to read other info files A beginner's guide to aXe * Window:: The components of an aXe window * Editing:: Basic editing * Selection:: Selecting text using the mouse * Buttons:: Buttons instead of menus * Keyboard:: Using the keyboard for speed Using the keyboard for speed * Bindings:: The default key bindings How to customise aXe * Resources:: Resources specific to aXe * SampRsrcs:: Examples of resource settings * Actions:: Actions specific to aXe * SampBinds:: Examples of binding actions to keystrokes * Minibuffer:: How to us the minibuffer * Macro:: Defining and using a keyboard macro * Undo:: How the undo mechanism works * Server:: aXe as a server of windows Resources specific to aXe * AppRsrcs:: Application resources * AxeWinRsrcs:: AxeWindow widget resources * AxeEdRsrcs:: AxeEditor widget resources * AxeTextRsrcs:: AxeText widget resources * AxeiiTextRsrcs:: AxeiiText widget resources How to us the minibuffer * Minimenu:: The minibuffer menu Secondary popup windows * Nominator:: The file selector * NumPad:: The numeric keypad * ControlCode:: The control code selector * Confirmer:: The confirmer * Preferences:: The preferences setter * Help:: The help system Extension language * Builtins:: Built in extension language commands * Utilities:: Other extension language commands * UseLang:: Using the extension language Changes since the previous release * Change 1:: Changes to the help system * Change 2:: Deleting the selection on text entry * Change 3:: Changes to the extension language * Change 4:: Setting of the WM_COMMAND property  File: axe.info, Node: Axinfo, Next: HyperText, Prev: Top, Up: Top About this program ================== Axinfo is a hypertext help system for aXe that presents most of the information contained in the aXe User Guide. The text is organised in units called nodes that correspond to the chapters, sections and subsections of the User Guide. The information in this section and its subsections, and that on the changes since the previous release are not present in the User Guide. Axinfo has two windows. The one you are reading this in is the *HyperText* window. The other displays the relationships of the nodes in the form of a tree diagram. Click on one of the highlighted words with mouse button 1 to proceed. If you have not used *axinfo* before then choose *HyperText*. * Menu: * HyperText:: The hypertext window * Tree:: The tree window * AxinfoCmd:: The axinfo command * CustomAxinfo:: How to customise axinfo  File: axe.info, Node: HyperText, Next: Tree, Prev: Axinfo, Up: Axinfo The hypertext window ==================== A highlighted word within this window indicates that information on the named topic can be obtained by positioning the mouse pointer over the text and clicking mouse button 1. Each node that is displayed is related to others by means of pointers named *Next*, *Prev* and *Up*. When a node is displayed its pointers are permanently on show in a separate section towards the bottom of the window. The highlighted text beside a pointer name is also sensitive as described above, enabling direct jumps to be made to the related nodes, and as the mouse pointer moves through it a brief reminder of what the node covers is displayed in the section underneath. *Next* and *Prev* will generally point to another node at the same level, while *Up* will generally point to a node at a higher level. Thus if you were looking at the node corresponding to section 1.3 of the User Guide then *Next* would lead to that corresponding to 1.4, *Prev* to that corresponding to 1.1, and *Up* to that corresponding to Chapter 1. The *Next* pointers have been set up so that always following them will result in visiting the nodes in the order that they appear in the User Guide. Pointers called *Top* and *Last* are also provided. *Top* ensures that a jump back to the overall index is always possible while *Last* allows the node most recently visited before the current one to be displayed again. Depending on how the current node was reached *Last* can be different from *Prev*. A node may have a menu appearing at the end of its text. The menu items correspond to subsections within the corresponding section of the User Guide. Clicking on the highlighted part of a menu item causes the help for the topic to be displayed. The node called *Top* is largely a menu consisting of items for every other node in the help system. Thus, if you know where the information is that you require you can access it faster by directly selecting the appropriate item from the menu than by navigating your way to it via pointers. Other nodes can also be accessed through cross references as well as by menus and the pointers described above. A cross reference appears in the text as follows: *Note Top::. That really is a cross reference, so clicking on `Top' will result in the overall index being displayed. If you did that then you would be able to get back to this node by selecting the *Last* pointer from the *Top* node. There are two buttons in the bottom part of the window. *Quit* should be obvious. The *Tree* button causes a window displaying the node hierarchy as a tree to be popped up. That window is described in the next section. If there is no *Tree* button then it means that your system is running an old version of X that doesn't support the widget that is used to display the tree.  File: axe.info, Node: Tree, Next: AxinfoCmd, Prev: HyperText, Up: Axinfo The tree window =============== This window is not available under versions of X prior to Release 5. The tree of the help hierarchy contains a button for each node of help. At any time the one for the node that is displayed in this window is highlighted. Clicking on a button causes the text relating to the node to be displayed in this window. If you do it now the text you are looking at will be replaced, but you can always get it back by clicking on the *Last* pointer. Whenever the displayed node changes its button is centred in the tree window. As the mouse pointer enters a button a reminder of what the corresponding node covers is displayed in a section at the bottom of the window. If the window is not big enough to show the whole tree it can be scrolled, in two dimensions if necessary, by pressing any mouse button over the background and dragging in the direction you want the tree to move - just like placing your hand on a piece of paper and pushing or pulling it. The *Delete* button in the lower part of the window deletes just the tree window if this window also exists, otherwise the entire application is terminated. The tree window can exist on its own because it is possible to specify that *axinfo* be started up that way (*Note AxinfoCmd::). If the application were not terminated in that situation there would be no way of subsequently obtaining either window. The tree window is useful for letting you see how the text that is currently displayed fits into the overall structure and for enabling fast jumps to be made into the help if you know where the information you require is located.  File: axe.info, Node: AxinfoCmd, Next: CustomAxinfo, Prev: Tree, Up: Axinfo The axinfo command ================== `axinfo' is a standalone application for browsing aXe's information system. If it is not already running aXe starts it up when an item is selected form the Help menu. *Note InfoReader:: explains how axinfo can be used to read other documentation created using Texinfo. The `axinfo' command has the following form:- axinfo [-node node] [-rows rows] [-columns columns] [-tree] [file] With no options axinfo creates the Hypertext window (*Note HyperText::) displaying the *Top* node. -node node permits a named node within the help system to be displayed on startup. The names which can be specified are the words which appear highlighted in the text of the help. Example: axinfo -node 'AxinfoCmd' axe.info would start up `axinfo' with the text you are looking at now displayed. -rows rows permits the height of the hypertext window to be specified. *Note CustomAxinfo:: has more information. -columns columns permits the width of the hypertext window to be specified. *Note CustomAxinfo:: has more information. -tree causes the tree window (*Note Tree::) to be created. The hypertext window (*Note HyperText::) is not created unless a node is specified using the `-node' option. This option is ignored under versions of X prior to Release 5. file is the name of the Texinfo file containing the information to be browsed. It is only required if `axinfo' is not being used to read the documentation for aXe (*Note InfoReader::).  File: axe.info, Node: CustomAxinfo, Next: CustomHyper, Prev: AxinfoCmd, Up: Axinfo How to customise axinfo ======================= The main widget structure of axinfo is as follows:- axinfo (ApplicationShell) hyperwin (TopLevelShell) treewin (TopLevelShell) It needs to be emphasised that there is no main window corresponding to the application shell, and hence the keyword `-geometry' which applies to that widget has no effect. *Note CustomHyper:: describes an alternative of way of changing the size of the hypertext window. If you want to alter the size of the tree window then you must set its geometry resource explicitly. * Menu: * CustomHyper:: How to customise the hypertext window * CustomTree:: How to customise the tree window * InfoReader:: Using axinfo to read other info files  File: axe.info, Node: CustomHyper, Next: CustomTree, Prev: CustomAxinfo, Up: CustomAxinfo How to customise the hypertext window ===================================== The hypertext window (*Note HyperText::) has the following widget structure. The names in parentheses following the widget names are the widget class names. hyperwin (TopLevelShell) pane (Paned) view (Viewport) hyper (Hyper) links (Hyper) hpane (Paned) quit (Command) map (Command) info (Label) Apart from *hyper* all of the widgets are standard Athena widgets and so won't be described here. The size of the window reflects the size of the main area of text in units of characters. The default size is 24 x 80. Changing the size of the window should preferrably be done by setting hyperwin's `rows' and `columns' resources in order to fit in with the way window manager resizing has been organized to report the size in units of characters. The keywords `-rows' and `-columns' have been defined to be equivalent to the resources `*hyperwin.rows' and `*hyperwin.columns'. In reality it does not make sense to alter the width as the text will not be wider than 80, and if it is made too small text will be lost at the right hand margin as the Hyper widget does not perform wrapping. Example: axinfo -rows 50 The following Hyper widget resources are available for customisation:- normalFont is the font to be used for normal text. The default is `7x13'. highlightFont is the font to be used for highlighted text. The default is `7x13bold'. normalColor is the colour to be used for normal text. The default is `black'. highlightColor is the colour to be used for highlighted text. The default is `red'. selectColor is the colour to be used for selected text, i.e. when mouse button 1 is pressed over highlighted text. The default is `blue'. Although the Hyper widget is capable of displaying any font the text is prepared on the assumption that a fixed width (character cell or monospaced) font will be used. Specifying a proportional font will probably result in ragged layouts in various places.  File: axe.info, Node: CustomTree, Next: InfoReader, Prev: CustomHyper, Up: CustomAxinfo How to customise the tree window ================================ The tree window has the following widget structure. The names in parentheses following the widget names are the corresponding widget class names. treewin (TopLevelShell) pane (Paned) form (Form) porthole (Porthole) tree (Tree) bpane (Paned) quit (Command) close (Command) info (Label)  File: axe.info, Node: InfoReader, Next: Introduction, Prev: CustomTree, Up: CustomAxinfo Using axinfo to read other info files ===================================== Although the motivation for developing axinfo was to improve the information available in aXe the fact that it is based on the GNU Texinfo system should mean that axinfo is capable of reading the information files produced by that system for other software. At this moment, however, that is only true to the extent that axinfo can read a single information file at a time. This is achieved by setting the `infoPath' resource to state where the info file is to be found, and by naming it on the command line, e.g. axinfo -xrm '*infoPath:/usr/local/doc/texinfo/info' info-stnd.info  File: axe.info, Node: Introduction, Next: Window, Prev: InfoReader, Up: Top A beginner's guide to aXe ************************* aXe's primary aim is to provide an easy introduction to text editing, but it is hoped that it is also sufficiently flexible to continue to meet most users' needs as their editing skills develop. aXe can be used to edit several files at once, with each file being allocated to an editing buffer. An aXe window may support multiple buffers, but only one will be visible at any given time. The user determines the allocation of files to buffers, and hence to windows. * Menu: * Window:: The components of an aXe window * Editing:: Basic editing * Selection:: Selecting text using the mouse * Buttons:: Buttons instead of menus * Keyboard:: Using the keyboard for speed  File: axe.info, Node: Window, Next: Editing, Prev: Introduction, Up: Introduction The components of an aXe window =============================== An aXe window consists of five visible parts. From top to bottom they are: `Filename' A line showing the name of the file currently being edited in the window. If a file has not been associated with this window then 'No name' will be displayed. The name is preceded by '*' if the text in the Editing buffer (below) contains unsaved changes. '~' at the beginning of the filename is shorthand for your home directory. `Information bar' A line that is updated with brief help explaining the action that would be performed if mouse button 1 were to be operated with the mouse pointer in the current position. If an action can be performed directly from the keyboard then the help line will contain a description of the keystroke(s) that would achieve it. It is enclosed in square brackets, e.g. [ Ctrl-a ]. *Note Using the keyboard for speed: Keyboard, for an explanation of what that means. The information bar is also used for displaying information arising from some actions, and for some error messages. `Menu bar' A row of buttons having associated pulldown menus. Pressing and holding down mouse button 1 whilst a button is highlighted (by moving the mouse pointer onto it) will reveal the menu. The *Show* menu shows the names of all of the files being edited - the current file in the window from which the menu was popped up has a tick against it at the right hand side of the entry, and dividing lines are drawn to group the files associated with individual windows. `Editing buffer' An area displaying the text of the file that is currently being edited in the window. It may the topmost of a stack of buffers associated with the window, in which case a different buffer is made current by selecting its entry from the *Show* menu. When an aXe window is resized all of the the adjustment in the vertical direction is applied to this component. Also, the size of the other components is discounted by the window manager and the information displayed during resizing is the size of the editing buffer in terms of characters, rather than pixels. In other words the editing buffer can only be resized in character increments. `Minibuffer' An area containing a menu button and a 1-line text buffer, called the minibuffer (*Note How to use the minibuffer: Minibuffer.) The menu associated with the button provides convenient access to some of the more complicated facilities that are only available via the minibuffer. The selected ones feed the contents of the editing buffer to an external Unix command for processing and display the output, if any, in a fresh window. The user can optionally suppress display of the Filename, Information bar and Minibuffer components. *Note suppressFilename: AxeEdRsrcs, for details.  File: axe.info, Node: Editing, Next: Selection, Prev: Window, Up: Introduction Basic editing ============= Traversing the text in the editing buffer and making changes to it can either be carried out from the keyboard or by using the mouse. The current position, or insertion point, in the text is denoted by a caret (^). It lies between characters and is initially right at the top of the file before the first character. In order to edit using the keyboard, the mouse pointer - the symbol that moves around the screen as the mouse is moved - must lie somewhere within the editing buffer area. Note that the pointer symbol changes depending on which part of the screen it is over. When it is in an editable text area, i.e. the editing buffer or the minibuffer it will have the appearance of the letter I. With the pointer in the editing buffer area, typing on the keyboard will cause the characters typed to be inserted at the insertion point. The character immediately to the left of the insertion point can be erased by using the Delete key. The insertion point can be moved one line or one character at a time by using the cursor (arrow) keys. An easier way to move the insertion point, especially if you want it to be some way away from the current position, is to move the mouse until the vertical bar of the pointer lies over the character which is to be to the right of the insertion point. With this done, quickly press and release the left hand button on the mouse (note that the information line is updated to show the line number of the chosen line). Slightly moving the mouse while the button is pressed down may result in one or more characters becoming highlighted. If this happens, you can either try again or simply ignore it for the time being.  File: axe.info, Node: Selection, Next: Buttons, Prev: Editing, Up: Introduction Selecting text using the mouse ============================== Some features involve the notion of a *selection*. A selection is identifiable as an area of highlighted text. You may already have accidentally created one by moving the mouse with the left button pressed down when attempting to adjust the insertion point. So, one way to create a selection is to move the mouse until the pointer is where you want the selection to start, then press and hold down the left mouse button. Now move the mouse with the button still held down and the text between the starting point and the current pointer position will be highlighted, i.e. selected. Release the mouse button when you are satisfied with the selection you have made. If you didn't quite get it right, a selection can be adjusted at either end. Just move the pointer to the new end point and click (quickly press and release) the right hand mouse button, or press it down and sweep out the extension while continuing to hold the button down. Another way to make a selection is to move the pointer to where you want it to start and click the left hand mouse button, then move the pointer to the required end point and adjust with the right hand button. A selection can be cancelled by clicking the left hand mouse button within the buffer, but remember that doing so will likely affect the insertion point. Once you have mastered using the mouse as just described you might like to try performing multiple clicks to make some selections. Rapidly clicking mouse button 1 the following number of times will make a selection as follows: 2. selects the word under the pointer. Words are delimited by Spaces, Tabs and Carriage Returns. 3. selects the line under the pointer. 4. selects the paragraph under the pointer. A paragraph boundary is defined by two Carriage Returns with only Spaces or Tabs between them. 5. selects the entire text. The reason for making a selection is so that some operation can be applied to it, e.g. deletion, or copying to another part of the file. Copying can either be carried out by using the *Selection* entry from the *Insert* menu or by clicking the middle mouse button. The selection will be inserted at the current insertion point. The insertion point will be at one of the ends of the selection immediately after it has been made, so will normally have to be moved. Using the mouse to move the insertion point will cause the selection to be unlighted, but it will remain available for insertion until another one is made. You should be aware that the selection mechanism is not peculiar to this application - many other X applications support it - but there can only be one selection across all applications at any one time. Selecting *Selection* from the *Insert* menu [the notation *Insert:Selection* for indicating a choice from a menu will be used in future], however, will result in the selection, whichever application owns it, being inserted at the current insertion point. And a selection made in this application can be transferred to some other by using its insertion method - probably clicking the middle mouse button.  File: axe.info, Node: Buttons, Next: Keyboard, Prev: Selection, Up: Introduction Buttons instead of menus ======================== After a time you may find it too slow to execute operations that you perform a lot using the menus. If this is the case then you might like to try the optional button interface in which an array of buttons - there is a button for every menu bar menu entry - is permanently displayed underneath the menu bar, making access to the operations that much faster. One way of requesting the button interface is to start aXe by using the command `axe -buttons'. *Note buttons: AxeEdRsrcs, for an alternative. To use a button simply click mouse button 1 when the button has been highlighted by moving the mouse pointer on top of it. It is not necessary to display the complete set of buttons - they do take up a lot of space. *Note buttonList: AxeEdRsrcs, for details. A good compromise is to have your most frequently used operations available via buttons; the less frequently used will still be available via the menus.  File: axe.info, Node: Keyboard, Next: Bindings, Prev: Buttons, Up: Introduction Using the keyboard for speed ============================ As you become even more proficient at editing you may want to speed things up by doing more from the keyboard. Many of the operations implemented via the menus (and buttons) have keyboard equivalents, e.g. Ctrl-a Beginning Of Line Ctrl-a means:- press and hold down the Control key, and while it is held down press and release the A key, after which the Control key can be released. Other operations involve the use of the Meta key. However, keyboards don't have a key labelled Meta, so some other key, which varies from machine to machine, performs the role. It is Alt on Acorns, Compose Character on Vaxstations, and either of the ones at the ends of the Space Bar on Suns, viz. Left and Right on Sun 3s, and the keys with a diamond shape as label on Type 4 and Type 5 keyboards. The Meta key is used similarly to the Control key. *Note The default key bindings: Bindings, for a list of the default bindings. Some of the operations that are available via the menus and buttons do not have default bindings. *Note Actions specific to aXe: Actions, for a description of how they too can be associated with key strokes. The information there assumes a knowledge of how to use and specify X resources. * Menu: * Bindings:: The default key bindings  File: axe.info, Node: Bindings, Next: Customise, Prev: Keyboard, Up: Keyboard The default key bindings ------------------------ The default key bindings are patterned after those in the EMACS text editor: Ctrl-a Beginning Of Line Meta-b Backward Word Ctrl-b Backward Character Meta-f Forward Word Ctrl-d Delete Next Character Meta-i InsertFile Ctrl-e End Of Line Meta-k Kill To End Of Paragraph Ctrl-f Forward Character Meta-q Form Paragraph Ctrl-g Multiply Reset Meta-v Previous Page Ctrl-h Delete Previous Character Meta-y Insert Current Selection Ctrl-j Newline And Indent Meta-z Scroll One Line Down Ctrl-k Kill To End Of Line Meta-d Delete Next Word Ctrl-l Redraw Display Meta-D Kill Word Ctrl-m Newline Meta-h Delete Previous Word Ctrl-n Next Line Meta-H Backward Kill Word Ctrl-o Newline And Backup Meta-< Beginning Of File Ctrl-p Previous Line Meta-> End Of File Ctrl-r Search/Replace Backward Meta-] Forward Paragraph Ctrl-s Search/Replace Forward Meta-[ Backward Paragraph Ctrl-t Transpose Characters Ctrl-u Multiply by 4 Meta-Delete Delete Previous Word Ctrl-v Next Page Meta-Shift Delete Kill Previous Word Ctrl-w Kill Selection Meta-Backspace Delete Previous Word Ctrl-y Unkill Meta-Shift Backspace Kill Previous Word Ctrl-z Scroll One Line Up In addition, the pointer may be used to cut and paste text: Button 1 Down Start Selection Button 1 Motion Adjust Selection Button 1 Up End Selection (cut) Button 2 Down Insert Current Selection (paste) Button 3 Down Extend Current Selection Button 3 Motion Adjust Selection Button 3 Up End Selection(cut) Since all of these key and pointer bindings are set through the translations and resource manager, the user and the application programmer can modify them by changing the Text widget's translations resource (*Note Actions specific to aXe: Actions, for examples of the mechanism).  File: axe.info, Node: Customise, Next: Resources, Prev: Bindings, Up: Top How to customise aXe ******************** Like most X applications, aXe is highly customisable through resources. What follows makes the assumption that you know what resources are and how to apply the information that is presented. * Menu: * Resources:: Resources specific to aXe * SampRsrcs:: Examples of resource settings * Actions:: Actions specific to aXe * SampBinds:: Examples of binding actions to keystrokes * Minibuffer:: How to us the minibuffer * Macro:: Defining and using a keyboard macro * Undo:: How the undo mechanism works * Server:: aXe as a server of windows  File: axe.info, Node: Resources, Next: AppRsrcs, Prev: Customise, Up: Customise Resources specific to aXe ========================= Before you can perform any customisation through resources it is necessary to know the widget structure of aXe. The hierarchy, including the first editing window, is shown below. All widgets are listed by instance and class name. Most of the widgets are custom widgets developed specifically for aXe. Where this is the case the superclass is enclosed in parentheses. The file server window is either fileServer FileNominatorWindow (TransientShell) or server TopLevelShell with substructure table XpTable waiter Command show AxeMenuButton (MenuButton) poleaxe Command help Command The following menus are childern of the application shell, and are shared by all editing windows. mMove AxeSimpleMenu (Simplemenu) mSearch AxeSimpleMenu (Simplemenu) mInsert AxeSimpleMenu (Simplemenu) mDelete AxeSimpleMenu (Simplemenu) mHelp AxeSimpleMenu (Simplemenu) mMisc AxeSimpleMenu (Simplemenu) mWindow AxeSimpleMenu (Simplemenu) mBuffer AxeSimpleMenu (Simplemenu) mShow AxeSimpleMenu (Simplemenu) mFile AxeSimpleMenu (Simplemenu) mQuit AxeSimpleMenu (Simplemenu) mLogo AxeSimpleMenu (Simplemenu) mMini AxeSimpleMenu (SimpleMenu) Editing windows have the following structure apart from the instance name. Only the first, 00, is shown. 00 AxeWindow (TopLevelShell) panes AxeEditor (Composite) fileName Label infoBar Label buttons XpTable moveMenu AxeMenuButton (MenuButton) searchMenu AxeMenuButton (MenuButton) insertMenu AxeMenuButton (MenuButton) deleteMenu AxeMenuButton (MenuButton) helpMenu AxeMenuButton (MenuButton) miscMenu AxeMenuButton (MenuButton) fontMenu AxeMenuButton (MenuButton) mFont AxeSimpleMenu (SimpleMenu) windowMenu AxeMenuButton (MenuButton) bufferMenu AxeMenuButton (MenuButton) showMenu AxeMenuButton (MenuButton) fileMenu AxeMenuButton (MenuButton) quitMenu AxeMenuButton (MenuButton) axeLogo AxeMenuButton (MenuButton) edDeck AxeTextDeck (Composite) ed AxeText (AxeiiText) (AsciiText) ed AxeText (AxeiiText) (AsciiText) ... ... miniMenu AxeMenuButton (MenuButton) miniBuffer AsciiText All of the above information, apart from the superclasses, can be obtained by running the editres application at Release 5 of X. The menus consist of AxeSmeBSB (SmeBSB) objects. The names of the objects for each of the menus are these:- mMove: mbeg, mend, mup, mdown, mtop, mbot mSearch: sbtext, sftext, sline, scaret, sbsel, sfsel mInsert: ifile, isel, ipaste mDelete: dword, dline, dsel, dcut mHelp: hgnrl, hbind, hcust, hnom mMisc: mundo, mwhere, mform, mcentre, mhcentr, mpref mWindow: wnew, wfull, wclose, wclall, wicon, wdeicon mBuffer: bempty, bfull, bclear, bclose mFile: fsvex, fsvall, fsave, fsvas, frvrt, fload mQuit: qquit, qsvex, qsvclw, qsvclb Note that lists cannot be given for mFont and mShow, the showMenu buttons' menu. The composition of mFont is not known until startup time while that of mShow varies as windows are created and deleted. *Note The minibuffer menu: Minimenu, for a discussion of the minibuffer menu, mMini. * Menu: * AppRsrcs:: Application resources * AxeWinRsrcs:: AxeWindow widget resources * AxeEdRsrcs:: AxeEditor widget resources * AxeTextRsrcs:: AxeText widget resources * AxeiiTextRsrcs:: AxeiiText widget resources  File: axe.info, Node: AppRsrcs, Next: AxeWinRsrcs, Prev: Resources, Up: Resources Application Resources --------------------- The following application resources are recognised `fileServer' Setting this boolean resource causes aXe to start up in server mode with a FileNominator as the server window. *Note aXe as a server of windows: Server, for more on aXe as a server. `server' Setting this boolean resource, the default, causes aXe to start up in server mode. It has lower precedence than fileServer. If neither is set then the application terminates when the last window is closed. *Note aXe as a server of windows: Server, for more on aXe as a server. `windows' This resource is used to stipulate how many initial windows should be opened. If a greater number of files than the value of this resource is specified on the command line, then the value is ignored. The associated command line keywords -noserver and -windows are supported. -noserver is equivalent to server:False; -windows requires a numeric argument. The application geometry resource (-geometry keyword) is used as a default for all windows opened, but only the width and height parts, which are interpreted to refer to the size of editing buffers in characters, are used. It is also possible to apply geometry specifications one level down in the hierarchy at the individual window (AxeWindow) level. Windows are named 00, 01, 02, etc. If windows are deleted the lowest missing number is used as the instance name for the next window to be opened. This is only relevant if geometry resource specifications for named windows are in use, e.g. Axe.windows: 2 Axe.00.geometry: 80x32+0+0 Axe.01.geometry: +0-0  File: axe.info, Node: AxeWinRsrcs, Next: AxeEdRsrcs, Prev: AppRsrcs, Up: Resources AxeWindow widget resources -------------------------- The following AxeWindow resources are recognised `fileTitle' If this boolean resource is set to True then the name of a window will be set to the pathname of the file currently being edited in it, prefixed by `axe:'. The window's icon name is set to the last component of the path name, prefixed in the same fashion. `fileTitlePrefix' This resource allows the user to alter the prefix that is used when the fileTitle resource is True. `iconNamePrefix' This resource allows the user to alter the prefix that is applied to a window's icon name when the fileTitle resource is True.  File: axe.info, Node: AxeEdRsrcs, Next: AxeTextRsrcs, Prev: AxeWinRsrcs, Up: Resources AxeEditor widget resources -------------------------- The following AxeEditor resources are recognised `buttons' Setting this resource selects the default button interface, unless *buttonList* below is also set. `buttonList' This resource enables the user to specify both which buttons are to be shown and what their layout is to be. Its value is a semi-colon separated list of rows of space separated button names. A `-' may be used in place of a button name in order to skip a column position. The names of the button widgets are presented below. *buttonList* implies *buttons*. `focusToText' Setting this boolean resource has the effect of altering the keyboard focus so that keystrokes occurring in the name section, information bar or button area are redirected to the main text widget, i.e. the mouse pointer can be anywhere within the main application window for editing to take place. `fontList' This resource defines the entries in a menu of fonts from which a choice may be made at run time to be applied to the visisble text buffer of the current window. It is a whitespace separated list of names. If a name contains a `:' then the left hand part will be used as the label of the entry and the right hand part will be taken as the name of a font, otherwise the whole name will be used for both purposes. The items in the list are in addition to the default entry *Default* which corresponds to the original font. `infoTimeout' This resource specifies how long a message should remain in the information bar if no other message is generated in that time. The value should be given as a number of seconds. A value of 0, the default, disables the feature, thus each message remains displayed until the next is generated. The information bar reverts to displaying the version number if a timeout occurs. `menuList' This resource is a space separated list of menu names specifying which menu buttons should appear in the menu bar and in what order. The default value is move search insert delete help misc font window buffer show file quit logo If logo doesn't appear in the list then it will be added at the end. Wherever it appears it will stretch to occupy any otherwise unused space. `Menu' Resources for each of the move, search, insert, delete, help, misc, window, buffer, file and quit menus are defined so that the default contents may be changed. Their values are space separated lists of items consisting of object names from the entire pool of object names across the set of menus, plus `+' and `|'. `+' is interpreted to mean that the default menu should be substituted at that point in the menu, and `|' means that a dividing line should be added. *Note Resources specific to aXe: Resources, for the complete list of object names. `miniMenu' This resource defines the entries to be displayed in the menu associated with the minibuffer. It is a whitespace separated list of names. If a name contains a `:' then the left hand part will be used as the label of the entry and the right hand part will be taken as the command to be run, otherwise the whole name will be used for both purposes. A `+' causes expansion of the default menu and `|' results in the generation of a dividing line in the menu. `suppressFilename' This boolean resource is used to suppress display of the filename pane. This is most likely to be desired when the *fileTitle* resource (*Note AxeWindow widget resources: AxeWinRsrcs.) has also been set, otherwise the filename will be displayed twice in adjacent sections of the window. If both of these resources are set then the modification state of the file is also displayed in the title bar. `suppressInfobar' This boolean resource is used to suppress display of the information bar pane. Of course, then, any error messages which would normally have been displayed there will be lost. `suppressMinibuffer' This boolean resource is used to suppress display of the minibuffer.  File: axe.info, Node: AxeTextRsrcs, Next: AxeiiTextRsrcs, Prev: AxeEdRsrcs, Up: Resources AxeText widget resources ------------------------ The following AxeText resources are recognised `backupNamePrefix' `backupNameSuffix' These resources only apply when *enableBackups*, below, is true. The backup name is the concatenation of the first, the filename, and the second, in that order. The defaults are the empty string and `.BAK' respectively. `enableBackups' This boolean resource controls whether backups of files are made before they are saved for the first time. `grabOnPopup' This boolean resource controls whether popups grab events. The default is False. When events are grabbed it is not possible to do anything elsewhere in the application until the popup is popped down.  File: axe.info, Node: AxeiiTextRsrcs, Next: SampRsrcs, Prev: AxeTextRsrcs, Up: Resources AxeiiText widget resources -------------------------- The following AxeiiText resources are recognised `blinkPeriod' This resource specifies how long the matching `(', `{' or `[' is highlit when a `)', `}' or `]' is typed, and is expressed in milliseconds. The default is 500, i.e. half a second. Setting the value to 0 switches off the feature. `blockCaret' This boolean resource specifies whether the default caret indicating the insertion point should be replaced by an inbuilt block caret. WARNING: Since the introduction of *blockCaret* (above) and *caretBitmap* (below) it has come to light that the Tab key has no visible effect when either has been selected, although the Tab character is inserted into the file. Neither the cause nor a fix for this problem has been found. `caretBitmap' This resource names the pathname of a file containing a bitmap that should be used as the caret that indicates the insertion point. This resource takes precedence over *blockCaret* if both are set. `columns' This resource specifies the desired width in characters. It overrides any setting of the width in pixels. `deleteOnInsert' This boolean resource controls whether the entry of the first character via the keyboard (i.e. via the insert-char action) following the setting of the selection should delete the selection. The default value is False. This feature cannot be supported on older (than Release 5) versions of X, and setting *deleteOnInsert* will have no effect. `expandTabs' This resource specifies whether tabs should be expanded into spaces or not. The default is False. The resource only has an effect if the Tab key is bound to the action *insert-or-expand-tab* - which it is by default. *Note Actions specific to aXe: Actions. `rows' This resource specifies the desired height in characters. It overrides any setting of the height in pixels. `tabEvery' This resource is used to request that tab stops be set every *tabEvery* character positions. The default value is 8. `undo' This resource specifies whether undo information should be kept. The default is True. *Note How the undo mechanism works: Undo. `undoLevel' This resource specifies for how many recent operations undo information should be kept. The default value is 1. A value of 0 implies keeping unlimited information, but remember that doing this could incur excessive memory usage costs.  File: axe.info, Node: SampRsrcs, Next: Actions, Prev: AxeiiTextRsrcs, Up: Customise Examples of resource settings ============================= Here is an example in which the *New + Load* entry of the *Window* menu is replicated on the *File* menu: *fileMenu: + wfull and here is one in which the file menu items are rearranged: *fileMenu: fload frvrt | fsvex fsvall fsave fsvas The buttons in the button interface are AxeCommand widgets. Their names are identical to the corresponding menu entry AxeSmeBSB object names. Thus, the following resources would be sufficient to change the labels of the two *Load* entries to *Edit*. *fload.label: Edit Prefixing that resource specification by *XpTable or by *buttons would be sufficient to refer to just the button widget named *fload*. Here is an example of how to specify the *buttonList* resource. *buttonList: sbsel sfsel - dsel - mform wnew - - fsave; \ - scaret isel dline - - wclose The `;' after fsave terminates the first row of buttons and the `-'s indicate empty column positions, so the layout of the resource value attempts to mimic the actual layout as it will appear in aXe's windows. axe-6.1.2.orig/Help/axe.info-2100644 243 144 130432 5550557110 14515 0ustar joostusersThis is Info file axe.info, produced by Makeinfo-1.55 from the input file axe.texi.  File: axe.info, Node: Actions, Next: SampBinds, Prev: SampRsrcs, Up: Customise Actions specific to aXe ======================= The main editing subwindow of a top-level aXe window is derived from an Athena Text Widget. Hence all of the default bindings of keys to Text Widget action routines apply. The Text Widget is fully described in 'Athena Widget Set - C Language InterFace' of the 'MIT X Window System Manual Set', but for your convenience an extract from the section describing the default key bindings can be viewed on-line (*Note The default key bindings: Bindings.). aXe extends the functionality of the Text Widget by providing additional action routines, but it does not set up any default key bindings for them, i.e. the new features are only available through the menu and button interfaces, or the minibuffer. If you wish to set up your own bindings then you need to know the names of the new action routines. They are goto-line search-caret forward-search-selection backward-search-selection include-file include-selection paste delete-word delete-line cut undo where centre-line set-preferences new-window close-window close-all iconify-all deiconify-all new-buffer clear-buffer close-buffer save-and-close save-all save-file save-as load-file reload-file size match-parens find-match re-search forward-line backward-line delete-selection-or-previous-character insert-or-expand-tab keymap set-mark highlight-region kill-region copy-region yank-region It should be obvious which menu entries/buttons those in the first eight groups correspond to. include-file inserts a file using the file selector, as distinct from insert-file, the Text Widget action bound to Meta-i that brings up the Text Widget's own insertFile dialogue box. new-window and new-buffer may be given the optional argument `load', causing the file selector to be popped up for the new window or buffer immediately it is created. Without an argument save-and-close saves and closes all buffers. With the argument `window' it saves and closes the current window; with the argument `buffer' it saves and closes the current buffer. The remaining actions are not available via the menus or buttons and hence must be bound to keystrokes or typed into the minibuffer (*Note How to use the minibuffer: Minibuffer.). size reports the size of the editing buffer in the information bar. match-parens, if bound to `)', `}' or `]', causes the matching closing bracket to be highlit for a period of time determined by the value of the *blinkPeriod* resource (*Note AxeiiText widget resources: AxeiiTextRsrcs.). find-match causes a search to be made for the character matching the `(', `)', `{', `}', `[' or `]' immediately to the right of the caret, and if successful, highlighting the text between the two characters, inclusive. re-search is like the standard search action except that regular expression searching is performed. It must be supplied with a direction argument of 'forward' or 'backward'. search and re-search share the same popup. The main observable difference when regular expression searching is in effect is that its title is 'RE search' rather than 'search'. There are also minor differences in the messages The forward/backward-line actions are similar to the Text Widgets's next/previous-line actions except that they maintain position within the line if at all possible, i.e. the cursor does not gravitate towards the left margin as ever shorter lines are encountered. The delete-selection-or-previous-character action does what its name suggests. insert-or-expand-tab is bound to the Tab key by default, and operates in conjunction with the *expandTabs* resource (*Note AxeiiText widget resources: AxeiiTextRsrcs.). If that resource is False then tabs are inserted, otherwise an appropriate number of spaces to take the insertion point up to the next tab stop is inserted. The keymap action enables an alternative set of bindings to be switched in. keymap takes a name as argument, which, together with the suffix Keymap, defines the name of a translations resource. A name of None restores the original translations, e.g. *ed.translations:#override \n F1:keymap(foo) \n ... *ed.fooKeymap.translations:F1:keymap(None) \n ... The final set of actions allows selections to be manipulated via the keyboard. set-mark sets an invisible marker. It is initially at the beginning of the buffer. highlight-region highlights the region between the marker and the caret. kill-region deletes the region between the mark and the caret, and stores it in cut buffer 2. copy-region copies the region between the mark and the caret to cut buffer 2. yank-region inserts the contents of cut buffer 2 at the current insertion point.  File: axe.info, Node: SampBinds, Next: Minibuffer, Prev: Actions, Up: Customise Examples of binding actions to keystrokes ========================================= Binding actions to keystrokes involves setting the translations resource of the Text Widget (instance name ed). Here is an example of how this might be done in a resources file. Axe*ed.translations: #override \n\ Down: forward-line() \n\ Up: backward-line() \n\ Delete: delete-selection-or-previous-character() Some of the features in aXe are implemented through setting ed's translations resource in the class resource file, but at Release 4 of X if you provide a value for the same resource it will completely override the application's. A mechanism, which aXe uses, has become available at Release 5 to overcome this difficulty. So if your aXe is an R5 one then you can skip the remainder of this section. If at R4 you don't want to lose any of the application's bindings then you will have to repeat in your value those you wish to keep. The features affected are the matching of parentheses and the reporting of the current line number on a button release. This is how they are implemented in the class resource file Axe*ed.translations: #override \n\ ): match-parens() \n\ ]: match-parens() \n\ : extend-end(PRIMARY, CUT_BUFFER0) where() \n\ : where() \n\ : extend-end(PRIMARY, CUT_BUFFER0) where() and the following is an example of how a user supplied value might look Axe*ed.translations: #override \n\ ): match-parens() \n\ ]: match-parens() \n\ Down: forward-line() \n\ Up: backward-line() \n\ Delete: delete-selection-or-previous-character() Meta=: where() The matching of parentheses has been kept but the reporting of the current line number has been implemented another way, viz. by binding to Meta-=. The Btn?Up actions are not repeated because what is left after removing the where() action is the default behaviour that is defined by the Text Widget.  File: axe.info, Node: Minibuffer, Next: Minimenu, Prev: SampBinds, Up: Customise How to use the minibuffer ========================= Commands corresponding to the two *Search:Text* operations plus *Search:Line*, *Insert:File*, *File:SaveAs* and *File:Load* can be entered directly into the minibuffer. The command names are styled after those of the Unix editor ed and are /regular-expression ?regular-expression [0-9][0-9]* r filename w filename e filename In addition pipe and shell commands have been introduced. Their names are `|' and `!' respectively. Execution of pipe has the effect of replacing the selected text, if any, in the editing buffer by the result of filtering by the command specified in the remainder of the minibuffer. If no text is selected then the output of running the command specified as the pipe argument is inserted at the current insertion point. Execution of shell has the effect of passing the whole buffer or the selected text to the shell command specified as argument and displaying the output, if any, of that command in a new aXe window, unless a `>' occurs in the command, in which case it is assumed that the user wishes to handle the output themself. The command names must occur in column 1 of the minibuffer, and whitespace preceding the argument of `r', `w', `e', `|' and `!' commands is mandatory. The minibuffer also recognises actions as commands. Thus it is not necessary restart aXe with new key bindings to experiment with untried features or to execute infrequently used actions - simply type them into the minibuffer, e.g. new-window() [or simply new-window] or new-window(load). New action routines have been defined so that the minibuffer can be enabled from the editing buffer. When they are used the normal editing buffer translations are suspended and replaced by a minimal set of editing bindings that take effect in the minibuffer, i.e it is not necessary to move the mouse into the minibuffer to execute commands in it. If they are found to be inadequate the mouse can always be moved into the minibuffer to gain access to full range of Text Widget key bindings. The names of the action routines are mini-search mini-insert mini-saveas mini-load mini-pipe mini-shell mini-stuff mini-search may be given an argument of `forward' or `backward'; the default is forward. When the command is mini-insert, mini-saveas or mini-load the minibuffer is initialised with the directory already associated with the editing buffer. mini-pipe, mini-shell and mini-stuff may be given arguments with which to initialise the minibuffer, so frequently used filters and other minibuffer commands can be set up via user defined key bindings. If the last mini-pipe, mini-shell or mini-stuff argument ends with `\n' then the command will be executed right away. Four other action routines have been defined. They are mini-clear mini-select mini-commit mini-abort mini-clear enables and flushes the minibuffer. There is no command corresponding to *Search:Line* so mini-clear could be bound to a key for the purpose as it would provide an empty minibuffer awaiting the entry of a line number. mini-select enables the minibuffer without altering it, so the previous command can then be repeated by simply hitting the Return key. mini-commit executes the command in the minibuffer. mini-abort is defined so that a minibuffer command can be aborted while the accelerators are in effect. The default minibuffer translations and accelerators (the bindings that get installed as the editing buffer translations when the minibuffer is enabled via the above action routines) have Return bound to mini-commit and mini-abort bound to both Escape and `Ctrl-g'. In all cases except mini-search, hitting the Return key causes reinstatement of the editing buffer translations after execution of the minibuffer command. The reason for this is so that repeated searches can be made simply by continuing to hit the Return key. Thus it is necessary to explicitly abort search operations. Note that the caret is only displayed in the minibuffer when it is active, either because the mouse pointer has been moved into it or because it has been enabled by execution of one of the mini- action routines, and further that the caret in the editing buffer is disabled in the latter case, although it won't always be easy to spot that that has happened. Here are some typical bindings that might be used MetaG: mini-clear() CtrlS: mini-search() CtrlR: mini-search(backward) CtrlX,B: mini-select() CtrlX,O: mini-select() CtrlX,CtrlF: mini-load() CtrlX,CtrlI: mini-insert() CtrlX,CtrlW: mini-saveas() CtrlX,CtrlX: mini-pipe("sed 's/^/> /'\n") Print: mini-shell(lpr -Pprinter\n) The second last example will cause each line of the selected text to be prefixed by `> ', i.e. it might be used to annotate a section of a mail message or news article being replied to. It is best to quote the whole argument to mini-pipe because of the way it would otherwise be split on spaces and commas. aXe does try to piece the line together again but can't know whether a split was as a result of a space or a comma; it always assumes that it was a space. The last example causes the selected text or the whole of the text in the editing buffer to be queued for printing by printer `printer'. The minibuffer menu provides a few ready-made examples that are likely to be commonly used. * Menu: * Minimenu:: The minibuffer menu  File: axe.info, Node: Minimenu, Next: Macro, Prev: Minibuffer, Up: Minibuffer The minibuffer menu ------------------- The minibuffer menu provides easy access to a few selected external commands that it is hoped will be commonly required, e.g. printing, spelling checking, formatting and mailing. The mini-shell commands that implement them are: mini-shell(lpr) mini-shell(spell) mini-shell(nroff) mini-shell(mail) Those commands only place the commands `! lpr', `! spell' etc. into the minibuffer (with its accelerators enabled) so it is possible to add options to them before proceeding. For convenience, the menu also provides exec and abort entries; the first is simply equivalent to hitting Return, and causes the command in the minibuffer to be executed, while the second removes the accelerators so that keystrokes in the editing buffer will revert to being directed to that buffer instead of to the minibuffer. A further three entries are identical to the first three except that the commands are entered and executed in one operation. They are identifiable by having in the entry label, which is meant to convey that the command contains the Return to cause it to be executed. It does not make sense to replicate `mail' in this way since a recipient will always have to be added to the minibuffer command before execution. Although probably useful as it stands, the minbuffer menu is merely a demonstration of what can be done. It is totally customisable by the user by defining the *miniMenu* resource. Its value is a whitespace separated list of items. If a `:' occurs in an item then the left hand part will be taken as the corresponding menu entry label and the right hand part as the minibuffer action, otherwise the whole item will be used for both purposes. If the action part begins with `mini-' then it is left untouched, otherwise it is taken to be an argument to mini-shell. Furthermore, an item of `|' is interpreted to mean that a dividing line should be added to the menu at that position. An item of `+' means that the default menu should be substituted at that point, i.e. the user can either replace or add to the default menu. So *miniMenu:who | + would add an item called who, that would execute the who command, to the top of the default menu, and separated from it by a dividing line, whereas *miniMenu:who would generate a menu consisting of a single `who' entry. The resource value defining the default menu is: print:lpr spell nroff mail | \ exec:mini-commit abort:mini-abort | \ print:lpr\n spell:spell\n nroff:nroff\n Labels and actions can be quoted using either the single or the double quote characters, e.g "laser printer":'lpr -Plaser' or 'laser printer':"lpr -Plaser" The " and ' characters themselves can only be included by using the other quote character to do the quoting, e.g. "jim's printer" You can provide help to be displayed in the information bar when the mouse enters your menu items by setting each's help resource. The name of the widget is the same as the item's label, e.g. *laser printer.help:Send to laser printer  File: axe.info, Node: Macro, Next: Undo, Prev: Minimenu, Up: Customise Defining and using a keyboard macro =================================== A single global keyboard macro can be defined. The following new action routines have been defined in this connection: start-macro end-macro exec-macro repeat-macro start-macro and end-macro should be self-explanatory. exec-macro executes the macro once. repeat-macro optionally takes an argument specifying a repeat count. This is most likely to be of use when the action is executed as a minibuffer command. Otherwise a repeat count is taken from the minibuffer and the macro is executed that many times. This is most likely to be of use when repeat-macro() is used from a key binding. If the conversion fails or the minibuffer has been suppressed then the repeat count defaults to 1. Here are some bindings that might be used: CtrlX,(: start-macro() CtrlX,): end-macro() CtrlX,E: exec-macro() CtrlX,R: repeat-macro() A macro is defined by executing start-macro and stepping through the sequence of actions that will constitute one invocation, followed by end-macro. The macro is effective in all buffers, not just the one in which it is defined, and gets replaced if start-macro is executed again. With these bindings the effect of the mini-pipe example above could equally well be accomplished, after moving the insertion point to the beginning of the first line to be annotated, by defining a macro with the following sequence of keystrokes C-x ( > C-a C-n C-x ) and by executing `C-x e' for each subsequent line to be annotated, or by entering the number of remaining lines to be annotated in the minibuffer and executing `C-x r'.  File: axe.info, Node: Undo, Next: Server, Prev: Macro, Up: Customise How the undo mechanism works ============================ The availability of undo is controlled by the resource *undo*, which is True by default. By default you are able to undo only the most recent operation that changed the file. If you wish to retain a greater history then set the *undoLevel* resource (*Note AxeiiText widget resources: AxeiiTextRsrcs.) to the level you require. The default is 1. A value of 0 means keeping unlimited information, but that could run away with large amounts of memory if editing over an extended period. The new action undo performs a single undo. Inserted characters, apart from control codes, which are dealt with individually, are handed back in units of uninterrupted runs of at most a line. A run is interrupted by any operation other than the insertion of a character, even if it doesn't change the file, e.g. moving the caret. If you want to undo single characters then delete them in the normal way. Deleted characters can be undone individually. The implementation allows undos of undos. Once *undoLevel* consecutive undos have been performed the next (consecutive) undo will cause the most recent undo to be undone, the next the undo before that, and so on ad infinitum until some action other than undo breaks the sequence. Note that if you have a number of undos to perform it is quicker to type undo in the minibuffer and repeatedly re-execute it by hitting the Return key than by selecting *Undo* from the *Misc* menu each time. You should be aware that currently multiple changes arising from performing a single action, e.g. by doing a `replace All' or executing a keyboard macro, require multiple undos to get back to the position prior to the action being invoked, and may be impossible if *undoLevel* is not great enough. If you find that for some reason the undo information has got out of step then the easiest way to get back in sync is to save and reload the file. Loading or reloading a file causes all the current undo information to be thrown away and the mechanism to be reinitialised.  File: axe.info, Node: Server, Next: Popups, Prev: Undo, Up: Customise aXe as a server of windows ========================== There are two main differences when aXe is acting as a server: an additional window is created and aXe does not terminate when the number of windows reduces to zero. The function of the extra window is to provide a way of getting an editing window when there are no others to use as a launch pad, and to provide a way of shutting down the application. The default server window allows empty windows to be created and provides access to the help system. Alternatively, a FileNominator (*Note The file selector: Nominator.) can be used as the server window by setting the top level *fileServer* resource (*Note Application resources: AppRsrcs,). Additionally, editing windows can be obtained from a server by cooperating clients on the same host. Two such clients are provided: coaxe and faxe. Coaxe waits until it gets notification that its aXe window has been closed, whereas faxe terminates as soon as it has successfully contacted its server. Faxe can take several filename arguments, but coaxe is restricted to one. By default multiple files passed to faxe are assigned a window each. A group of files can be assigned to buffers of the same window by preceding the list by any leading substring of the keyword -buffer. The keyword may occur more than once on the command line. Coaxe and faxe start up aXe in non-server mode if a server is not already running, and coaxe is notified when the invocation terminates, i.e. when the last window is closed. A display can support servers for many hosts, but only one server per host is catered for. If a second server is started for some host when one is already running then the second will take over the role of server to the client programs, and the first will be uncontactable by them. Shutting down aXe from the server window is equivalent to doing a *Window:Close All*, i.e. a check is made for unsaved changes if any editing windows exist. A third client program, poleaxe, is also provided for shutting down the server, but checks are not carried out when it is used. It is not a serious client; it only came into being because of the pun afforded by its name.  File: axe.info, Node: Popups, Next: Nominator, Prev: Server, Up: Top aXe's secondary popup windows ***************************** From time to time as aXe is running windows other than the main editing windows and the initial server window, if running in server mode, that is, are popped up for the input and output of information. Each type is briefly described in one of the menu items that now follow. * Menu: * Nominator:: The file selector * NumPad:: The numeric keypad * ControlCode:: The control code selector * Confirmer:: The confirmer * Preferences:: The preferences setter * Help:: The help system  File: axe.info, Node: Nominator, Next: NumPad, Prev: Popups, Up: Popups The file selector ================= The FileNominator popup is popped up whenever a menu operation that requires a file name is selected, or an equivalent action routine has been activated through a key binding set up by the user. The FileNominator is both a directory browser and a file selector. It consists of a scrollable list of the contents of the directory associated with the buffer from which it was popped up, or the directory last visited by the user in earlier usage, a filter section, which allows the user to filter the list of files displayed according to normal shell pattern matching rules, a 1-line text area in which the filename to be returned is assembled, and three buttons. The filter pattern that is initially applied may be something other than the default `*'. A different value is specified by setting the value of the resource *filter*, for example to `*[ch]'. A file may be nominated by choosing from the list using mouse button 1 (causing the name to be entered into the filename input area), or by typing into the input area, or by doing both. All keyboard input is directed there when the list widget has the input focus. The content of the input is assumed to be relative to the directory currently displayed if not an absolute pathname. The selection is always taken from the nomination in the input area, and happens when the select button is clicked (mouse button 1) or the Return key is pressed. If no modification is to be made then a choice from the List can be selected by double clicking mouse button 1 or by single clicking mouse button 2. Further, an immediate selection of some other directory in the path of the displayed directory can be made by selecting from the `path' button menu. A `~' as the first character in the input area is understood to mean the user's home directory. If a nomination begins with a `$' then the first component will be treated as a possible reference to an environment variable, with the expansion being made if a variable of that name exists. In addition the user may define a list of potential nominations - either files or directories - to be added to the `path' button menu. Since selecting an entry from the menu is equivalent to entering the entry in the input area and selecting it in the normal way, i.e it is subject to the checks that would be applied if the user had typed the value as a nomination, then `~' and `$' may feature in the user-added entries. The user adds entries by providing a value for the *pathList* resource of the FileNominator. It is a colon separated list of pathnames that are converted into menu entries and added to the path button menu. When the selection is a directory the contents of the directory are filtered according to the pattern in the filter input area, so that a reduced subset of interest may be displayed. A new filter can be run on the current directory by hitting Return in the filter input area or by selecting Apply from the menu belonging to the filter menu button. The menu has two other entries: `Apply to directories', which controls whether directories should always be displayed or whether they should also be subject to filtering, and `Apply to "." files', which controls whether names beginning with a `.' should be displayed or not. The last two entries are toggles, whose selection cause toggling of the setting and rescanning of the directory with the toggled value effective. The "." files entry takes precedence over the one for directories e.g. if the pattern is `*c' and there is a file called .filec, then it won't be shown unless there is a tick mark against the `Apply to "." files' entry.  File: axe.info, Node: NumPad, Next: ControlCode, Prev: Nominator, Up: Popups The numeric keypad ================== The NumericPad popup is popped up whenever the *Line* entry of the *Search* menu is selected, or the goto-line action invoked by other means. This popup is an instance of a general purpose widget for entering numeric data, and contains features that are probably inappropriate for aXe, like the ability to change the base to octal or hexadecimal. A number can be entered into the 1-line text area by clicking the digit buttons or from the keyboard whilst the popup has the input focus. A number is submitted to the application by clicking the enter button or by hitting either the Return or the Enter key. The cancel button is for dismissing the popup without entering a number.  File: axe.info, Node: ControlCode, Next: Confirmer, Prev: NumPad, Up: Popups The control code selector ========================= The ControlCodeSelector popup is popped up whenever the *Control Codes* entry of the *Insert* menu is selected, or the insert-control action is invoked by other means. Selecting an item in the table of control codes that is displayed causes the item to become highlighted and its ASCII code to be displayed in a label at the lower left of the popup. The widget that is at the heart of this popup has a resource, *base*, which controls how the numeric value of the code is displayed. aXe displays the value to the base 8, i.e. in octal. The currently selected control code is entered into the current buffer of the window from which the popup was popped up by clicking the enter button with mouse button 1. Several consecutive control codes can be entered as the popup is only popped down when the cancel button is clicked. A code from the table can be entered directly into the current buffer by clicking the item with mouse button 2.  File: axe.info, Node: Confirmer, Next: Preferences, Prev: ControlCode, Up: Popups The confirmer ============= The Confirmer popup is popped up whenever the user is about to perform a potentially destructive act, like clearing a buffer that has unsaved changes. Apart from a superfluous bitmap, it contains a message describing the reason why the user is being asked to confirm proceeding with the requested operation, and three buttons. The rightmost button - cancel - is for dismissing the popup by abandoning the requested operation. The remaining two buttons provide alternative courses of action. If the middle button is greyed out then it means that there is only one possible action to take. The symbols at the right hand end of the button labels signify keyboard accelerators for selecting those buttons. `^A' is shorthand for hitting key A in conjunction with the Control key. Thus, if the popup is popped up as a result of a keyboard event then in all probability the user will be able to make a choice without having to resort to the mouse since the popup is centred around the mouse pointer and a popular way of working is for the widget having the input focus to be determined by the location of the mouse.  File: axe.info, Node: Preferences, Next: Help, Prev: Confirmer, Up: Popups The preferences setter ====================== The Preferences popup allows a selected number of user preferences (resources) to be changed at runtime. You should note that under `Wrap Mode' selection of `Auto Fill' automatically forces on `No Wrap', and selection of `Line' or `Word' automatically forces off `Auto Fill'. These are the combinations that it has been found work best. Any typing within the popup is directed to the `Tab Every' entry field as this is the only one which requires keyboard input. Although there is apparently provision for having the settings apply to just one buffer, all the buffers in one window, or to all buffers, only the first is possible. The buttons corresponding to the last two cases are insensitive to button presses, which is indicated by their being greyed out.  File: axe.info, Node: Help, Next: Language, Prev: Preferences, Up: Popups The help system =============== You have obviously already discovered the help system. If you require more information about how to use it then jump to the *Note Axinfo::, node. If a window fails to appear in response to requesting help then it is almost certain that the executable, axinfo, was not found on your shell command search path. If a small window appears containing a message that the application defaults file could not be found then axinfo has either not been installed properly or you have incorrectly overridden the default search path for application defaults files, for example by setting the environment variable XFILESEARCHPATH, Once axinfo has been started up it is independent of aXe, i.e. terminating the one does not terminate the other. On the other hand, if an axinfo is already running, as a result of having been started independently or remaining from an earlier invocation of aXe, when help is requested then aXe communicates with that axinfo rather than fire up a new one.  File: axe.info, Node: Language, Next: Builtins, Prev: Help, Up: Top aXe's extension language ************************ aXe's extension language is Tcl. As Tcl is a separate package with its own documentation, which should be available locally, it is not described here. The language extension is an option at build time. If the *Help* menu does not contain an *Extension* entry then the option has not been configured into the version of aXe you are running. In order to integrate Tcl into aXe a new action routine, execute, has been introduced. It takes a Tcl command as argument. Thus Tcl commands can be bound to keystrokes, e.g. *ed.translations:#override \n\ Ctrlx,r:execute(prefix) where `prefix' might be the following procedure: proc prefix {{text {> }}} { with-selection action insert-string $text } with-selection is a general purpose procedure that applies another procedure to each line of the selection in turn. The applied procedure and its arguments are passed as arguments to with-selection. In the example above the applied procedure is `action' and its arguments are `insert-string' and `$text'. with-selection is implemented as follows: proc with-selection {func {args {}}} { set selection [get-selection] set start [lindex $selection 0] set end [lindex $selection 1] set lines [lindex $selection 2] if {$start == $end} {return} set-position $start for {set line 0} {$line < $lines} {incr line} { action beginning-of-line eval $func $args action next-line } action beginning-of-line set-selection $start [get-position] } By default prefix prepends `> ' to each line in the selection, but by supplying an argument a different prefix can be employed, e.g. prefix "! " prefix " " prefix and with-selection make use of a number of builtin commands (*Note Builtin extension language commands: Builtins.) that have been defined. * Menu: * Builtins:: Built in extension language commands * Utilities:: Other extension language commands * UseLang:: Using the extension language  File: axe.info, Node: Builtins, Next: Utilities, Prev: Language, Up: Language Builtin extension language commands =================================== `action arg1 arg2 ...' enables action routines to be executed from within Tcl commands. Action routine arguments are separated by spaces, not enclosed in parentheses, e.g. search forward, not search(forward). `eval-buffer' evaluates the current buffer on the assumption that it contains a Tcl script. In other words new commands can be entered and immediately tried out. `get-selection' returns a list consisting of the starting and finishing positions of the selection, the number of lines spanned by it, and the selection itself. `get-position' returns the value of the insertion point. `set-position point' sets the insertion point to the value of its argument. `set-selection start finish' sets the selection to be the text spanned by the positions passed as arguments. `set-value resource value' `set-source-value resource value' `set-sink-value resource value' set the resource named in the first argument to the value in the second for the text widget or its source or sink objects.  File: axe.info, Node: Utilities, Next: UseLang, Prev: Builtins, Up: Language Other extension language commands ================================= A small collection of commands built using the builtins (*Note Builtin extension language commands: Builtins.) and action routines should have been loaded when aXe was started up. It consists of the following commands. `with-selection proc args' applies a procedure and its arguments to each line of the selection in turn. Example: with-selection action insert-string "> " `prefix string' prepends an optional string to each line of the selection. The default string is `> '. `strip n' removes a number of characters equal to the value of its argument from the beginning of each line in the selection. If no argument is given the default is 1. `join-lines n separator' joins together the next n lines as given by the first argument (default 1) to the current line, and inserts the text given by the second argument (default " ") at the join. `format-all' formats the entire buffer by applying the action form-paragraph to successive paragraphs. On completion the caret is restored to the character position it was originally at, but of course that is likely to be correspond to a different place in the text. `upper' `lower' convert the selection to upper and lower case respectively.  File: axe.info, Node: UseLang, Next: Changes, Prev: Utilities, Up: Language Using the extension language ============================ User-defined commands that are to be loaded at startup should be stored in the file axe.tcl in the user's home directory. Commands can also be loaded dynamically at runtime from a file by executing `source pathname' in the minibuffer. If the file does not exist then the command will fail, and that failure will be reported identically to other errors, i.e. the keyboard bell will be rung and an appropriate message displayed in an alert popup. The easiest way to execute Tcl commands is to type them into the minibuffer. Thus the example given at the beginning (*Note aXe's extension language: Language.) could equally well be executed by typing `prefix' in the minibuffer, whereas making a selection and typing prefix " " will cause each line in the selection to be indented by 4 spaces. Using the minibuffer is especially convenient if you want to create and try out new commands from within aXe. If the current buffer contains a Tcl script defining some new procedures then these can be loaded into aXe by typing `eval-buffer' in the minibuffer. The new procedures may be tried out by issuing commands in the minibuffer to invoke them. Changes to the script can be made and the process repeated as often as necessary as defining a procedure replaces the existing definition, if any. The extension language makes it possible for things to be done in aXe that either I couldn't envisage users wanting to do or wouldn't want to implement as fixed features. Here are just a couple of examples that might set you thinking of the possibilities. `Example 1' The following procedure demonstrates how the extension language might be used to set up modes. proc a-mode {} { set-value tabEvery 4 set-value wrap word } Execution of the procedure will affect the current buffer of the window in which it is executed. There are three ways in which it could be executed: 1. by typing `a-mode' in the minibuffer. 2. by setting up a minibuffer menu entry and selecting it. The entry might be set up using the following resource specification: *miniMenu:+ 'A mode':mini-stuff(a-mode\n) 3. by setting up a translation, such as the following: *ed.translations: #override \n\ Metam:execute(a-mode) and typing `Meta-m' in the editing buffer to which it is to be applied. `Example 2' This example shows how a procedure defining a C++ template header file might be set up. proc class {class {baseclass {}}} { action insert-string "#ifndef ${class}_h\n" action insert-string "#define ${class}_h\n\n" action insert-string "class $class" if {$baseclass != {}} { action insert-string " : public $baseclass" } action insert-string "\n\{\npublic:\n" action insert-string " $class\(\);\n ~$class\(\);\n\n" action insert-string "protected:\n\n" action insert-string "private:\n\};\n\n#endif\n" } When invoked with two arguments, the name of the new class and the name of the base class, then the following is generated at the insertion point of the current buffer, assuming arguments of Foo and Bar: #ifndef Foo_h #define Foo_h class Foo : public Bar { public: Foo(); ~Foo(); protected: private: }; #endif If the second argument is not given then the `class' line becomes class Foo  File: axe.info, Node: Changes, Next: Change 1, Prev: UseLang, Up: Top Changes since the previous release ================================== If this is the first time you have seen axinfo (aXe information system) then the minimum you need to know to begin to use it is that clicking on highlighted words using mouse button 1 will take you to other parts of the help. *Note Axinfo:: describes the system in more detail. * Menu: * Change 1:: Changes to the help system * Change 2:: Deleting the selection on text entry * Change 3:: Changes to the extension language * Change 4:: Setting of the WM_COMMAND property  File: axe.info, Node: Change 1, Next: Change 2, Prev: Changes, Up: Changes Changes to the help system ========================== aXe's help information is now displayed using a separate application (this program) that is either run standalone or invoked, if it is not already running, when an entry is selected from the *Help* menu. *Note Axinfo:: describes the system in detail. The underlying documentation system that is used permits both on-line help and printed output to be generated from the same input file. Hence the help information is now available as a User Guide. It should have been provided as a PostScript file when your site acquired the aXe distribution. Check availability with your system administrator.  File: axe.info, Node: Change 2, Next: Change 3, Prev: Change 1, Up: Changes Deleting the selection on text entry ==================================== A new AxeiiText widget resource `deleteOnInsert' has been introduced. It controls whether the entry of the first character via the keyboard (i.e. via the insert-char action) following the setting of the selection should delete the selection. The default value is `False'.  File: axe.info, Node: Change 3, Next: Change 4, Prev: Change 2, Up: Changes Changes to the extension language ================================= The supplied commands that manipulate the selection reselect the modified text so that it can be further operated on. Some new commands have been provided and others have been renamed. join and format have been renamed as join-lines and format-all because they masked Tcl procedures of the same names. getSelection, getPos, setPos and loopSel have been renamed as get-selection, get-position, set-position and with-selection. In addition get-selection provides the selection as an extra element of the returned list. The new commands are:- set-selection start finish which sets the selection. eval-buffer which evaluates the current buffer as a Tcl script, i.e. you can compose, add and try out new commands from within aXe. set-value resource value set-source-value resource value set-sink-value resource value which set the value of the named resource for the editing buffer Text widget, or its source or sink object. upper lower which convert the selection to upper or lower case respectively.  File: axe.info, Node: Change 4, Prev: Change 3, Up: Changes Setting of the WM_COMMAND property ================================== When running in server mode aXe now sets the WM_COMMAND property on the server window. This means that an entry for aXe will now show up in the output of xlsclients, and that aXe will be visible to startup generator applications. The WM_COMMAND property is not set if aXe is not running in server mode - there is no window that can be guaranteed to survive the term of the invocation. axe-6.1.2.orig/Help/axinfo.c100644 243 144 113447 5550743652 14373 0ustar joostusers/* * Copyright 1993 The University of Newcastle upon Tyne * * Permission to use, copy, modify and distribute this software and its * documentation for any purpose other than its commercial exploitation * is hereby granted without fee, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of The University of Newcastle upon Tyne not be used in * advertising or publicity pertaining to distribution of the software * without specific, written prior permission. The University of * Newcastle upon Tyne makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * THE UNIVERSITY OF NEWCASTLE UPON TYNE DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF * NEWCASTLE UPON TYNE BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. * * Author: Jim Wight (j.k.wight@newcastle.ac.uk) * Department of Computing Science * University of Newcastle upon Tyne, UK */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include extern char *getenv(); extern char *malloc(), *realloc(); #include "Confirmer.h" #include "Hyper.h" #include "util.h" #include "axinfo.h" #include "version.h" #define INFOFILE "axe.info" #if __STDC__ #define MAKESTRING(name,string) \ name##String = XtNewString(string); \ name##Len = strlen(name##String); #else #define MAKESTRING(name,string) \ name/**/String = XtNewString(string); \ name/**/Len = strlen(name/**/String); #endif #define BCOPY(outof, into, upto) \ into = malloc((unsigned) (upto - outof + 1)); \ bcopy(outof, into, upto - outof); \ into[upto - outof] = 0; #define TABLECHUNK 20 typedef struct { String tag; int pos; } TagTableRec, *TagTablePtr; typedef struct { String version; Boolean tree; String node; String dir; } AppResRec, *AppResRecPtr; Widget top, hyper = 0, links, tree = 0, root, porthole, lastNode = 0; char soh = '\001', eoh = '\004'; XContext context; String infofile, basedir, currentfile = 0, buffer; int baselen, buflen; TagTablePtr tagTable; int maxTags = 0, numberTags = 0, currentTag = -1, lastTag = -1; TagTablePtr indirectTable = 0; int maxIndirects = 0, numberIndirects = 0; int dragX, dragY; String fileString, nodeString, prevString, nextString, upString; String menuString, entryString, xrefString, btagString, etagString; String itagString, tagiString; int fileLen, nodeLen, prevLen, nextLen, upLen; int menuLen, entryLen, xrefLen, btagLen, etagLen; int itagLen, tagiLen; Atom AxinfoUserAtom(display) Display *display; { char propName[1024], *user; strcpy(propName, "AXE_AXINFO"); if ( (user = getenv("USER")) ) { strcat(propName, "_"); strcat(propName, user); } return XInternAtom(display, propName, False); } Boolean IsTag(tag, tagId) char *tag; int *tagId; { int t; for (t = 0; t < numberTags; ++t) { if (strcmp(tag, tagTable[t].tag) == 0) { *tagId = t; return True; } } return False; } char* Find(buffer, magic) char *buffer, magic; { char *bp; for (bp = buffer; *bp && *bp != magic; ++bp) {} return *bp ? bp : 0; } char* Locate(buffer, search) char *buffer, *search; { char *bp; int i, len = strlen(search); for (bp = buffer; *bp && *bp != INFO_COOKIE; ++bp) { for (i = 0; i < len; ++i) { if (bp[i] != search[i]) { break; } } if (search[i] == 0) { return bp + len; } } return bp; } char* ReverseLocate(buffer, search) char *buffer, *search; { char *bp, *rsearch; int i, j, len = strlen(search); rsearch = malloc((unsigned) (len + 1)); for (i = 0, j = len - 1; i < len; ++i, --j) { rsearch[j] = search[i]; } rsearch[len] = 0; for (bp = buffer; *bp; --bp) { for (i = 0; i < len; ++i) { if (bp[-i] != rsearch[i]) { break; } } if (search[i] == 0) { free(rsearch); return bp + 1; } } free(rsearch); return bp; } int LookingAt(bp, nbp) char *bp, **nbp; { if (*bp == INFO_COOKIE) { ++bp; while (*bp == '\n' || *bp == INFO_FF) { ++bp; } } switch (*bp) { case 'F': if (strncmp(bp, fileString, fileLen) == 0) { *nbp = bp + fileLen; return IS_NODE; } break; case 'T': if (strncmp(bp, btagString, btagLen) == 0) { *nbp = bp + btagLen; return IS_TAG_TABLE; } break; case 'I': if (strncmp(bp, itagString, itagLen) == 0) { *nbp = bp + itagLen; return IS_INDIRECT; } break; case '(': if (strncmp(bp, tagiString, tagiLen) == 0) { *nbp = bp + tagiLen; return IS_INDIRECT_LABEL; } break; case '\n': if (strncmp(bp, menuString, menuLen) == 0) { *nbp = bp + menuLen; return IS_MENU; } else if (strncmp(bp, entryString, entryLen) == 0) { *nbp = bp + entryLen; return IS_ENTRY; } else if (bp[1] == '*' || bp[1] == '=' || bp[1] == '-' || bp[1] == '.') { *nbp = bp + 2; return IS_SECTIONING; } break; case 'N': if (strncmp(bp, nodeString, nodeLen) == 0) { *nbp = bp + nodeLen; return IS_TAG; } else if (strncmp(bp, nextString, nextLen) == 0) { *nbp = bp + nextLen; return IS_NEXT; } break; case 'P': if (strncmp(bp, prevString, prevLen) == 0) { *nbp = bp + prevLen; return IS_PREV; } break; case 'U': if (strncmp(bp, upString, upLen) == 0) { *nbp = bp + upLen; return IS_UP; } break; case '*': if (strncmp(bp, xrefString, xrefLen) == 0) { *nbp = bp + xrefLen; return IS_XREF; } break; default: return 0; } return 0; } /*ARGSUSED*/ void Exit(widget, client_data, call_data) Widget widget; XtPointer client_data, call_data; { exit(1); } void OpenInfofile(file) char *file; { FILE *inf; struct stat fstats; if (currentfile) { if (file != currentfile) { free(buffer); currentfile = 0; } else { return; } } inf = fopen(file, "r"); if (!inf) { Widget conf; char message[1024]; conf = XtVaCreateManagedWidget("confirmer", confirmerWidgetClass, top, XtNgrabOnPopup, True, NULL); XtAddCallback(conf, XtNpopdownCallback, Exit, (XtPointer) 0); sprintf(message, "Unable to open\n%s", file); ConfirmerRequestConfirmation(conf, message, "acknowledge", ConfirmerPopdown, "unused", NULL, (XtPointer) 0); XtAppMainLoop(XtWidgetToApplicationContext(conf)); }; if (fstat(fileno(inf), &fstats) == -1) { perror("fstat"); exit(1); } if (!(buffer = malloc((unsigned) (fstats.st_size + 1)))) { printf("Out of memory\n"); exit(1); } if (fread(buffer, (int) fstats.st_size, 1, inf) != 1) { printf("Read error\n"); exit(1); } buffer[fstats.st_size] = 0; buflen = fstats.st_size; currentfile = file; fclose(inf); } char* MakeHeaderBuffer(bp) char *bp; { char *sp = bp, *header; while (*bp != '\n') ++bp; /* +15 to be absoultely safe on length = "{} " for Next, Prev and Up */ header = XtMalloc((unsigned) (bp - sp + 15 + 32)); /* Assumes this takes up less space than "File: xyz.intro" */ sprintf(header, "Top: %cTop%c ", soh, eoh); return header; } void CompleteHeaderBuffer(header) char *header; { if (lastTag >= 0) { sprintf(header, "Last: %c%s%c", soh, tagTable[lastTag].tag, eoh); } } void HyperLink(type, bp, header, eol) int type; char *bp, **header, **eol; { char *sp, *head = *header; int len; switch (type) { case IS_NEXT: strcat(head, nextString); break; case IS_PREV: strcat(head, prevString); break; case IS_UP: strcat(head, upString); break; } sp = bp; while (*bp == ' ') { ++bp; } strncat(head, sp, bp - sp); sprintf(&head[strlen(head)], "%c", soh); sp = bp; while (*bp != ',' && *bp != '\n') { ++bp; } strncat(head, sp, bp - sp); sprintf(&head[strlen(head)], "%c ", eoh); if (*bp == '\n') { *eol = bp; /* Blank out back to comma terminating "Node: Tag," */ for (--bp; *bp != ','; --bp) { *bp = ' '; } *bp = ' '; } else { *bp =' '; /* overwrites ',' */ *eol = 0; } } void Entry(bp) char *bp; { char *sp; sp = bp; bp = Find(bp, ':'); if (bp[1] == ':') { bp[1] = eoh; for ( ; bp > sp; --bp) { bp[0] = bp[-1]; } sp[0] = soh; } else { ++bp; while (*bp == ' ') { ++bp; } bp[-1] = soh; while (*bp != '\t' && *bp != ',' && *bp != '.' && *bp != '\n') { ++bp; } bp[0] = eoh; } } void CrossRef(bp) char *bp; { char *sp; while (*bp == ' ' || *bp == '\n' || *bp == '\t') { ++bp; } sp = bp - 1; bp = Find(bp, ':'); if (bp[1] == ':') { /* * This is a "*Note node-name::" case. * Convert it into "*Note Node name", i.e. sacrifice * the two ':' characters to make way for the two markers. */ bp[1] = eoh; for ( ; bp > sp; --bp) { bp[0] = bp[-1]; } sp[1] = soh; } else { /* * "*Note cross-reference-name: node-name[,.]" or * "*Note cross-reference-name: (info-file)node-name[.,]" cases. * * Convert the former to * "*Note cross-reference-name:node-name", i.e. sacrifice * leading space and terminating period or comma, * * and the latter to * "*Note cross-reference-name:(info-file)node-name", i.e. * shift "(info-file)" down 1 to release space in front of node * name and sacrifice terminating period or comma. */ bp = bp + 1; while (*bp == ' ' || *bp == '\n') { ++bp; } sp = bp - 1; if (*bp == '(') { bp = Find(bp, ')'); for ( ; sp < bp; ++sp) { sp[0] = sp[1]; } sp = bp; } sp[0] = soh; while (*bp != '.' && *bp != ',') { ++bp; } *bp = eoh; } } char* ExtractNodeAndHyperize(buffer, header, body) char *buffer, **header, **body; { char c, *sp, *bp = buffer, *node, *headerBuffer, *eol; int type; while (*bp && *bp != INFO_COOKIE) { ++bp; } BCOPY(buffer, node, bp) bp = node; *header = 0; *body = 0; while (*bp) { sp = bp; switch ( (type = LookingAt(bp, &bp)) ) { case IS_NODE: headerBuffer = MakeHeaderBuffer(sp); break; case IS_NEXT: case IS_PREV: case IS_UP: if (!(*body)) /* i.e. finished with header, and hence allows */ { /* possibility of "Up:" in text, for instance */ HyperLink(type, bp, &headerBuffer, &eol); if (eol) { CompleteHeaderBuffer(&headerBuffer[strlen(headerBuffer)]); *header = headerBuffer; *body = node; } } break; case IS_ENTRY: Entry(bp); break; case IS_XREF: CrossRef(bp); break; default: ++bp; break; } } return node; } char* MakeNode(nodename, header, body) char *nodename, **header, **body; { char *bp, *sp, *tp, *node; int i, p; String f = infofile; if (!IsTag(nodename, &p)) { return 0; } if (indirectTable) { for (i = numberIndirects - 1; i >= 0; --i) { if (tagTable[p].pos >= indirectTable[i].pos) { f = indirectTable[i].tag; break; } } } OpenInfofile(f); if (indirectTable) { bp = &buffer[tagTable[p].pos - indirectTable[i].pos + indirectTable[0].pos]; } else { bp = &buffer[tagTable[p].pos]; } if (bp[-1] == INFO_COOKIE) /* The Tag Table number doesn't always plonk */ /* you on the INFO_COOKIE */ { ++bp; } else { while (*bp && *bp != INFO_COOKIE) { ++bp; } bp += 2; } sp = bp; if (LookingAt(bp, &bp) == IS_NODE) { for (i = 0; i < numberTags; ++i) { if (strcmp(nodename, tagTable[i].tag) == 0) { lastTag = currentTag; currentTag = i; break; } } return ExtractNodeAndHyperize(sp, header, body); } else { return 0; } } void InvertWidget(widget) Widget widget; { Pixel fg, bg; if (!widget) { return; } XtVaGetValues(widget, XtNforeground, &fg, XtNbackground, &bg, NULL); XtVaSetValues(widget, XtNforeground, bg, XtNbackground, fg, NULL); } void PositionNode(node, highlight) char *node; Boolean highlight; { String label; WidgetList children; Cardinal numChildren; int child; Position x, y, tx, ty; Dimension w, h, pw, ph, tw, th; XtVaGetValues(tree, XtNchildren, &children, XtNnumChildren, &numChildren, NULL); /* NB child = 1 excludes root widget */ for (child = 1; child < numChildren; ++child) { XtVaGetValues(children[child], XtNlabel, &label, NULL); if (strcmp(node, label) == 0) { if (highlight) { InvertWidget(children[child]); InvertWidget(lastNode); lastNode = children[child]; } break; } } XtVaGetValues(children[child], XtNx, &x, XtNy, &y, XtNwidth, &w, XtNheight, &h, NULL); XtVaGetValues(porthole, XtNwidth, &pw, XtNheight, &ph, NULL); XtVaGetValues(tree, XtNx, &tx, XtNy, &ty, NULL); /* if (y + h + ty < 0 || y + h + ty > ph || x + w + tx < 0 || x + w + tx > pw) { */ XtVaSetValues(tree, XtNx, -(x - pw / 2), XtNy, -(y - ph / 2), NULL); /* } */ } void RevealNode(tag) char *tag; { String node, header, body; int i; if (currentTag >= 0 && strcmp(tag, tagTable[currentTag].tag) == 0) { return; } if ( !(node = MakeNode(tag, &header, &body)) ) { return; } HyperSetText(hyper, (body ? body : node)); XtFree(node); if (header) { HyperSetText(links, header); } XtFree(header); if (XtIsSubclass(XtParent(hyper), viewportWidgetClass) && XtIsRealized(hyper)) { XawViewportSetLocation(XtParent(hyper), 0.0, 0.0); } #if defined(XtSpecificationRelease) && XtSpecificationRelease > 4 if (tree) { PositionNode(tag, True); } #endif } void ExposeNode(tag) char *tag; { Widget popup; void MakeHyperWindow(); if (hyper) { for (popup = XtParent(hyper); !XtIsShell(popup); popup = XtParent(popup)) {} XMapRaised(XtDisplay(hyper), XtWindow(popup)); RevealNode(tag); } else { MakeHyperWindow(tag); } } void DisplayNode(widget, client_data, call_data) Widget widget; XtPointer client_data, call_data; { char *tag, *node; XtVaGetValues(widget, XtNlabel, &tag, NULL); tag = XtNewString(tag); ExposeNode(tag); XtFree(tag); } Widget AddNode(name, parent) char *name; Widget parent; { Widget node = XtVaCreateManagedWidget(name, commandWidgetClass, tree, XtNtreeParent, parent, NULL); XtAddCallback(node, XtNcallback, DisplayNode, (XtPointer) 0); return node; } Widget FindNode(name) char *name; { WidgetList children; Cardinal numChildren; int i; XtVaGetValues(tree, XtNchildren, &children, XtNnumChildren, &numChildren, NULL); for (i = 0; i < numChildren; ++i) { if (strcmp(XtName(children[i]), name) == 0) { return children[i]; } } return AddNode(name, root); } char* ProcessMenuItem(buffer, parent) char *buffer; Widget parent; { Widget node; char *sp, *bp, *nodename, *help; sp = bp = buffer; bp = Find(bp, ':'); if (bp[1] != ':') { ++bp; while (*bp == ' ') { ++bp; } sp = bp; while (*bp != '\t' && *bp != ',' && *bp != '.' && *bp != '\n') { ++bp; } } BCOPY(sp, nodename, bp) node = FindNode(nodename); XtVaSetValues(node, XtNtreeParent, parent, NULL); free(nodename); return bp; } char* ProcessMenu(buffer, node) char *buffer; Widget node; { char *bp; for(bp = buffer; ; ) { bp = Locate(bp, INFO_MENU_ENTRY_LABEL); if (!*bp || *bp == INFO_COOKIE) { break; } else { bp = ProcessMenuItem(bp, node); } } return bp; } char* ProcessNode(buffer) char *buffer; { Widget node; char *bp, *sp, *s, c, *idx; /* It has got to exist */ bp = Locate(buffer, INFO_NODE_LABEL); sp = bp; bp = Find(bp, ','); BCOPY(sp, s, bp) sp = s; while (*sp == ' ') { ++sp; } if (strcmp(sp, "Top") == 0) { root = node = AddNode(sp, (Widget) 0); } else { /* * There's potentially too much in indexes, so ignore them. And, * furthermore, the repeated node names screw up the hierarchy. */ if ( (idx = rindex(sp, 'I')) && strcmp(idx, "Index") == 0) { free(s); return bp; } else { node = FindNode(sp); } } free(s); c = *(bp = Locate(bp, INFO_MENU_LABEL)); if (c == 0) { return 0; } else if (c != INFO_COOKIE) { bp = ProcessMenu(bp, node); } return bp; } Widget InfoOf(widget) Widget widget; { Widget popup; for (popup = XtParent(widget); !XtIsShell(popup); popup = XtParent(popup)) {} return XtNameToWidget(popup, "*info"); } /*ARGSUSED*/ void ShowInfo(widget, event, params, num_params) Widget widget; XEvent *event; String *params; Cardinal *num_params; { XPointer value; String nodename; if(XFindContext(XtDisplay(widget), (XID) XrmStringToQuark(XtName(widget)), context, &value) == 0) { XtVaSetValues(InfoOf(widget), XtNlabel, (String) value, NULL); } else { XtVaSetValues(InfoOf(widget), XtNlabel, "", NULL); } } /*ARGSUSED*/ void ClearInfo(widget, event, params, num_params) Widget widget; XEvent *event; String *params; Cardinal *num_params; { XtVaSetValues(InfoOf(widget), XtNlabel, "", NULL); } void BuildIndirectTable(buffer) char *buffer; { char *f, v[16], *sp, *bp = ReverseLocate(buffer, INDIRECT_TAGS_TABLE_LABEL); char *subinfo; int len; indirectTable = (TagTablePtr) malloc((unsigned) TABLECHUNK * sizeof(TagTableRec)); maxIndirects += TABLECHUNK; while (*bp != INFO_COOKIE) { sp = bp; bp = Find(bp, ':'); BCOPY(sp, f, bp) sp = ++bp; bp = Find(sp, '\n'); strncpy(v, sp, bp - sp); v[bp - sp] = 0; ++bp; if (numberIndirects == maxIndirects) { maxIndirects += TABLECHUNK; indirectTable = (TagTablePtr) realloc(indirectTable, (unsigned) maxIndirects * sizeof(TagTableRec)); } len = baselen + 1 + strlen(f) + 1; subinfo = XtMalloc((unsigned) len); strcpy(subinfo, basedir); strcat(subinfo, "/"); strcat(subinfo, f); indirectTable[numberIndirects].tag = subinfo; indirectTable[numberIndirects].pos = atoi(v); ++numberIndirects; } } void BuildTagTable() { char *bp, *sp, *s, v[16], *dummy; OpenInfofile(infofile); bp = ReverseLocate(buffer + buflen - 1, TAGS_TABLE_BEG_LABEL); if (LookingAt(bp, &dummy) == IS_INDIRECT_LABEL) { BuildIndirectTable(bp); while (*bp != '\n') { ++bp; } ++bp; } tagTable = (TagTablePtr) malloc((unsigned) TABLECHUNK * sizeof(TagTableRec)); maxTags += TABLECHUNK; while (LookingAt(bp, &bp) == IS_TAG) { while (*bp == ' ') { ++bp; } sp = bp; bp = Find(bp, INFO_TAGSEP); BCOPY(sp, s, bp) ++bp; sp = bp; bp = Find(bp, '\n'); strncpy(v, sp, bp - sp); v[bp - sp] = 0; ++bp; if (numberTags == maxTags) { maxTags += TABLECHUNK; tagTable = (TagTablePtr) realloc(tagTable, (unsigned) maxTags * sizeof(TagTableRec)); } tagTable[numberTags].tag = s; tagTable[numberTags].pos = atoi(v); ++numberTags; } } /*ARGSUSED*/ void Quit(widget, client_data, call_data) Widget widget; XtPointer client_data, call_data; { exit(0); } /*ARGSUSED*/ void DeleteTree(widget, event, params, num_params) Widget widget; XEvent *event; String *params; Cardinal *num_params; { if (hyper) { tree = 0; lastNode = 0; XtDestroyWidget(widget); } else { exit(0); } } /*ARGSUSED*/ void CloseTree(widget, client_data, call_data) Widget widget; XtPointer client_data, call_data; { Widget shell; for (shell = XtParent(widget); !XtIsShell(shell); shell = XtParent(shell)) {} XtCallActionProc(shell, "delete-tree", (XEvent *) 0, (String *) 0, (Cardinal) 0); } void MakeTreeWindow() { Display *display = XtDisplay(top); Atom wm_delete_window; Widget popup, pane, form, bpane, quit, close, info, shell; Dimension height; char *bp, *dummy; int i; if (tree) { for (popup = XtParent(tree); !XtIsShell(popup); popup = XtParent(popup)) {} XMapRaised(XtDisplay(tree), XtWindow(popup)); return; } popup = XtVaCreatePopupShell("treewin", topLevelShellWidgetClass, top, NULL); pane = XtVaCreateManagedWidget("pane", panedWidgetClass, popup, NULL); form = XtVaCreateManagedWidget("form", formWidgetClass, pane, NULL); porthole = XtVaCreateManagedWidget("porthole", portholeWidgetClass, form, NULL); tree = XtVaCreateManagedWidget("tree", treeWidgetClass, porthole, NULL); (void) XSaveContext(display, (XID) XrmStringToQuark("tree"), context, "Press and drag any button to scroll"); bpane = XtVaCreateManagedWidget("bpane", panedWidgetClass, pane, XtNorientation, XtorientHorizontal, XtNskipAdjust, True, NULL); quit = XtVaCreateManagedWidget("quit", commandWidgetClass, bpane, NULL); (void) XSaveContext(display, (XID) XrmStringToQuark("quit"), context, "Terminate the application"); XtAddCallback(quit, XtNcallback, Quit, (XtPointer) 0); close = XtVaCreateManagedWidget("close", commandWidgetClass, bpane, NULL); (void) XSaveContext(display, (XID) XrmStringToQuark("close"), context, "Delete this window"); XtAddCallback(close, XtNcallback, CloseTree, (XtPointer) 0); info = XtVaCreateManagedWidget("info", labelWidgetClass, bpane, NULL); (void) XSaveContext(display, (XID) XrmStringToQuark("info"), context, "aXe Information System Version 1.0"); for (i = 0; i < numberIndirects || numberIndirects == 0; ++i) { if (numberIndirects == 0) { OpenInfofile(infofile); } else { OpenInfofile(indirectTable[i].tag); } for (bp = buffer; bp; ) { if ( !(bp = Find(bp, INFO_COOKIE)) ) { break; } if (LookingAt(bp, &dummy) == IS_NODE) { bp = ProcessNode(bp + 1); } else { ++bp; } } if (numberIndirects == 0) { break; } } XtRealizeWidget(popup); if (hyper) { for (shell = XtParent(hyper); !XtIsShell(shell); shell = XtParent(shell)) {} XtVaGetValues(shell, XtNheight, &height, NULL); XtVaSetValues(popup, XtNheight, height, NULL); } if (currentTag >= 0) { PositionNode(tagTable[currentTag].tag, True); } else { PositionNode("Top", False); } wm_delete_window = XInternAtom (display, "WM_DELETE_WINDOW", False); (void) XSetWMProtocols(display, XtWindow(popup), &wm_delete_window, 1); XtPopup(popup, XtGrabNone); } void GatherFromNode(buffer) char *buffer; { char *bp, *sp, *fp, *nodename, ch, *help; bp = Locate(buffer, INFO_NODE_LABEL); while (*bp == ' ') { ++bp; } sp = bp; bp = Find(bp, ','); BCOPY(sp, nodename, bp) while (*bp && *bp != INFO_COOKIE) { sp = bp; if (LookingAt(bp, &bp) == IS_SECTIONING) { ch = sp[1]; while (*bp == ch) { ++bp; } if (*bp == '\n') { fp = sp - 1; while (*fp != '\n') { --fp; } ++fp; BCOPY(fp, help, sp) (void) XSaveContext(XtDisplay(top), (XID) XrmStringToQuark(nodename), context, (XtPointer) help); } break; } else { ++bp; } } free(nodename); return; } void GatherSectioning() { int tag, ind; char *node, *file; for (tag = 0; tag < numberTags; ++tag) { if (indirectTable) { for (ind = numberIndirects - 1; ind >= 0; --ind) { if (tagTable[tag].pos >= indirectTable[ind].pos) { file = indirectTable[ind].tag; break; } } } else { file = infofile; } OpenInfofile(file); if (indirectTable) { node = &buffer[tagTable[tag].pos - indirectTable[ind].pos + indirectTable[0].pos]; } else { node = &buffer[tagTable[tag].pos]; } GatherFromNode(node + 1); } } /*ARGSUSED*/ void ShowNode(widget, client_data, call_data) Widget widget; XtPointer client_data, call_data; { String tag = XtNewString(((hyperCallbackStruct *) call_data)->text); RevealNode(tag); XtFree(tag); } /*ARGSUSED*/ void ExplainNode(widget, client_data, call_data) Widget widget; XtPointer client_data, call_data; { hyperCallbackStruct *hcs = (hyperCallbackStruct *) call_data; if (hcs) { String tag = ((hyperCallbackStruct *) call_data)->text; XPointer value; if(XFindContext(XtDisplay(widget), (XID) XrmStringToQuark(tag), context, &value) == 0) { XtVaSetValues(InfoOf(widget), XtNlabel, (String) value, NULL); return; } } XtVaSetValues(InfoOf(widget), XtNlabel, "", NULL); } /*ARGSUSED*/ void Last(widget, client_data, call_data) Widget widget; XtPointer client_data, call_data; { if (lastTag >= 0) { RevealNode(tagTable[lastTag].tag); } } /*ARGSUSED*/ void Tree(widget, client_data, call_data) Widget widget; XtPointer client_data, call_data; { MakeTreeWindow(); } void SetHyperWMHints(shell) Widget shell; { Window window = XtWindow(shell); Display *display = XtDisplay(shell); WidgetList children; Widget viewport = XtNameToWidget(shell, "*view"); Dimension wHeight, vHeight; int margin; XFontStruct *font; XSizeHints hints; long supp; XtVaGetValues(shell, XtNheight, &wHeight, NULL); XtVaGetValues(viewport, XtNheight, &vHeight, NULL); XtVaGetValues(hyper, XtNnormalFont, &font, XtNmargin, &margin, NULL); /* * All this kind of assumes that the height of * highlightFont is the same as that of normalFont. */ if (!XGetWMNormalHints(display, window, &hints, &supp)) { hints.flags = 0; } hints.flags |= PResizeInc | PBaseSize; hints.height_inc = font->ascent + font->descent; hints.width_inc = font->max_bounds.width; /* 4 = vSpace in MakeHyperWindow */ hints.base_height = wHeight - vHeight + 4; hints.base_width = 2 * margin; XSetWMNormalHints(display, window, &hints); } typedef struct { int rows; int columns; } RowColRec, *RowColRecPtr; static XtResource rowsColsResource[] = { { "rows", "Rows", XtRInt, sizeof(int), XtOffset(RowColRecPtr, rows), XtRImmediate, (XtPointer) 24 }, { "columns", "Columns", XtRInt, sizeof(int), XtOffset(RowColRecPtr, columns), XtRImmediate, (XtPointer) 80 }, }; void MakeHyperWindow(nodename) char *nodename; { Widget popup, pane, view, hpane, quit, map, info; char *node; Display *display = XtDisplay(top); Atom wm_delete_window; RowColRec rowsCols; XFontStruct *hyperFont, *normalFont; Dimension width, height; int rows, columns, margin, vSpace = 4; popup = XtVaCreatePopupShell("hyperwin", topLevelShellWidgetClass, top, NULL); pane = XtVaCreateManagedWidget("pane", panedWidgetClass, popup, NULL); view = XtVaCreateManagedWidget("view", viewportWidgetClass, pane, NULL); hyper = XtVaCreateManagedWidget("hyper", hyperWidgetClass, view, NULL); XtAddCallback(hyper, XtNactivateCallback, ShowNode, (XtPointer) 0); XtVaGetValues(hyper, XtNnormalFont, &hyperFont, XtNmargin, &margin, NULL); XtVaSetValues(hyper, XtNstartHighlight, soh, XtNendHighlight, eoh, NULL); links = XtVaCreateManagedWidget("links", hyperWidgetClass, pane, XtNskipAdjust, True, NULL); XtAddCallback(links, XtNactivateCallback, ShowNode, (XtPointer) 0); XtAddCallback(links, XtNhyperCallback, ExplainNode, (XtPointer) 0); XtVaGetValues(links, XtNnormalFont, &normalFont, NULL); XtVaSetValues(links, XtNstartHighlight, soh, XtNendHighlight, eoh, NULL); hpane = XtVaCreateManagedWidget("hpane", panedWidgetClass, pane, XtNorientation, XtorientHorizontal, XtNskipAdjust, True, NULL); quit = XtVaCreateManagedWidget("quit", commandWidgetClass, hpane, NULL); (void) XSaveContext(display, (XID) XrmStringToQuark("quit"), context, "Terminate the application"); XtAddCallback(quit, XtNcallback, Quit, (XtPointer) 0); #if defined(XtSpecificationRelease) && XtSpecificationRelease > 4 map = XtVaCreateManagedWidget("map", commandWidgetClass, hpane, NULL); (void) XSaveContext(display, (XID) XrmStringToQuark("map"), context, "Display the hypertext tree"); XtAddCallback(map, XtNcallback, Tree, (XtPointer) top); #endif info = XtVaCreateManagedWidget("info", labelWidgetClass, hpane, NULL); (void) XSaveContext(display, (XID) XrmStringToQuark("info"), context, "aXe Information System Version 1.0"); RevealNode(nodename); XtVaGetApplicationResources(popup, (XtPointer) &rowsCols, rowsColsResource, XtNumber(rowsColsResource), NULL); XtVaSetValues(view, XtNheight, (Dimension) (rowsCols.rows * (hyperFont->ascent + hyperFont->descent) + vSpace), NULL); XtVaSetValues(hyper, XtNwidth, (Dimension) (rowsCols.columns * hyperFont->max_bounds.width + 2 * margin), NULL); XtVaSetValues(links, XtNheight, normalFont->ascent + normalFont->descent + vSpace, NULL); XtRealizeWidget(popup); wm_delete_window = XInternAtom (display, "WM_DELETE_WINDOW", False); (void) XSetWMProtocols(display, XtWindow(popup), &wm_delete_window, 1); SetHyperWMHints(popup); XtPopup(popup, XtGrabNone); } /*ARGSUSED*/ void StartDrag(widget, event, params, num_params) Widget widget; XEvent *event; String *params; Cardinal *num_params; { dragX = event->xbutton.x_root; dragY = event->xbutton.y_root; } /*ARGSUSED*/ void Drag(widget, event, params, num_params) Widget widget; XEvent *event; String *params; Cardinal *num_params; { Position x, y; XtVaGetValues(tree, XtNx, &x, XtNy, &y, NULL); XtVaSetValues(tree, XtNx, (Position) (x + (event->xbutton.x_root - dragX) * 10), XtNy, (Position) (y + (event->xbutton.y_root - dragY) * 10), NULL); dragX = event->xbutton.x_root; dragY = event->xbutton.y_root; } /*ARGSUSED*/ void DeleteHyper(widget, event, params, num_params) Widget widget; XEvent *event; String *params; Cardinal *num_params; { if (strcmp(XGetAtomName(XtDisplay(widget), event->xclient.data.l[0]), "WM_DELETE_WINDOW") != 0) { return; } if (tree) { hyper = 0; XtDestroyWidget(widget); } else { exit(0); } } /*ARGSUSED*/ void Notify(widget, event, params, num_params) Widget widget; XEvent *event; String *params; Cardinal *num_params; { Atom gotAtom; int gotFormat; unsigned long gotItems, moreBytes; unsigned char *propValue; if (XGetWindowProperty(XtDisplay(widget), XtWindow(widget), XInternAtom(XtDisplay(widget), "AXE_AXINFO", False), 0L, 64L, /* 64 is an overestimate */ False, XA_STRING, &gotAtom, &gotFormat, &gotItems, &moreBytes, &propValue) == Success) { if (gotAtom == XA_STRING) { ExposeNode((char *) propValue); XtFree((char *) propValue); } } else { /* Ought to do something here just in case */ } } XtActionsRec actions[] = { "delete-hyper", DeleteHyper, "delete-tree", DeleteTree, "show-info", ShowInfo, "clear-info", ClearInfo, "start-drag", StartDrag, "drag", Drag, "notify", Notify, }; static XrmOptionDescRec options[] = { {"-tree", ".tree", XrmoptionNoArg, (XPointer) "True"}, {"-node", ".node", XrmoptionSepArg, (XPointer) 0}, {"-rows", "*hyperwin.rows", XrmoptionSepArg, (XPointer) 0}, }; static XtResource appResources[] = { { "version", "Version", XtRString, sizeof(String), XtOffset(AppResRecPtr, version), XtRImmediate, (XtPointer) 0 }, { "tree", "Tree", XtRBoolean, sizeof(Boolean), XtOffset(AppResRecPtr, tree), XtRImmediate, (XtPointer) False }, { "node", "Node", XtRString, sizeof(String), XtOffset(AppResRecPtr, node), XtRImmediate, (XtPointer) 0, }, { "infoPath", "InfoPath", XtRString, sizeof(String), XtOffset(AppResRecPtr, dir), XtRImmediate, (XtPointer) 0 }, }; main(argc, argv) int argc; char *argv[]; { XtAppContext app; Display *display; AppResRec resources; String file; int len; void Listen(); context = XUniqueContext(); top = XtVaAppInitialize(&app, "Axinfo", options, XtNumber(options), &argc, argv, (String *) 0, NULL); display = XtDisplay(top); XtVaGetApplicationResources(top, (XtPointer) &resources, appResources, XtNumber(appResources), NULL); if (!resources.version || strcmp(resources.version, QVERSION) != 0) { char message[1024]; Widget noapps, msg, quit; strcpy(message, "This is "); strcat(message, QVERSION); strcat(message, ".\n\n"); strcat(message, "The application defaults file\n"); strcat(message, "for this release has not been\n"); strcat(message, "found."); if (resources.version) { strcat(message, "\n\nIt may help to know in solving\n"); strcat(message, "the problem that the defaults\n"); strcat(message, "file for "); strcat(message, resources.version); strcat(message, " was found."); } noapps = XtVaCreateManagedWidget("noapps", formWidgetClass, top, NULL); msg = XtVaCreateManagedWidget("msg", labelWidgetClass, noapps, XtNlabel, message, NULL); quit = XtVaCreateManagedWidget("Quit", commandWidgetClass, noapps, XtNfromVert, msg, NULL); XtAddCallback(quit, XtNcallback, Quit, (XtPointer) 0); XtRealizeWidget(top); XtAppMainLoop(app); } basedir = XtNewString(resources.dir); baselen = strlen(basedir); MAKESTRING(file,INFO_FILE_LABEL) MAKESTRING(node,INFO_NODE_LABEL) MAKESTRING(prev,INFO_PREV_LABEL) MAKESTRING(next,INFO_NEXT_LABEL) MAKESTRING(up,INFO_UP_LABEL) MAKESTRING(menu,INFO_MENU_LABEL) MAKESTRING(entry,INFO_MENU_ENTRY_LABEL) MAKESTRING(xref,INFO_XREF_LABEL) MAKESTRING(btag,TAGS_TABLE_BEG_LABEL) MAKESTRING(etag,TAGS_TABLE_END_LABEL) MAKESTRING(itag,INDIRECT_TAGS_TABLE_LABEL) MAKESTRING(tagi,TAGS_TABLE_IS_INDIRECT_LABEL) XtAppAddActions(app, actions, XtNumber(actions)); if (argc > 1) { file = XtNewString(argv[1]); } else { file = XtNewString(INFOFILE); } len = baselen + 1 + strlen(file) + 1; infofile = XtMalloc((unsigned) len); strcpy(infofile, basedir); strcat(infofile, "/"); strcat(infofile, file); XtFree(file); BuildTagTable(); GatherSectioning(); { int dummy; if (resources.node && IsTag(resources.node, &dummy)) { MakeHyperWindow(resources.node); } #if defined(XtSpecificationRelease) && XtSpecificationRelease > 4 else if (!resources.tree) { MakeHyperWindow("Top"); } if (resources.tree) { MakeTreeWindow(); } #else else { MakeHyperWindow("Top"); } #endif } Listen(); XtAppMainLoop(app); } void Listen() { Widget listen; Window window; Display *display; listen = XtVaCreatePopupShell("listen", topLevelShellWidgetClass, top, NULL); (void) XtVaCreateManagedWidget("core", coreWidgetClass, listen, XtNwidth, 1, XtNheight, 1, NULL); XtRealizeWidget(listen); display = XtDisplay(listen); window = XtWindow(listen); TrapErrors(display); /* If axeis is already running this one will take over listening duties */ XChangeProperty(display, XDefaultRootWindow(display), AxinfoUserAtom(display), XA_WINDOW, 32, PropModeReplace, (unsigned char *) &window, 1); /* * Stamping the listening window with the AXE_AXINFO_user property * enables a check to be made that the window id stored under the * AXE_AXINFO_user property on the root window is still valid when * aXe comes to attempt to notify axeis. If the window exists but it * doesn't have the property then axeis has been terminated and * the id reallocated, otherwise we should be OK. */ if (xerror == Success) { XChangeProperty(display, window, AxinfoUserAtom(display), XA_STRING, 8, PropModeReplace, NULL, 0); } DontTrapErrors(display); } axe-6.1.2.orig/Help/axinfo.h100644 243 144 2441 5550557110 14317 0ustar joostusers/* String Constants. */ #define INFO_FILE_LABEL "File:" #define INFO_NODE_LABEL "Node:" #define INFO_PREV_LABEL "Prev:" #define INFO_ALTPREV_LABEL "Previous:" #define INFO_NEXT_LABEL "Next:" #define INFO_UP_LABEL "Up:" #define INFO_MENU_LABEL "\n* Menu:" #define INFO_MENU_ENTRY_LABEL "\n* " #define INFO_XREF_LABEL "*Note" #define TAGS_TABLE_END_LABEL "\nEnd Tag Table" #define TAGS_TABLE_BEG_LABEL "Tag Table:\n" #define INDIRECT_TAGS_TABLE_LABEL "Indirect:\n" #define TAGS_TABLE_IS_INDIRECT_LABEL "(Indirect)" /* Character Constants. */ #define INFO_COOKIE '\037' #define INFO_FF '\014' #define INFO_TAGSEP '\177' #define INFO_CHAPTER "\n*" #define INFO_SECTION "\n=" #define INFO_SUB_SECTION "\n-" #define INFO_SUB_SUB_SECTION "\n." #define IS_NODE 1 #define IS_TAG_TABLE 2 #define IS_INDIRECT 3 #define IS_INDIRECT_LABEL 4 #define IS_TAG 5 #define IS_NEXT 6 #define IS_PREV 7 #define IS_UP 8 #define IS_MENU 9 #define IS_ENTRY 10 #define IS_XREF 11 #define IS_SECTIONING 12 axe-6.1.2.orig/Help/axinfo.man100644 243 144 3523 5550557110 14645 0ustar joostusers.TH AXINFO 1 "January 1994" "axinfo Release 1.0" .SH NAME axinfo - an X info reader .SH SYNOPSIS .B axinfo [ -toolkitoption ...] [ -tree ] [ -node node ] [ -rows rows ] [ file ] .SH DESCRIPTION .I axinfo is an X Window System reader for info files (generated from GNU Texinfo source files) built using the Athena Widget Set toolkit. It was specifically written for use with aXe and is not yet fully capable of being used to browse info file directories. It can however be used to read a single info file at a time by setting the infoPath resource to the location of the info file and specifying its name as an argument. The name must be given in full, i.e. including the .info suffix, e.g. axinfo -xrm '*infoPath:/usr/local/texinfo3.1' texi.info .PP axinfo has two windows: a text window, which is displayed by default, and an optional tree window which shows the node hierarchy as a tree. Navigation of the information in the info file being read is performed either by clicking on hypertext, i.e. sensitive, text in the text window, or by clicking on node buttons in the tree window. The latter may provide more direct access to a particular node than the former. .PP When the command line option .I -tree is used axinfo starts up displaying its tree window only. Specifying the option is equivalent to setting the .I .tree resource .PP The command line option .I -node can be used to initially display some node other than `Top'. It corresponds to the .I .node resource. .PP The option .I -rows specifies how many rows of text are to be displayed in the text window. It corresponds to the .I *hyperwin.rows resource. .SH ACKNOWLEDGEMENTS axinfo is built around Baudouin Raoult's HyperWidget widget. .SH SEE ALSO axe(1) .SH AUTHOR Jim Wight (j.k.wight@newcastle.ac.uk) .br Department of Computing Science, University of Newcastle, Newcastle upon Tyne, UK, NE1 7RU axe-6.1.2.orig/Help/version.h100644 243 144 71 5550557110 14455 0ustar joostusers#define VERSION axinfo 1.0 #define QVERSION "axinfo 1.0" axe-6.1.2.orig/Help/axe.A4.ps.Z100644 243 144 256557 5576304461 14550 0ustar joostusers%B@™Ò"™7bʴᆂ%†È)†Î9:@±“Î5\ÐÈQÄ7pòÈIs 1rà°ÁfŽ2@H C&͘0l@ÉSÄ”7fèÜ 3ña *iè°)“1 ž2.6¦q*‘"4oÜ©H4u@)#ˆ0ièaCÇ ¸1sÐp %Ì™2s2ÊÈÂ!ľŸÈ!S#ˆ sÆ”qCÆ©7u(§qsæ2žŒ0 ƒÌa2œ¡|²M›Étæ<$b%ÉÀÖmÂPf²¹¬V Z4aµÌìÚÖ‘#9£Ù2X@`¦§Î˼42„1CG Ô6,—9³Šœ7c¦”¡“‘N<.àœBÁ *Љø|)£Fèžc¼Ä˜Ïa¡_€ $Dž ¼àÄö1`ƒBì!ÆfdhT†}8Ñà{¼76ˆÅS€àD Ñ RìA‡ºÍÁY%¾†™ÔEyø‚s¤¡GQ1Ä 9µQGPB±Ò‚{ìÈÆ{lZ J*Ú—](0FX?ÑÑG2©`o°aX ödÇ’9Y!›n~–FiÌéÆx DTQVbyçm¾¹'E©@ jÊ ‚“A…㙚¨ž Ú‰§¢ idQæ$©’Ùå?;Gm û=- QK.úúrÖT8?`ͯ~ë¹_ ð€3ì!2À˜þ§>¾/~p9 ´¸G?æ¡þkÃ`A&+'Ldpƒlu°]èÃCGXBø%KI)L ñ—†Üüe†lšfßኀD¬¹N§Âœît¨"C†V„¦‹ïf/ðÈ,ž¡W.³ÏÀµ‹Å+cßäð760Fø ƒŠ‚iµ)()jß Ì†6æCïÙ R4··…8*LQÑWÁèL¯WNœÑÍb(ð1Ð ß1 ðétpa[,ÙÀNâO|äKVªLÙ‚MH[?‘½ÊÀɰ•ñóäþZò’ƒq dRR \ $RrRƒš,%1‰#Å.„°‡~)Ù|X†ÜÌa ÒŒE&r1"”k cÞõ –D#Ž ~IüÓº€©ê1hg+Š ÁÙII–h…¤Ü>’ÈzÚ,E¿‹ÔÙ¾ö І0 ýœõGÊR‘Ñú¤†¦ký뉒ŒâYÔ®$œ/œ.&”ì_ñWÙP’¿Ças nxÃÜ`!–¢Á¥í|Á’(9 RbÉfð¥I½aŽi\EµNÎ 6·‚•³”¤Âö­ÊZ¡©j³V•*¸à&ž£C¹¢`…>”K eES®T”Ï…nBTJrT“î4›ùºHQæpÓ;À!š @éböcŸºÂ¡¥oxiLg"›â´ŠQÊSÄ*X•q²ˆU¬Li*Y9Ð!³,ªh\_à)Då NÀ{¦N»§èİåÓœ^@›$ø0µ‡ëOi.×6…FIý©öp¸áðˆÊk_hàH]•n v`PÂg3Ôà8ˆ nPšÞ‰êHÀ³.vµË]öõ©AŒUÚr|õ5GR˜Ú/‹ú10 IDxlp<ä–QO d³à¶¹¬Av(€§Ò6¹-8Ñ)k»¬°‡‹¡5Pú¢¿Tj´wÊç ‹CÐô7‘½ÅõÃ!fV¯¿@k¡q±°6ã9Ø(¾B~æ‡å!eˆ° ‚½Ì¸V¹1PàèPÈB¾ˆYãê#¶bj­@2k•³¬V¶™2{ØÃæàSVg™Ã(ŒŠÃŸLEZÖÕƒÛ¶å¢Ä·"{À¯~§Mkbó É+7Í*f2ÏÑÌi~Ô2×ü`98PnFRB묓©å9¿f‚æ_ü¬@oSšWör»Èº·1—yF5¢nìX¬!ãaD¬¦–µ¢B#7´î"«nÃQ×¹F‹FlèMR2g%*ØÂîuœýë`ÿ)©fèYP­M½^, {Ð5Rß ºµpÀ΃P³^À60:¡‘ƒ¶y}±& HY27 Wé<’¾»Wõ†áZ¬&pgû†‹¿ÛE®…€`àÁÛ·’þ‚3Àøà3ß­¸‡œ0\ {øÅÖ°‡~³Ë>wx¸ºwm‘‹ù¬WüÁ.Öé.+oMQž“˜7è .ÿ˜Í_—+içp$j~1,õ æë¯T~1†&E#ßöÅòñ¡Û‘ AéUHú,é >UÀŠÞuA½ÚÜtQâTCó G=¡Äö“ ñm9ˆA pÁÐÔ 3À nRš×Æv‡‡­Pð‚›¾f7:ÃAÜð7¨a wxAqZ¼ k…ƒæ¯’ޤ¨ý—H¨¤&g<À®†0ûÚ»0àoxn Ôàµ>Ø»H…‚´¶t©?1Šæ;¿ùоô£Oýé[¿ú¹>wb@ìÞä;>€ °ˆ@|Œt…%=ö»¿ýð¿üãOÿù+`þø¯¿þóÏÿýß¿0€Fp3ygá'{A~2ƒ1Òz¯§|ë÷°ExD€ˆ'Á‡Ã×€k…'p{°5{7008üu0€]Ì÷‚Dẽ°uƒ°}8ȃ;¨ƒ9ƒ'hDÈ~>„=„G¸„7HTHøƒBø„RÈ„QH…8xîÇ~1p1‚÷}6~E<0ý§{¹·‰šØ‰›‡xè†ô€4Ð…x0À p"u‰ôƒ¯‹0 †jh‚€©ˆ˜Š>@ãÇD¨‚Á[A0‹‚‡‚G•X†¸Ç‚ü…xÐèˆÇ_θ‚8àˆC€Ú¸‚ÙÈÛݎߎäH3al¸‹ˆWD…{ÍÇ‚7P9À…3ЋH†Ü±†C¨ŠÈU؃éÙŠø‡ù™í·‡00ðHóøˆËØ~‚÷Zü¥†ˆg'x30*(ŽŽްՑ%y‹G›[gÈ‚h¸ƒ h¶€†Gm¨DˆXh8P„‚Wð(-$‘–H‘+}jƒ/¨“ÜÁwM©ˆ·xØ'x‹y؃)ÉgØ‘Ìב¨•*Ø‘yBˆxvÈ“9”YE™%éF+ˆƒ3€ƒ,T8x{ÆÃ”¯Å†B˜”¸ƒ*ƒEh„y˜ü¸“±¨“F°–˸Ž8É~«h]9{³“˜ [ ¸™)Ø”é–OihØ’C0’äˆI–g«˜gy‹@©“BI”evh†ç٥긋*9•vØ|YçÈ~ˆ§…×’É ’Ìé‚ÜHzɂՃg›ñ蘖hŠH„E°“·ŒÜ‰Œ! iž—Y;Èè)šîix Ù†ñ©©’=‡De1‘ÙŖ̘šÏ˜jXzŽðx” E€hi+˜ÆI‘ÏH–àÈ7,y†y¡, €N¹˜ zjIÙŒç~iŽŽ¸œË9_ÙœÐùŒCºY˜¤‰†·è’Mé—J¹‰(.q‰³éŸx†xˆ¤s¨¤hœ;h›¡8q “=H¥¡h“VY)ù‡˜•;˜]L ¦x(¦O*‡/™‡+ès‡Uʦs€ àŽ¸šsê¥9Фw:šMº ù‘A`Š™wÊh] @†… …$I‡vh‡8Ȩ? •tˆ{Ž©*—‹„&¹F °¹‚—…“j‡&)ª*Hªt8ª%Yª'I©th„ŽÈ|…É©+ˆ›AyÇm)¥—I’ÎÙ†2ð|žš¨ïˆ¤6à¥6 §wi¥0)™s8¥r¹ƒÎ­xئÔj•$h•¥ˆ¤Ùú¥yÈ‘N؆¼ºƒº:—¦(y7ËX˜®J¢*‡†g‡.œ•ŠžòJTÌÇž÷ …øJ•Cˆ¤Ìç¯s }ûº¯êœ6È­õÚ­t¯«Ê¨šº‡1@«¶Ú…>`„a¨Eø©Ÿ €v‡íÚ|Nø®g ¯A8°ú …H:ŒA°&[²PX‡\Ц2ë¤3‹‡NZ„OZеj®1‘®”¹“‘*‡0h¯ìZ´ j´Š´B»´Ë´´D{´R›´Së´J´Þ©˜Ùµ³ß§ŒLR¨ÀH™fœdû²yX¶ck¶h{¶jû²Q˶i+‡jšŠ€ŠŠEà³7Ø ðж:º°wè H‡ìI‡Yêˆ6›ž'{‡Y:¬6û«6K4[œZ¥ðç¥Ðg¹Øø·Nú©LÛ¹§j•ðz†Q;g)¶9ù åú}w{%±S¹‡û·fk¦rø‡°+»´[³¸«»/뱚)‡¾ë«ž‚+‡×©•û‘ȵy‡>+®–—™*½gØ{°E£Æc½0€½©x‹Ük£°¾ƒw†â[¾g¸œ‰Š¾çëˆé ƒ@z¾î+P绚éK¿ó{é Žd ¦û«¿é ÿ«…ç ÀÜxÀй3!¤³g›©‹þ)¶ ,—)i„†g½|žã{”æi¸æÙ¢°Å—! ‹!x†¦' Ž'üŽ!ÌÂèÉ…-Œw1œ-Ì}5L!ì„F•-…(yÀùxº‹ùÀÜ7‘1è¬*¬¤Wø·²7мžºªBk•†9‡88¥¸‡Å‚§Åσ[¼ƒíøÅk(ÆÊÅrj˜T,ŧڒ¡«§rè¥-¤’Ü(¬Ý9‡1AÄwk‰‡Š©Ç«¨WªPµ’ ©O[ÈrØ•gˆ³¹{»³Ë»ÆÃÈ‹»CœzGÄA0‘³¤h €6p†Ÿ¬™g˜£œ)ª|ºX¸•k‹•(ùÊ©*Ênh‡4,(›G©DL‰ØŠ;©È°8˜êI’5yÀ¹iÌÇÄÉü¿9ÀNŠtìÆv̤@<ÍÐLÍÑ\ÍO*ºÖŒ‡ÙüÍØÎ׌‡R*¶h˜wµ¨àè  Ç”9Á¢Z©"ËÁ$ë·ö\Ïø<²úLÏŠ7Ïþì®}Ïûlxè¦éÙ†Üé’ì©›â*¹8JÄÊh‰«¼ÐË)Ÿ^Œ¸O9•<¸Pº¸±i€Œ­(¥‚'˜BÈ|€iŸu Ž<*„0¨ƒ7¥\«[(¤B`›)‹ñØ“º\óØŠ–¹ÍÝ,ÍÚLÇl­¤m=Í *¤ »§8H’)IÌÍl̹×zÝ×ÄÌ×v×à „1  ²Ï AD­w#Š–£`z“}·p{•â ÓÜ.iyÄ=™$FÌÙ» ÉŽ\ÚNú¶\¹ƒ1ϧjµ~üÚ{ȲM‡Ã+„£[ӣ鸊H{ ¤éü}”X” ŽÔÉ—çØvH{Á¸¶eë„S‰Ð))x -Ú@éÙú)×Û·Ô)YÝ•ÍÜ/K„3 Þ”MÞßݶBkÎD‰ƒGÃèZ”›šðxù˜Žö½£MYÜi™ 8•X¹‡åìÞù¡©30Ó3àÉ&<˜† <©ŸìÖžÖk=áh Æo½ÍqÃl¼°ÀJ’mâz*âL⺬ª%>â*¾ÚÛ‹Ü< £Þ’‹Š6®x¡xÖ‰ºã=ÝãnÌã?îã ¾ì}DuÉzlájáK®ä>ÍJ=Çvxâ:ªÂÛ Š"ù¤D€¤BJÉÝ8š=(Õwš•I<š>­ÂFxF ¥.þÛyGáƒf-ä@Äu~çt΢A¾çvžç|~ºƒWä4ŒäÀx{ކ¸ ^‘7(¦XíèÂü×B(éÁ|À•N’—é|é~Ø×œþéL„ú<É}}ùàj˜®´—£¾§{»°¥úÌ$â+Në)~ë¶žë(.êB ¤Ö­wF-ÜØxm¨—ÍçÉŒšìЍì1ȨžÜ¨ NÜKÝà¿^í\èqÍ~¯^×a)Øy-éàØâî×Ý~ÀN×hÈ~¤—Lþä®Ö€¾‚@zXøÙ0>{-Ú}ž ‹E0 ~Þç|ŽçýÊ’§Þ“í'† ãF †ü•¯j¨‚™q¹ˆÜ!Ôæ Kžˆ–T©†ìg‹ êÖ}ð×°ì¹ÐªíÆÓ+Ôÿ.ð}îï0’CóÍÇYÙÕôÞ˜ë§ê¢­ë°þó³Žâ¶~â@_ëBô>ݺm½^ðúyïú‰–& €$¹zšÐÿ … Ûž1HÒ0¼†4,®&]’cïîjž!›$¿çî,¥Ê‘ªJ—JõÉ_ í0ˆõ[ȯÍG‚\ßïù‡ wVy¥öŠXŠ8,®é¤Ý=‡ÿ¤ÒmÇÄ‹º¿Ž®×N„QþÕ¤Ù·Þ­ˆË]ïäIÿÓkZ¥Xú¥MüÐ[‰Ûí£M¿ö>+¤p¿’Uõ{ °[_øºlÅ^øÜQöHáíÎõ=|¦eúƒ$Ýï\ZƒûÒI²…õ®Ÿl{9ù†˜÷[õ‰š•É|bþ«˜]“^–š [ëýëØÍS è:£‘|±G‘Δۻ½)H–ʸw…Z~F <3,ÄT(è%Œ(Y*gQ©2ÝžŠ„–‘eW{è!Ó¥çD›ØÂ=¢M´-» ¸†˜Ԁ͎~@'•™SW§ ºhÅ<`|#°ŠÀØBH  dpâÀ˜a ´ÆîÀ(}à<‚p'‘:†„…îÏ4Bt.`¡ PJj·§¨ÀTLÒ1º\»Ñ€Ò€´Y¦2CzHÏi*%uÖÐ ´bƒp°YÅÁ7(ë |ƒ\ª ¾>;èû༃~P Â9h†ò !üƒ¿ ¦ºG‚RPRh$´¢45ñ†V3N‰'Q=|×™Ú¡N˜±D¡=ô„æìg}$”î4Pš€*Ë&C Ä P[Rcc,½´ªäÍ^aIrˆíÈ!扸êàZ– <ñ8e©õS¸Œ’žz….©A•6ô ¯ØÖóˆ‰*®Ý¢%ŸTÒ[Ðj%ª+a¤®fZ?lˆ‹‹öáÄhÇ$¢N\CÆ(ZÂGxàâQA\F}ëÐY'–“˜¢ª‡Lq ±¹Õ·Ü޲c+bE†TØÔ”\ûЉ,™ýA¢@Q)9!ðÔÎ[lv.qA½Á—ÙÒnˀќ Äe ——Êf.J©4È7Ú#‡7® Æ!wãâ]Ž“ˆOªÅݸ˜ !_—ÃCè8FÍxã^³ÚAžñÆ &ÈH•Æ¡5;p•Q4CoÆ©¸ºx—m*Du5÷Ž[IG,!©z—¤ W–VlN+¦;·f•Vã[cžòá!ØøÒR¡O¢„)p*>ÇÁÐŒ"j¸[„ÊuÑÆ‡eÇ!Å«xT %•Dñh•²’i4"Ñ=™FÉã’zˆ‚m%´$á#n´ <¾-øXú*ÞÜ‚^ÿ‘?Ò¬(7 é#93®$å<™}’%EH~e)¤CœÅQÄWhà8$†Œ‰2ÊmÁ † ªŽE  çe±ÀV‰\Ž/ò¡¥Ë(#Óât¾q8ÖÈ¥Ç!|?<¦;Ç—íˆdŽ‚>Ò2eÆl§¤Æa…ôŽÎ*ÊIÿøedP¼‘2JÍH‰8+£w, ðF"ÆIñ–¤¬‘cRHz64¹&sd›$“R©}+ËÄ Y¢eúi (ÑĹõáÔLBEªÈ_uÔRJ„…‰1©@\–iŸ;2gØå%Ƴ©¤[r´FÁ‰29±Lœ2”lÔPŸ²!¥¬N9*S´*Œ°q9Áƈ*[%«|•6.UžÊP¤Ã\e¬´•9W.G]™ue³RiêêÖÃYÄÉh€Qœ2€é“ÊY*‹€Í*3v'Í¢Ž„òâ$ea#·lƒ©PXÇïØ·Æ%»›…™’'}«] ­X"»x ‰RFP6­,˜d¼kï¬J™µù.%“ê—æŒIÃÐXÓ” "˜9Ql)ϸ›rei¤†·òaú&i×øál R³'?$ýÔ5fÅ3l«š}ÌS)2ËY»™?’7bÆ< kËìN.s,Ž«Xù-£œê\êfÆŒ¶§nFã{©ª:)¥ŽZ ÁG@+ª,ÓGº Wšrš?v¸±«¦âé‘K“ÍKa4Ý bN´´9·ØåüœÑ BÀ™6Ô¥›ÄnH1°N™L‘UP„6sæ,—Ú`bQ:±M@Øg†2 £ •—xÂÆáÉ ¥ª‚Sjf ¸[$à>Ò´‹BåÌ”Y0Ü$›"®*Cçð7ž®¿è»gÂüž<1‚Ïž˜0eù ŸX(j!"‡œNÜ|LêÅÏçi_ .ãœð ÞD½¨?ë'ÿÜbù€îÏúub<â‘™ð&Ž+)Ù'M н³¦H^'”²³-}ÇrF:•"ç\œUi\¥  x áb²ƒ”ZðKâi£G†ÏÓ0ÁP#¸D_h»Tszhâ5Ñ)ZÉbe¢Vì+õ@+ºE±hÕ€¿¬-Z°*x¬`'m"*Ì®Ï|ˆ“ ÔWÔO]é5q@Èé5#çM›góq²2†ø4Õ!Ejší² &‰T/c#9«q™ŠK9Kx%bºTdNQê}È3VC×P%ÝmÉ ]RÕ  ÕnTz:Æ¥YØPvâB1låÍø&8[)át¥|ÐjRM?HKù&,•¥º“Š…§Lé‘f¦Àaêb1NG4LÓ”ù´x+q&Óú¹"2EƒÎT™BSÊL•d4­¦Ò´™RÓkš;ƒ‘O2†>‰ûHÁe;1Y?“ŸaI¦Ólú£;=™}Jl:NVúɦ<½§õtžêS|½rÒs¬ -Ä(â¦õ§JadáÄ¥•–ÎÒ=³þæ-U¨u¢íA‰*Ôx©Ud¥NÖA8h¹,æŒVìsêM}(5`~ÂIÍ „‚ÈWÈ9Sýô¤™22Änúà eM½?ÜÈ‚VAç\ ÞŒ§ù”ŸîÓ JTÇæL³§Eu¨"Õ¥ªT›*´¥{œ£~WF© hsg‹s&2ž´’&EZžËóÉ„ö3VÑR~™ ilš´Æy‚ÖªMªB5®ÖÓ£êTáª]eªr¯BU¼zWë*_í§µÇ› ÖÀzŠáÌÃN‰E°RÇ8¹êÅãI¼S¬>ÍdØœi1²¬ÕÔBqÓmÊY—éfõ¬uš‚VÁcK?«h=­Ú”DÞ4X³ËzÓI‰ƒÎN«´! igÊvôs!ÝÊCéÕ‘ü³¦; \/%8,®È52¸›Øóägè„…ÐU'Æ)‹*YË|RЇ6Cwûdbâl—8i%¾U%y:ñ("ÜϵsNΖª9A§T¯ô4s¾W°‰^['-ªÄt«¢ÔÄ>kxBŽõ• ØX Qê,½’'PŠÓº$”d+V½­5U¬ö¤-ÖÕ8矲°¹VB$U7l,„ö‚تÙÕ\>¤Š¿G»æ„7 ±ÐXeе¯®* &ÆBâUÔƒj®ð©,hH%eâæ¤H2ëE±÷êÚØnÕ–IR)2Ø×’ ‘vu^m)?JY<”!YéƒR™†þÈE˜¼¸¨—õ¢VÔ QÑ/:ƒ6 âlg¶Ì†À4»’šf×t››ªðÁ+dY—†¦&óYŽsêÎКZQë3í³¥•ÏþÙAËN -6=´›õ˜Ú.™N£Òh “!õ!FÐaÊÀ\ëCšG6lMÚ¯'-¬Ú’éTšY¼«xZûg{Ÿ2Õâ¸E«”4ìLíÕLòIï„l?,V¶Ö`+ý”7=’@ᘄSÀÌUÆÕf#…5¶í@ÎÀç y$&MiÍŽ™*ÝHj5Sór±L]%‰À,©¡MLb³ÖLàH ‹£G5C4+ýË8+&Ïç€ý“=1JVHTÚér-I²jƒ>W¹ÔMGcMõ·––1aZžêÎô,k5¸“3‘iQ%ÚäSÃuš¸q\=7´d'ßp¤c ]ꨵاUÇ•‘ùQJåGãx-Ãa߬qŬ–†/EµJŒL™¡ª8{:ª±c&ð, Ìϸ`±mªcH#YÌ€’áŸa4s¯ŒáB1˜©ºR^{wfÏ êXE–’äôÌxOi‰eŸ?Æu¥Væ‚>‰êëŠ] –¹[4$®Y(»p²f¡z1kýô #’ŠQ$l]?ô‰E/óËBÓø“bˆ ª©$óFÞ\žÀ‰(iOjµï4rÀz»½èbaOÓØøÎ„TÜ ÷d^1v[m'#ò¼hl%5ÇY(m)œå¢\6­InDÌH•cz*h=l$­'*éoõ¬ÃMßI=ÞÆf]­å–)8M¯„èeTZ‰Ç—_—â'³`™2ÚN@* 'à“bTS3Sù´OúêV–õ¾ÓvûîQ(HgœE[›a‘ù&D@JCÖzã‚9 ßñT@¨NÜzÔsU="6SMYí#Hrª ážuÙÅÖQò\io þ.[øl­5뤖4ÇeÅåˆr+°VˆY*ûe©¥¶¡X ãrý I¢àÔßL¥["i¶âºÎ-$ â½UÒN`—xI­;b¸V)ùö09¥ƒÛî‹Zh9æ²fÅÁ*ÚÏì½ð§JA©Àµ„K/vj¥—[}_v O޶qè fabmÁfžâ™6Q® "p?³0¬X’÷ˆ]<l máK{ÃY [1Ò›…0¾ÃíúFážÉ‡°nÃ’ñ¾A,ˆ‰on¤h5¦êæP‹E Pñ0`lˆ+±N›Ã8ÛáM|Û©'Ž•ÐL¥õG?܇ùpŽ‚W™±%bødà 1(ÊTÏ^Bª¤‡·j#=@Ó5þ®3îòˆÙ`„À‘˽´*üÒ ×²ÂCÆØxÈg•Œ36XÏøKEãæ¬è_’ YÖ8é9!ú¤°±]êô¯aã”$Ž)_t³…¯å»µ¦$P(q:vJè8§ºcn¤‘””¿ÓÀkŠqà|¬¿x¦2×8=…^l9©ò ²Ãéw’i¶*).ì¿ Ùˆ©IWù°îûÂÝojÊ©³t‡§N-}ZèfùÔj ¹*ÔI'£ä” ÝÏ-B£.9zħÉ!a Àƒ©ðÝÎõ›²,Ú™shÕŒµ¤ä£ò¦M« ,Ø×£†¡öÀÕ0çB±‰·‰¯KD¾ÌW_åƒÌ•ƒ)Þ­6q Ë%xïF±YÅh9G©@LˆÛr!vËÑÖ›Î@êÖÞ¯RÁnò~θÆ-D,——órvV09Ë96€ P¿#¨oRu8ªGØ„™›VàY¤=Cc‡Õb ³T¯ÅU¥çÎ’×ó¯JJ§ÁŒ$®Z‘J‘±$Ã9A޻Ɍd$'¾…š´ hIÆþ¢¡CtÖØé’;sçí¢!£{JPê®)èòŒ¼†V…^UWëjÝEE¦JSVÉhYÆ lš¡0kxí‡$­¹¬øøï³j¾yø¼™)(ˆƒlR“NÐtËÆ ‰ªßmtµÒê; éF6 G[ZkL[‰¨p/DfîʦãHX·‚ÍØ)ý”vk¥¢ZX:µ#¦uÅÞÒ™› Í·'9"Ô`ÚîŠmK%‘mq»«û”â”fÓVš‚‘HÎI M›6^M‡ÞV€®ÂºØeÄju‘nrvÌ&F]:f¹Rg¹‹Ó­OÆ‘¿~Äž`Pá3µWuÒªüVÙ*[CÊe4³‹Õ(ÄZ»ÕZ—9¯¾4 #U÷…[†WÈñ])¶±Ût}úØß½ÉèWºªWRŠ  i"ž²“Ó”L žþ­1‰*ô—5’¸zÓw$­…xvëÙ‰IðòìØ6ÛÐç"Ú° Çíp·§ÜhɬHKy„,ÃPQˆ ÐW+"`Ëø â½WÚµkCv—³6Ûh;‘$¢­M’´®dS;PŸiì)éØ}ºåîruª—ø¬p*ŒþÛ­ÈRä[ç¶1ôE“gm‹~‡ï§ ’~n×€TÝ¢ÂfÛÎöAN‰@L€]îDÆdU„~Ѐù)ýeœ­¡V z_ŠHR®Õ]§2‘ÞÃ@ÕqŸ/‰ævSÊŸBÀû-ÀT厈!ÞÒCZŽhÔÛº‹7îbk§í?F¿¸ ‰d矞„BŠáAŸøè’òïµêR§Þ2$'Yšè±ñèÞ I>¢¨£„ÃøKOJdß!;5o#–£’_v¸yøQŸ.×]x[Þ㻊:7%E=–FyzVëE¥ ÐÕ2hŒ»×a•57h³[u wÖuà üÛ¶cM¶³´Oãw“z+m¯ü)›±lÁµÛg…WŸf_kOv¨SÁ'(„@Ñ^æ×ú¨ðq½¯W’€ßðÃq ˜[®ªˆ‚ÏŽÔPVáe¡ ×è^ÀÊO1 +k›¤“[zÈIÙí¾„™²Ò„ZÕa©+qZöCl³‹±lLN6…|”“|$ç2á®#VE…@àBJBxp !9î¯Áóâ¢áâ ø‘=ÁH+s+˜E˜ò…¢7þ»®xΛÆÏ!è§P$§6T´›U"þ—ÞÑRFW! E‘œ £ØÅkškøÞrRS–Å#°îL§¼”cRö £h(7}«œ”Ãr•Êg9*—åµ¼–¯"\ÎËMy/å¾<˜ûG%'­Ÿrãè©í*£G”ÔP2ezæŒ×rùLgþ õaÕMß<úàé¿2˜»v—L¶q~´'úLÒX!A#¾³q6 56YÙ"1KrçÒ‰çîWåXÎÏý¼ã“ÊÒR÷}àòiÛ‘ÔÎÌe-]/3M?7GŽÖ‹çB*]¦ëÄ*L$¤Ìp©Xx·U4œ ¹¨L³R‚r.‡D¯ï@·W]89«2Je#q:–0Ýa¾ËÚ+¢JséßÑ ¥ô]›¤:U¤/5%¡F¸ôu{¬ÎMw"QÕŠåS5mõ‰E0§×À›(±)»ê*X¤KQñ)¢”®0p5~õûšÏÃ:Yë­°«Ÿuz:ÖÍ+3ëa’ªkõ-:3Á(V¿š»‘€~@OÍe]¹“ ]õ» Ž?­Ÿ íˆÙ]p´¥Ù,¾"P—Yɾ‰(;G›ê6°ôñض˜Ù ¼ìjv¹ÖGX)ÙKÝl¦V]ÿ  *ãŽ6õP90.¨ ²/ì°ÙáÀÅþ²»¼B¶¦5ëš'»™•ý,2Ç4;°Ú€ S‚öûèΫûM¿î6=»O+-HYj•¤Î ªñ޳ö˜]ߢ`”»Ÿ÷ß~×aàzwïíý½¯÷ÄŽÞã{°ŠÓY¾Ç÷ýÞÅl}ÿïìÀÃwÿÞ§+€'ï±½i) À‘W¬šÐއ Jøœ;áy`…'‚þÂkxF¥EYàŒEð(U?1Eã0v÷¸Ú=Z÷ßE—­?ñ+ůÜEE [¿ñ½Õ¼&ªž6µ¨÷Ê0LÒÔ>©®*’CìͰ¼`¬YSÑ¡*sòæ÷¤ ?DAc'íò:]øªC\+®Æ¼™K34Žy(àþG$xhÞA± 5?ÜTê&ªók¾i`©ç'ë&úµ>ÎË5j翪ŸgP8`bK]tèQjôÑuSaËqµæ#=¶îËûxñ¦»Ë-IÁ‰£%½*«‡ÞT·Ç– ~SYtÛI¤ «L¼©*$»oö¹|÷íð,ÚD[;¡#D7LÖõ»«L?Ȇ=%Xb|l9µ$ÿë¥óa‹‹sz&u]¬ŒzÙ¡Dái&v&ΧŒÝ©uN/ã‹¶/GÝÌk({?×{üï‡h<Éñ5Æ›üeKßQ¼ËOù(ŸJþXKG³Sñ›J˜Ftïóz?÷>ß“ö.Ê͆þ úòèý¥¯ô¾úN éó=£ô™~ÕÛòèZEuX.¥¾öÃX-iq.ì>kçÓDÃnØ×~lè³²¶÷‹§[;ëÜ·•â ÄòhÁ„åê]ñ8*Ð{/Áa"¶ÈhððãKìsàúÑÎ(VÙZŽK•8Ûº­ü!MFúe`+#Ǫ”’æBÊó¯9hF2ÖaéŒðF¦þ<«¨:ØÔ¬íÆ’¹]¦—’æÕögÞ…Š¾ˆœÑ[G ÎîÖ˜¬«P¹qé€T•c{ 8 …1eš¥•sÚ# S«¿eª7ˆù|tÿ(¦“csçB_\nÛͦNH ©½Ÿâü›§»ô¿þÕ¿ŸÿB òþ§«B³ïÕnÍ}·Cl¯Ý¤TÿzÑÿ'ýßþ÷ÓàaÕ–g›,ORcÿ¥!l—~ÑÔ&kØT´t¦O’Å5Ñrn#b}€OYH=#Fˆ2µã…K:N–‹=nѾ·ïÍd0 C$ÎB4`JeŠg ЄõÐ1VáUÓä(½&ôÐJ&ÿ„EcÓùV•H d’©{aQç2Vk’wàÔT`µVÄ\k ãÔ‚„$¯ ,ÇÅqnA ˜(y#¿§Ä4IðŠñ¥%WÈ$Äøp.V×–$tyQù•{ñnØ uà€Mg`Ø€ÍeWÒ•4— ‚X!ØjR~ !ØF`ŒàhHóQ ¨†QmÁ¶4+´P&ÈþÁš ûçG}‚’žLfñÀMiJšw\ÙP E¢Ý¤‚¬ JÕ ®‚‹“ã ΂°`-8}y'ªY9%§ˆç$<Ø9DñP<Ÿ”ÈÔ­¡~É(å|MVèßd¥ ¶Ï 3¸ FƒjÊÜ(m!)Rò¼$[Í`4è Nƒà 4Jƒâ 8èl‘ƒèà7¨YƒI‰<¢íÄ9÷0«@¤ m’æé2E@ e›l1´àôe V%ÿ *è„!A˜I„5•.˜±”3s ‰,s¯ôö Ñ|(û¢-¾—)ÄÛ,;SG˜6y„ËŽF¨Z„!í#B #0™þÅ‹;s\)bôí“;)Eùß²S€`šãÿ€;Ó‰s/Ú8©ÈÈŽuPI¿82!1Ó“Å.zÓß8öL‚c7s8jŽìÜÐh7.ã˜=yŒ¥bx9>FP©¨í\¸é•*µaèâ;f)÷:´/ÆaéePysäâM'Ha‰—¢Ö½Ü{£Tu-.B$^$£+¤™a3a]Åæ.V[cœ¦4EoØö“ŽŠÈÛÆŒ‰”õµ¸\‹¾£xä¹D©‘WT^£ ¨/ŠŽï#&¶9Êì\Ö¥0!ެáfăãÇè7ÂK6Î Ä?Ñÿ»dìÆ­#£y9ÖK;Sw¢?J#õ£PWA2@ ã42>Jäu…Ù'ê\c†Í@Ïa¹ˆ‰Ñ‰Ð™ã8Ë EÒ94Hð" ¹¸@"úÙà<Fͱw‰aˆÒžôõ°kH1â€c¼³UFD$)‘K¤©®Rzcÿx:’ŠS¤y*‚‹&¤)Þ<‘0™Eb‘¥£ÙD2)9V½Eš‘]$6B|}ãêøAnA•cyFR‘Wdð—FuyÐyGŠ‘^d FV‘Ý –(Gî‘dÉDö‘€¤CpHª‘~¤ùE:’ä"ù£9‘Œd"é$¾H@$& Õ¡@ùTW€ègE€óˆ€JD®$!™JJDed+ KÞ’¯d.)KÆ’.¹Kú’¶¤.LÆB³¤0ÙHò’Ç$0ùDQ_bØ‹ô"Å de•Ç”’1¤+‡JvwQcýÈ)ò§bæFÆ€$ßXK&’WdåxE^ŽŽ‘7yNÂF't,9Dêd:)+É“ï¤tÆÍø‘æä(•e]c¼3?V‘ ·¶Mr1êøBÞ‘/  i -§¢6Y”:–ËäOªsF$øFþ“§"F9QF¥¹Ej”R?Rzb#¥G ™‹Š™Êè¥L”RøH0Ò)üdwN&YCHÔ(+1RTdMš[ÒK 8è ß¶‹ÛQiÞÁ‘¦ž~…0j@Ûä!¦ MVg Ku‰Å;ULÙ¥Y•dL7IZ‘e…ϼ’Qz•þ$XÉ!‰•åY™¡\¤Ñ#™;ºSܤZ©:¦•äZ¹µ•qåÉPÖ‘r¥ÿ3Õ•n%€W’“²d^Y@î•€äIW–}%_©Xž OemÐáw¶dÙ{Ñ1È2´¢5 ¢$F9VG¥O¢YªalÎeŽý‘ÉÄ屎åëXû=F=Ùl´¶(w}Ø’tdŒ PÌ4Œ°\ëàÞ”ìLåÌX7J‰{åØç?*ޤ;åU­L’–;¥BÒ– ¤9oEÎ19­ø}p%*Wf!Æ ” bê¤$– m¤Dy‰LéJ<gm‘t€YŒJ˜*¹;âŠí’ãädŽY‰lI`!@ÿœdyØ–­#¹¢E“ÝQ#A”AH•„˜eBñ^ðD#‘KØb8„ÊèR ãj™'‰tâœ('¦AÑ¢ ´©è‚ßÒ:U2V‰«Q•(bºEv}e>ªBU¢xc&¦B)f%´U=Œ*û4}$£ÎŸD˜˜z´!³2ä˜L H;è‚ígMÝAH¡•û$7ÉMÚŒ.SB 35I&i¤d¾IgQ5™T&“ie[›ãô³4a!é¡b”^¾uþ‰-êXKæ’é6P|ߣ…Ã%Y!¥šé(¾I¤à¾g†”¶áðgÒ†¢xgÖ™o¢œÉf¦™ootf²†d¦.BU³ƒC9Znk§ï͉,²ôSB` •35R£t%BB”g#Öy[]ˆÉg^W—¦1™H"“§¦2iI²’d«9'7ö–qTÁ_/Õ3µZl´X:Ú&IIif j²Ô[¤Ü=`ÎeT2Ù‹Èæ±©l"ŽÉfiQZ˜æ„yaZ˜õΘè,‰šÒˆ¦^=f¿ÝØ4)–uu¢µ©N‘‰~æh”Rþ™dâDù@¥›mfFÙOšê¦"×nÆ›åæéf†›Õ•‡ù&ÊšôTèÖ©,ºr=qvç>=EštWWizÓ/s$m€š¦b7PÆ‘°8*a›Uawfž™ñŽÃ©_"•1$ªy*‘ÊaÉ '¢RJ É%ùÝ!I£šô(94 ˜³¤Ä˜3´HØHdSÒwg A‹Sùi IùIüD½‰Úã½±Gx¢E©tzI…… >¦ŽP'Ÿt&8–´iuNN§—¤uR÷äÕ¹uf\'ØÉ%Æ,X'divn–ÛŒ¤Jn[FŒ9ÔI-„÷£I8€@(wÔ ÕWœM~…}šf¢ÊT%Ö;mb™ùw–˜e&ßy-åtdÝéTÑSðÑNwPC7ãdTbLáùÄ­ER"UdÉFn–Ÿ  -Šl$^vÔ¥CQ6Kq6Mâ<ˆâ¥žþœ’”Ã!†î–Uw]‰‘Ô¾8¥ô˜ð׃6š$OŸ*ä8þžÇ#õuEMbÇ rY|ŸÎThÙXywe« x:ŸeóYfšÑ'ô)}RŸyæ i}nŸÓ§ÊÔLž’3Ò#¢ ]ƒ-Dœ“Ñ%ŸË§åRvŸÕ'ûy}>Ÿî'÷‰}ÊŸÚgü 3$íçüiêŸügýéÙàŸïgþé Ëç¯èCö6ÈRãf$B^»Ù$tI”ÑùX^Œ®¢]ÚbI4å,$“ÆW ½FžÒw„…lBècZgy•¾Ø™ ç š-–™c˜A .( ªx¨L1¨ô4ƒ¦~8è Ú&å 5èŸDrž2(ªƒ¡Ah´×ƒIê] ʃ:¡J(š2I¡Eh›t?¡‹j–¼d¡^`õ6u¡«M¯ ¡Ø$*›aòT®f|Ò‚]@@{ÈeȶFÝ ÚlB£Ð·üñHu(¼„¶I æ º‡þ¡~èSÙ‡Ú €(!ꇢ†( :eꡈ(#šˆþI\èꨚE¢jN!†.< '$‰ß ‡:£ÞW%šcQs5ï ‚™#Õ›¨è¼Igº›&PG銮¢¯(ß÷iÉ¢öæi¡Ô›c"o”‹‚ZGãc5÷}K¦($ŠS)w©¹x"Ùœh£ÜùH\¶X—™é z£¨øi–Jo’©×|jŸgæ½É™M§Ÿ9jΙ´¨7ºgŽ£â¨ÊtÖ¢Ù(õyo šÕç¾—TÆ}ŒD_A£Ý‰ \ÁLú¨e^™õR’ÙXî£ÈV@Úò£é@ŠQŒQT§V±¿Jµæé•¡ÐÎ2Ñ!Äa”0–£Ÿ©·~à{)¸ˆ…%ôÕ|Ù$6‘&'r”Pž¤$©AêjB™,)Jú’­¤.©J:}æ—QÔ#õ Í<6'v£Ë|¡&„ßåOŸ’S]p'Ñ+$GÉ-'QÓùKêA¿ df]©fÅã/69EVR(øH6H\H†¦Ði+UG–ÆüAÚ”“Õ–'Ht)!í{1Á%úsaOàÌ8“3^3)£k$—*DXBµ*Z”ä"^6,UU£×v^˜eçšù—Ò‰)´Y˜†›æSp„åmŠé‰¹˜‚kÐÚ´ZÆSÓ(éI#idÔMï—3Ô§=G'hZ ž.§³øfò¡c¦#ªš¾L…èjº` ¢©)kڈʦ(mêšÞ­©mª›¢§©ßI;¡f ‰ÂýÕ¬„wLKñP¾·géžjéX˜0E|âÁõˆ7ÑésZí$AMÜÇ3IP¬]›´†¹ þjD_™--f§rš 1$äé(.I02f53Áp®§/æÑ‰-U¹uIg¼ÉÔ =§ÉŸ¾2ßà&'V"º§*R&•‰q8^¦)[ξ(õMYuGòÞg;%‚Z¨•³Iò™>ßÊ`”ôŸâR“D­¹ƒˆ"yyœà ŠŒü2¤}Á[ ÙlY*f9™Œ¤aÅ‹8ÓBÂ$R¨]#F7&[‚%Þ¨rÐ()\£Èå^\j°Ãÿ`¾Ç ábÀ„É„5ÿ¼ª®j¬ «Î?¸¥>«â Â…TÔ ‰H"\@†È^N—œNW±z»«Ä*²:¬.«ªó´`¸Óî‰Éc Uf­V«Ø*héCR|âØäÓä'IOŸz‚„«äê(4ŒøI}b•Ú±1Ú׺ڤ$R^ »º#V9HDÀIrmI®u t')´å„‚=T£"í +’Š˜C°n1 SÆ-5¨«_¼‰èx9V©Tㆠ¬¼V3°êIÝÄÚõX|Ž*Ã?}¢Ä[¦Íð=I‚)Ušá«<ÀÊfèÄ#M“ô‘Ä`mÄaSã}ðªI"öÄ·­4”šnv®ulãÚdC®'Ü]+#®ŽdÎÔô¬ônnSŒ–—˜R7Ç”—QJÄW»ª´ö]uÎÏ:´ª$qÊÕjµ<¡É£Ô3嬳"G3óüp› Ê:¯)9MHd°"i W´eb1ÔÒYD¥U6 çd°¦­_¼öî,o§‚6.~B”£ÍŠ„ëÑ¡«×i”øŸI+‚káºÒ=)=Ú)…²V¤ñÈ)V5¶I â“¢' ï²6Aiø)DZ0¯Å}öÙqˆ‡ìÁÛ¬¡¢È±‚]¤XÙÏ$‡ >º£X(™ù†o!‡Õ€ƒ«:„F9>ò¥[Vò®Ž«W¼ºe«È"É€ÿÙÈ%~ô‚f«uIòO¢§`&ºíc¬™ž²¦lP÷„x¯ÔÇ÷ Æ’ «Æá>¯v‹´“0ÒÂFiˆ[уë|8„Mvà0iÏÒ‰U¼v·ZÈê–T]:ç¢8<Ãå(²(lêz¾¡ Ó1èÊÚ¬+­g,1eaܵ#dA,+CS|+7È7 ûqf™"8»nwæßWEñ›ÏluuE•>и"Ÿ™ C$¹[¸’$ÀVßG×”.$j·J“ŸæâhªÎæ˜BÍÆqÑÆïm³&6Ûi³"#UW?ÍIÑlͤ¸I³]TµäíÙ1ßì)Ò¼°3ðôò©1A\Yœ§Yµë ùåÑBÁk*æ–b:‹Îž^‡`#H§D?·D‚Â6`Sh˜ÖŒ0i_Mƒ*3 33¢@Á m¬ÃlåÕ=*3môñøÔ´ÎÇM{Ó–9=¦¯ !¤©A &n+Ík¹åE ë ÂÊ"±”Ë X彤ÄiqİŽa\ÎTË‚pKê±:ðÝlƒ$*W[ÆŽµšJ§’•Lhã¦ã*09IÏyÆ6€‹ìl86)2b˜]“Ö¦me›Ú–¶¹QãÎpS„xnT• ’6kœÛŽÄT:“Ø”¹¶à_ëC’HðJ¶âb´ *óÉrvÙ©G!/ŸÛ 2Á-!‘Œ‘&Ú¾nb¬ ¢·9!!lˆ¹©Q ã XÄÚ«(,vzA‹*ie×6iÆÌØe¹0ýˆaëÛ*¶¿mo«Ø=‰íæ¦×·|m_S =°t-)ä˜I¶ ¯*ׯvYÎÜ·Ø-b ¯= ‹w’ʶ±Ü-w uu?dÊ‚s’·ä­¯(‹¥;Ù¢¬ˆë:«Ûâµóí4c ñ8ø-œ¥ß.¨sLçãß^°Ž&Ê ©±)µÔ&£¼ÖCİV©î‡†tÛ uNšwv¾ž¯¤m…Úî!Ä”dRºô±®w6º!/®¥£è͵›Ãÿ}$’íë¼\;n-[ëXåFL[Œ{×.h2®1ãØ>‰8n«ãθ;î‚Ösúm5c㺷ÑíçÚÜ>yá’¾ àÊ/î’«äž­Mî²öä&¬GnÛJºJ5"­‘›µµ/.«5Ø=0,‡ ëœ9EÙhR´B±ìN–Ÿ†CÚ Ws$%*ø ÃÝα ZKé'iW½³ˆX Dn\˺ø2U¸¹X°¡­…ëÈìGvÚh[èŠmŒ.Ôâ”ÑFNÙâ–Æ¢°[!ºGŸRC† Еdº›nîÑéjºÜAï!¹lº×HW"t#„ªëx©º[Ž©Ûê6%‰¬»¬ò$NWUƒß<ŠâWrÖ†&¸.¯›)5—n÷§ÔT2“îçŠ3BKB.«E†9:¶ÌGÒìRµMâŽH»òÍ^£'y# n²×lRÍ_S¯hxÇ^îr#ã® ¾˜»{ ÷Á×4¨$ »«‚4¨=ç5ñ'IŸ+Hl˜Œ„-2Aœ×PF¬=%¬MÀÛ° ¼mšÀ ð¼‘OÂ[©(¼¶bgÖÂ`bÌÜ:üº9J’Ò.²ñØeݶÄL}‹Ýf­×-b‹Ø–]™K5ÄàJGçš“{µ;íUÉ|æ,píH;Pš«hL~€m± oÎÛð"¼:¯ÁËð ¼_›ÏÛóz5? Ñ ´h@m†6 R]N¡“ƒÖi¶£V²Ò]¯õ³|Ò¼Ñ÷åö¸Ï_ºmInëÇjdѱvn¹Ã¶i½ZXb£Ø5k¯Ú빎’õ±Ä¼fëç‡A²[õ^çÕ³õ¼<¯Ì²º]D™ Üú5T‘“S³T°Þ«v™õf4ß§9S†,î2’­·”¯’¬¦#–orR© o¦ã Úùr¾¥mèëocìè«Hv¾^UêËٻ𭷅)ÂMeÜ;Üξýq+ò¶¸oÈ›ûÒ¾Ùíî+ÜÖ¾º¯aûÚHjh$h0†€[Íð…Pº–®÷à {`­>ìºÔ¯Ykýb*V°:¬®º®.‹âˆ¬º4æ–þöe§®³‹°»ú{þš¿ kú{‹à0{Gf[•¹#Z\EÂú:/:  Ûý¹Xx¦ã[…pqúˆÿ%|‡Ï£+ô’útAšé­4³Z·qµ¶ªôˇè“ÖâúS]î[[ìvªaÕ;àNj۹Ϳ»¼ÕžÀTm¬ƒH,0é žåLŸoéë׳§iYGì¾·p“'Aø$„—ÈÖ—7>pŒÚÁ@pœ‡t±:0qjJ1e“Ý4†¸"òl¾aNÜE{»ºRpšÓ3gýž »…s 0Ë×}:Ü܇Á__%6Œ¡!ÏëÉʳCHðË¿†tðlÿ¯…á·"ãÁwðüÊÄÁÿ”)A¡¬h”£)Æ#µ‡?t©³\l[åÎi£+|tM°%rÍIè£[äú´!éVç;ÆO¦ÞÞ[µD*Cpb}y1ÿŸu+%…Zˆ}vŠ„qü™hˆî»–ƒ(`šâ4sÉQÙ(,ôÞ6;ïÁ[¥ù»¦p¥ÒÀ@t×  Cæ­ hìò+É•<%­ Iý½fÉ lèÚÂyÈZž1l¥œÉ»¡€- Zþ­ Ýzô eªQ½¶«a{¨Ép÷Â=ï?( []@¯0üóö½š(\ÁÀÃ`oèê÷Q|®KÀá»Xà¨8Äf€%˦q·\VCqw307 ýAGf, ìÁ½ÂHlB7½­d.¿Âò:¥h—厷"ëGåšÄï´¨CRõ*%8ÒÎvb$ìÀt\¶Ng+ÄV×öÚ¤<½c*÷ˆwКÄ;Œ,R ÜКH±H“¬ž$^+gc‚×bKò{(bʬDãÐ-[§M¢K¤áÂÊgÙ”ÃE[X }D-D[Y,›Å",“U’:LVòë ¯¸W[¦¼‚¸ŸF›ÇJ¥ÎiyO¹|ñ^,ž=ÂMË ’$t—nbÄènyaëƒÎ"CjP•±<öd,1Ä-ž3¡«i°›ƒ°Ù‰a¬Ç\Å­ß¡«ß ÉD¯+ôï³²[þ gÒ›ƒp•8ÎÒ„¤n¬iÛëºmŠkžèÆ ðý+ùÞóGèŽÆÄñ€Öü ÇØpr,ÉŒ³±J·ª¼ım7òHýÛ四à+×.vœß¹IÌvìßzÇfQÛÇäqxì‘ñ@ä÷QÇéSûzÇÐÙEU{¼´ø•ë§_½ð¢R £ÅüñYì'm«ŒÖô³ È|›³ÕÀǃ‡Hb‚m¬þçI½itn &È67,¿Õe4Y Êݽñ¥úWĆâ,7T+!¹dÓ£ûÂ}¯Ð Ki§¯\bµ*•—.¼Îé-¸0rl#»Pà’¿ù¤üÄI‚½Ö´G š–tûðícÅCǰŒ<#ï<mɾ¢ò zyÖ’iD<+Ïe„´?šþóñü?Ðt@?HÑ=‘Ð ´þl@/Ы³õüC@´æ3AÚ3Nãµ§ctT09ÛÓÒ+ ¢Ï­“ ËÙÍ! }BŸkxÎ]Ù­ƒöÂõä5‡Â NP«øq¤fã)Í(ÆS·å”š`4NøÃ~,elÍ!ÊuCçõÞ±C‚œH%AãbÍ*½ˆpA†œ€ä=ä˜Ð5ôàÁ{ #´ÉìâÜ Çä¬D÷š°PÚiëÇF O ñ­ÈÅÑt4ëçF×Ñm´=íÝÑv4=ArƲ…pÆ84'#;Š&<Ù{õuí$y^ï*3tæsnëÏÉpZÒÞ§ÅLIœtet—rIËaV¼P½ŠÎaÚ8¸úfM—?Þü^*Ï6•Œ¥'oP4‰Ö^ç*þìLÖDI Dï,C†ôlU•£.•qEBG9Ä3ü” É*ÆtýÄ@¹Îò3ÉçI ÏOÔ*…ͤ\*MJ×;¯ŠØtªty%6fþdI_F•t2ØOÁ©•^5Èr+h¹G–R»tÐK›iY)-!OŸ—÷:†Š‘ØX‡¤C%SLù@«2âºa:@1%y@ŠyõãÙ'œ‹ô×"Á^ì59OÆtí"=·~µ1š Ãá@%PeZ}ËktBGk^dbE¥àóõ¬,u[ú–bFàŒ“Ÿ^‹žÓ×—táÓºnWjŠbc~‹üÓÊÉ2ÕÂ4ÄÙj¹GîÈdò¹Ïô_w÷-¡‹e™.M½Ó?Ô XpÖ”à0ÏD9ÉyE`>÷$+zùœ/%SÁ|®›3Í­Bú⧨²P&Ï(4ROEÙ)ä!Yš´/<™.š´Ïi÷íÕzµvéB+šUóV;S#õ Õ˜‘Rð"í)UóÒ™–åÒ¡jI´Ñ$ŠçBº÷‰(® í­¨´©$Éšcʈl6óÙC%dÂÃIú g¸kj}òÕ¥lcÕ9Jï\°uC[ß³²umÃÀÓÌ`àñœ…yÈVŒ³_k÷\az_2SÍrÎCÔ%eBé—ɤ Ãç»ZâYšOcL d)Šù^Y ÅnËF#vBàtžiº|¦íáL¶!FÒ\Æš±v¾”ŽdÍŠÄF]ÿÈNOÕ™›–~c‡Õ6NFõc´Yÿ–Š#Ýø,>™1­ˆƒæ“`_3qã§Ü9æYø#šÑvm r6“n±ä“IÒ/5'm‡~žH˜d} e“¨/´ìj­J ‘”bŸ‰lM¶¹ä|rÃa¦×Àz¡3v1Tc¿góHФÔ#Ù5Y€î1[žD#uKt0*$C’Šoš[J¶á×’)ÙŠiHidÓøg¶´;‡˜5IÖxR²uI=¥“mn¡{ÆS…¤£Šf6ž+R½Î’^šÍf¿ÎdöŸôe+ÙM’ÄÞþµT£C\5Z¢óÈ2´‹Hdç¥Ã…=ºЗ‰²É›JÓN=Jgñ³®¢MG=;תî“Jõʘr)™9O©i›Œœ¶ªÔ>–ŒX#&¸iÏÏi«i”s1ªr*D’¶PÍr"1J6g{ÎYeÔ;Ñ^“¿Œï—ðÙ»5$’ö-BydA95†‰*¤¸Ùa²~à㥔†H ֿĉB›¿©éiu¢ÎJJ=m“¢Å3^ŠN ¤Ú6sÍm/ÛKf·}m{Ûû¨¸mnWÔv¶™ZÑö»dQ:Û´uç†5˜GãÓ©ÐÛq¢ã8;Ãv[dì¬7yzºµŽýÿüÚñí}7lç‰Cö/V;Y¯&¶‡%ÛÔfÄ]'>i·…bAz½Þ6÷5I·—ˆ5 ‚2ÇóaMç›;¶db²vt Ë,¦ÒrÛ5àvÅ4á€2÷ >^ÜôãK{ªK&üg­·]hЬ¹4·"P‡ndý\Kož#æŒ÷Y›¶MMÒY˜¢ ¸u¿1íÊ =µÜ8Ô¦³orÜ(wåÔq§›"·´ˆªf`7Õ¤˜¦Ý¼gÊvÓk-·Û=mZÐfœHv6›d³¹l¶‘&Èí+Úc¨AŽmt:gÑDz‰ÞBµ'Ü:Ñ 6cO˧Ò…ªlÑÓÊàÎ¥SS0ê¦j_Ø=[ÊÕ*ŠÚþãsÍ•Ä%ãøiƒÞ£6§`q¹kä¯;»Þ w9§=¾’:µŠ¹S©©ÒDh5ºÙëâĘhEÃèqI1Þ?©¬†G÷<2x!CÁmMÙÙ$}¨ÜÜð¶™H};ÝÖ7Éa†‰×·…ÙtsßÚ·´ù}ÕwœØ}‹ß3_ê(Y÷«n¤¼v£ßØ·ù~Ÿßô7Ž5~ËßïwýÏßó7¸}ç‰ú·Ç-}oAÏ7]5"E·õƒÍg4G{?R(o ø^gͩߞOà8›ŠCàøn‡à ¸ÑìkoÈc ,r2óÈÐ1ø3wäc铞¶„ýi[Œ8øg”ƒ‡Ú687ˆzƒÚ@ø ®ƒáÔ5évô -c xó]pTiêmÚázw,žwÏâfÝMw»ß²x-~‹?›»8ÞíióâÀ¸/ÎbÇßݽõj"8âPüý˜rl¿½­UƒKÎ8á’H㾩TT€_ãü6„AuáÌ¢¦¥ÒC¶W5 ~:–”ki%™ãâ u|…Bé¸DÄŽ×p íáøÜK£ ’Ôý¹{ŽO÷wVÚãüx>.Õµ~2ãwf›F®v~ÓXäâb¯F*Z>Îߣ3VgæøÈ*Ž4@>0šÂùx &2¹'„ ¥äŸ¢xņ§E’Ò•Œ'oä0yiÒDëc“9‡æ•\q¦ä3Y ËFÉ|­rmSj*O TÊà}¶b¤}3g_ê_ÚVhhæ éMÝß—zÁã[ùRnþµ>eYë#Sb©“—sÞ&¹3V\£GŒk¹Ž£ß‹ä­1§J1BŒblGÆå·]^Úåï©]®À¬mt ±å—ÃMx9%T˜s ~9‹“˜c! «›ì%æDª4pz‘ÒœD%͉˜ YŽr%æ˜ÔA‰kÓŠ×[Š€wáªø%o2ª ·}D2W\Ý 4Ð)±x йMÒöªø›6ÏËsKZ>ã©»¹ùüá¯y·ÅH¥þæãôˆ=I àÁ9q~œ³›Éù®Ÿ¢)iLš›çæ¶ùpz* >³ùÑ8‘9ÐñvhÌš3ç9މ…š3) ™n½|ïØ·ý<€«ß›“$]ekâä6¾é é›,ÓÎͤÊÙ@–óë Ýçõy~>a:ÙǶ¸Ÿ§ÛzfmEâM¢"d.>wã{·©È +诸0¡w¶ø³ùXrG|7ÂrãÓd¹z¿#ø=‰KØ»( 9'Ââ%—}Ž&þH*zà§~öù NÃç˜x»¹‘—ß2ß==rßÓJeöý~I•¸žh£ÿŸ5º‰^‹NŸ%z‘®¤«‰¨’ΟóFüùG¾s?6²³žЮë­ñ„Š“æ²ßQ±1$‘`v\˜œ»?´n¥ü)I°ß\v[_2SÉÝ£57©>’¦Ó åa}< ÅÖÕä[=B‰¬x¨˜*ÕŽ<ø"²ÍêþÙ6›eFí°lð·6âj"n‰µg‰Zû3·)J—C’7=y"¨a»ÿ%ò¡²È$@¸©¯~}¶ípå{ ]sù¬†ª‚sf0Þ…q)¨ní‚Ó¼LS7ùB§üeÂÇ΂ˆ«¿×HeðR­>‡HÙïý³¯+¹#åi3–¹³Q]ij¯¿õ¾¸39—`dÎÎ[ö×àäKÉl¦•ŽèÍ{h“>*ä98╽br¦‰re¤`ÌÒÆB[ß³æÁ1L©ŽÅÙ¨z˜=ýŒîé{ Ú]¼/B8¶Q„ž¯â íÐ-‰àyòü¨}¡‹Qe¿N’Š¥Ïdb–ìèØ3¤=|jæÞÍшL.äN‰µ ¸_¥…[úSwã—SÅ~’VvÙV–îAxþƒ£~w¥é݃ßïö{ýοN¥wOzs©yÈ Y‹7¨šßÎ|û'[²œ¼þaÙ&1MêV¦¨vSi³‹-d=7R2I]™]DÉTÄ4P&_ðìÕ|Õ^]/®ú#?i Ä\žõi]†v¸#d'ÌÐøw¥ì8¼LgG[ÔõyQ÷ðõOQÿJ[Ö$94µLå¶všQu…Õ­a®¶$=OPJÅ»S|xÅSñQ|WCäçÜ¿c.Þ÷hu«Â5´Èβ=Ã8ˆjî4R¶S}‘Ÿ„ÌÖ0í¹x@¼QñyüÉç;jIK£“”Aq_c¶JÃ,ö­BÃ×MƒÚqy|Öž6É(ÉWˆ¤v3Ý*Nò•ü{.?+5Lõ<„>«Œs-˜9·ï¹*%™˜òîoiñ¬|ïʯò¯üÆ”ÊÏòužk%ŸÓ”¥N¯NI“žK„¤ñÓÕ7Û„LR[R98·§ð Q'·ÒA¯\4¿In’C|íâP•¼ æ ]80{^5 K7%ó§Ìðò¹]UÕúnÚôþWœ¼-ßⶸX8û¬Ï‹D£<ßeéÙ¢óïóçs3Ðëó}\âÏ«¨$rjÒE“ˆ/ ë‚ ×µÛ: ¨ÿ¥cÃßsÅ[iš=G¯Ñ/ƒÈ|sÈ.ê›T  íÆ’[ºR›eÉc¶>rÏ£sË$jMÚr_ ø4Þô4à ¸åÉdí(oG©½—WÅkVOÐm—{õo³¯Ã[óJ=_Í_ÒK=POPÃÔq‚’[ ùPœÄÇв|²Eñ4˜—ÒWÏ0‚õdýXoÖwÑÜâ§$Ö£õl½}uÖ»õu Ü,M¢N³”ÆDôˆ"9Ù•I__Öïv±ß!¦âù)eõ‡}aØö†}~¢Ø?ö²QÆ"ÙWƒÉ’Qô§ôÖÂۓͽo˜;Éebö }t}-\Õ G÷Ѧ= X§örtkÏÚ³ö±kï àÕ©²ê9AP`ù*C®uÉi (;x Œ”Ã;õQ}S¿Ã3"O½qÏÔ÷ðøå¥«?5÷O‹c?£…°Þƒ¨¿3¬PIæ¯B}·°Ä¸{ò¿âTq6OмEõ±™t£õ×;¸€UÄgX'ÆxÂkªñLpOØ'öø}cÏØ/öü=d¿ßû÷ý}~ÏÙÿ÷>€ßÑMöÏeOßCxVë„—íܦWõ6…@a•’ý,rã}&‡€KžÏž)á0Iv¨ôKʼnvµšTâwðOw1”SØùƒtâ«ø—Š¿â»ä3¾ˆ_uÃø·¹ïâãä2~Œã§—’toâCt a“Çömzêl‘pu%È ‘GƒŸ 1ÆŒ¢Uoá—WôÓ/u‘øöÕâ³ÖÃõ`¾úÖOœmý—oæ“ùa>šæËFÖvY_æW·E¾\ÿ Ùõâ)ò±ñ ûh/Í2•ÒÔ5U×tÐ\'è7fÁ°ëºú¾Qçy»††¼¢¯èúoüV7™ä@×TŸ•1˜f7%³Þó9@Q·ÐHÕ¡Y%55éüTTñwµ«MÛÇõ±|Լŷò°|¬Ïêç@vu­ïÄÿ±Åy7¥ÄG/ ”Ì9/÷Éý<™Ô÷ñR}ßèÝ—…KCÃßœîLüÂk™Ém•˜.8 µŸ*«ò¥§jÚçѱýkÚûy´MêÀkêhÂéó,–#û)ÊÉÓâvúÿ­ð~Á7< øê´¶j`’Ô11Y«‰Î¤œðE{0>ÒË„¥»EJûÁ7Œ@سJa³È_OÖpß¿‘›àknÏîû?_Ð÷óü˜O…ï#ôÝ’Ñ+:_Ä3í$Š“ßé3ûÞ¸Ù­¶ük­–F3rš8ëŒô!Êy›áGƒž1JEÃ>—Õ‚zçÇq+¨©»éÎ=ÖïKxµòïXÓïbEP¹|?X¹÷Y|Oåë9‹=ýy?º|׺›£©ùChV!Ç•‚”ÖÍoæc’YéD-Z-c\+Z/{­l@ò)Aˆ'¥”B¹˜Lž¿ù?^F41,bVê/»3g: ²”Ìð ”/ÞQù)Taµ:‹-¿NCL׳ÔÒj|*¹ah‘•øô«ŸE=É›šDjIb¤Vd¶•k„±’ôV² e;_Ž>YOßEˆÜû“ ißÔe“/¿Óˆaý.âÓ%%Ñæ“idjcZ÷ÀÛ>2öcÎDÚ?C‚ñÖ÷N{{Úìe(ÍâÅeüÿhíÿ`ˆŸŠÏ-dOe˜çÈVS ²û`­A”D«3W Ê\5^LƒeˆŽx xAؼø`8/•·MVD8ˆ¼`SÌÅä0§´®B„r‘qk ë~&¤ˆ¤ÿf˜Á­È{‰®ä™+Ý S078¥ jõ>è¾2F)+£ÑtjÒHfºÌ·‚I˜±¯ÁÒz¯øà+2¨yÁ¼¬©‚Ä,m$Äæ³„ö€}¥(rÁ¥Èju0Ê$˜<„Â`q˜AXì3‚Á îDr#ñ¡‹›áͶR qŒ‹7è—®|¬~n8o†ˆPã¾A~°ÁØÚ®«Éxƒ§y”UÉÚfË`fÅAŽYUd^~DªÇIðöCÉØj ƒ6+.‡S¢·…ÈJܱ4dÕ0iÄîJô5®j¾ nÚDO1Ì8 “R0,“Á––0F¨¾º^õ±,2«ºáRˆ4È„¼\;è8Ø£Mà!¡ÑÈCÜ"Ü„•㇜¤¡Ñ¸Lðí1½‘ŸÏZÃEh%S“!!‰%¡ì"bÇØB$pƒs;ª„*¦Í‚|C ÂlÃÑD]{µü9“³†#Â'7 $©„‚Ñ{K°„5s # PQ˜òàá) …é ÃáAšÛAÊ0?Bˆ”ò#O¡n7rš\!e÷´+œöl¼3¨Ï‹KeöŽJͰ0e§I Ä ls¬e¼'€\¡ãe;ت¢UukJÕ ® ›“Ÿ!N}k=„*ðƒžP%à— îÄï0Ö-œù‰¡½wŠ M£5tóñ*N³›’€ŒÃñÐ~¬&ŽUÉ+z½ Fx1[ä_‚ò‰ÍDHax uk^"!ÀžüzE‰(VHè„‘Œ¡Ç&ôêT&³9DÈð%Ä‚­gò1AÌÄK>3‡¨Ç´ )1.C)ŒÇ3•ŠÑ´cfEò ‘;±3$¾°'Ri± ÕÍ O½ÙRm*d+Ö…)šV Žñ ™ÅPe¡åËvJ+c>‘z­œ† ZLHׄ![-i ¡† '̸ȆñÂä…Ȇã"³!&jˆ›ñCÖ$)®ì ƒGþ"‘±LôkòO ñEV‚{•¸NèÅJ–ªÒÇl”ýPRàcf/û$ ÌAJqxjnÁø(b°?Páðeh Q˜&^†¥óÔÆ}“•Àrœ!ž£5A 3¤ô‚™n- ½†Ý©uà¥Ã3!JaŽŽ$€BœW挪c…Gü1d©fÞívˆ;\j(fr‡.²¯ÔC§á:L²{7bCâË nxÎ2u„x¸Ì»0 Ø4Ñ»!¾À'n0Ñ(^ ?¦“|‹ "KÂÝUUD¶5ÆpI ßCHEøƒÅ¦°V\bÚ‡A9…oÐ áLúÈ)Ô†: ÆÐ3I]ƒäI¥xžC ‘‘HÔÊzh=ä^b ˆÛCõ!&&#«X–¥3𤆠øpHAœ Zb¦4ÒëoƒèœÙÌû숇Ìn©nxV/XJhBÝF˜£¦¶qR؈¼=•C‚¡ÊÐÜñx0‡0 È!qr¤|ñ¦”×t&s™`™¦ ÓjÚP2Xˆ.O m1y .¾!×Ò¡Äîà"+¾´ [WÄ,âôðix´Ò"v·ˆV™UËÑ6r5t÷©_ΈfÄ4bñQr>ü"º¹ˆpÄ0bcˆDBEtZtd'r-ˆÓذõ'6ì#òÿˆkC@âahH,$ ‰í½HݺøÐúÅ8q)0BŒÖ.’HI¼h=-‰˜ÄI"!#™^ò¨!œ›¬„†~H³ÙJG0(l pRqŠÜ†Z‡Äž¡Þ¨_s‹è*rp¡5a±qô’]é$vWð¤ÚŽ&ï@ùS@"ƒ{²„ˆœâ5³Zâ95 6¨5¢Ñè8A=}¡ŽasCèaÔßEâ‚ 2Bo"Èì›(Nl#‚ɉ=Ãtâ›gÂ2¼óÜ"‡‡ÃÑc¢7Ùj„xLDa žRñ­cnÙAp/fq‰â2Ç!PŒK4c05ë hÌz¢1D¹@HcŠEÌÆÉ{s”°J¥>&ŠÛ Çz‚$¡Q¬@pŸ ¬Þì%_aP´Ì”ý56/õD礈ž()Ê0@ŠK¹YÑH‚…8S”)¢kÜœ›ÉŠ4EM‘gáIô²‰,?ùÉD/1&ÅÀþ ?ŒŠËšõDm/¡Á¸@4m‰õD5d£ÈÆ)Â'¬Š³—ñBV‘SqUÔJt³°"ñb‘3Vì*Æ 6ÅGB­˜Ð0(*…Ø%E•ÄÝÐLÑ:ŽPEÙDÌžOG‘ÓÅ0»Ìb^Tª1~Ä×ð ’!ÄtR°pÅgÆXì'6EAŽÅÈ"dñIS"oÜê^a1hØú¬ÍŠž†IµMGÅd™yf”2¿6­Ô2ñéM”#f4ØGSìŒl1¶H[”&"`Â\“,äµ(ƒÈATÎøy‹Ä•IpÑ=¨AT")XBˆýÃ_[ ˆøçÂòý³†¬ÕMa­Z-F]7ÌDe¢-Qñ&>ü˜‘@²JZ,íbqµè©Å(WKÏ >†³iš`õĘÏ41ì¼`¼tH$ŽfãÅ›YUP="… ÎŒƒ°…!•É*IÁ²Gç8þVp¬'dÆ´ÍXiyŠ£ž‚VxQŒ},e, !‹ýGÞ1ï8YÍm$^3¢/”‚A!ŠàN\^LŒ¿‹œ"âA7Óž¸ÍÌfp3ßÁ•ŒÑøFcüÄä8@17ÆðŽñ?3c´1òkŒ;F ‡"*"àï@åš{| ÝŸæzø¼ÁÐΚŒPF䇓‘xH@¤2Za‰VF bfʈeì2r¿ŒQÆ÷Í:QŠ‘¸pxã„)œïLU$ð@ȤTPR‰™¦WIçj’U’ {0‚þ›Ç©ÐÃ:lOœ9pEð ¹åóDl~‡2Ï]¢ ¦ðeüð‚H[è„q®†ÈϤýÐf$äðá.®DŠ¦Ñ‡‡‚Yxl©úF=ψèÐb:á"Nn®Œ@ “ñÙ"Kd5_:!¯ò-£c2ûÊ+›¬ŠâHÐ"—H,ê¹r –!é>C'd?ã8Z‰#T¢óÆÁ.0ÿCYœ7NG‚Ñ!Ç™6z*ªÊ¯k#LMzÈþ!¥å¿†Ë1‡g1Oع±q°'G·“ D&•‚‚îyM[ ,Ǭ±ýsOÚaÌaè„):aGBÚèüHiÈqrˆÇåLÛ-åƒT"1t@eŠ•á H†8̘r}ôFìŽX"#¨oøÖ¹­°Òcëš8£öȈ²R‰"ʈ›‡¼Â Ò¼Ù€B*ˆÁ…Ibp±Ë1~|4z"ÃÓ£ìá1DÎgÚ2-ô\îgsÔ9z´Ô0‹4EĶ“®ø„@~ŽŽ¤B¤£Ò1éÈt\::›Ž§#Òšsº!Œý)¼…y³F(ÄÁuäDx»Ž\Çá×qìv$;šuTG&%ìꨌÈÏÈ5§¨`¹°{A˪‹4vBœDÁ¦ì ±{H”‡2™5Öªg5€äGhÓKèÂ.`óЖ­¡o4ý-]«"ôB,c\Ír…¡ ’yDóÆ‘6’3`H 2K ë+áÕBÕ˜ O5— ]OÊïb*EPÅJ”GVˆíîBhyÌ›ÑÇjò É…±óØyôxù [y­ ¤’•&„dlU‡!FC;àçkÕ}Œ¸SîJ5"IP Ix±]ÀK.,_vM[(…’Y„ö<~W“dÿQ )€CB5r€Bˆ7Ä¥8”QžDø°iRå‘éi«AÚif©´$â33½Q~ G>.£:KÅK‘{GTÈׯ˅°ì…ç,Ò;¨»f­Š’ r·0×P"§F°Ò…"PòLÙX"ìo”S ÌÆóÁ¿VœÂ^T”;V™*Rca…|m¬"g¯HW$Òfiõ3ÚÄ-Ž6³µh@B%èc” MbI„ìA!»-d$}‹ìB„¬o!ç^"%äAÇÖUç Ý„nZÀÍAFIØFÌlci¯p¤_‘ÉLÑe Í|J `d>hrƒ¹‘•y§¤ÇóLgð<è¡ZPî5ŽšëÄêñöZJtµ"/î«J%LüsµÑ/â&^,*ˆø«Kˆ]ˆc¡u…Iéãõ{EºÉºä5´’‹ýËòQS†|ìHr$%-ÓîÃ;«cÔ¢¡L$zR4‹øÃªN™‰¤DR§ÆUÑHNè§¾‹0Õ¼¢ŠQÅÔ¡üÄ '„€Ò¤&R®“$ ¢+AœÚD ×€¡ÞÃq¡ìA[°r(.j‹$Kò¼ñ¨¨Jö!‘8¸‰’„ªÐÀyoá‘¡Ž__2yŒ,K’%5Ìš³¤°Œ^ÒŠ1qAÚ ‘,¡¹Mì ·‘ÜâWeÌSxI"¡^rs³yÅ ½7£ öĨQ¸ -)X…™‚Œ×Á9ãcU:Ú Œ”„ï¢F8× L2in„  @¡™Ô/n$²’' +FùµÄAtp°8ŒÎÎRÔ BŠ"ª"ã‰&…´ YBP E/’€¹/½‘ ãÊQ‡\ Ñ*1õš¹X3Æ<æ(%vbG§'Ç3¤JüìÊD8Ã.Õ†B‘—$\ì%ag%¿¤vr›!˜ßx*Rl…I&!€¦IL’ã˜'+i *Icí’ÃZ¶ÌŸ„Çb”åø:6޻ܸè(Á¾`_„%$“8ˆcÅkì@¤£a Á9Úü^`ÿ ݽZu­Ô‘ƒ’¤F³{¨=(?ná3ÈÚ€DQE½CÍ¡C€GmâU½„áFÀË,Fb+¤!Užn€%#,‘ÿJ©»pŽ–dUòzÂaÝFj¨RYë¯Ô±òÌ ‰bï ¥r©€W@J+=‹KÃ&YÖvéD¹¤½uîØJHJD^’HyÀcÜÙLú+¤˜Hé´æ°ç›{LÐ)§Ié>ÚRހ̔d¡eÝH”Â?:,’)ƒˆoÊ–L·¿Ö7r™ôGȇò4ú] Yƒû66)‹L?»tVI*Iéב-áó:OÓ¼-©/Åe @ œ|8´‘;©Q¹ªe˜tm!§<è-H¢oóÈ8ŽÐRß0€‘·ŽÅ4 «AeúkÚ»ßÒènU™Îz´í—B”‡£ÚJ&äi4ySÕÀXt§ÆŒ”*Ïç$JUV‘G¥_%Åëc×qÒ‘Í¢fHŠåßiê8·úb<GX%5!’®²C–,§Pëª þŒÚ¯»CbÅ-N¦•?(;É#m¸òbš•I.]oª,“gh椉òåÉ©–&S¦†Ó ¢F‘8—î•¥ ©Ä¯Ìóïî¡¢„èhNy‡Užè¼i€ ßç tM ¹qÈ(‘*ˆ¶eñø2T «2€Ûásp,༧ÀZ`_0ȨV  ‚·l à0PÈ/_àИŒ 2*Û ²„Ì,ÿ..C4PR #üJ$#€À”RFK¤FLÀ?p1Ì ,@±b· h ÎOˈ…@ €¨ ä)3 àP7` ¤Ð(êp'˜ ÄRj€  !€ Ø€†`A@ÇPø+x^n€À@HPH·åâ¡5°,Ø œRgÀ` ð0pHú–?Å%L0¸¬¸úŠK@c Hи\\þà–‘Kµe“áºü ä ¦˜K¯ X<„Þ–_ËÔeàOз¤¿”|9Á¥ °d` ˜?µ%v   ä¿ÚF€%ƒ ‡ AŒ-QWþA `iÙ¸LÖ(ÔR-°dP¸Ö.ñAK`|ɸ\_ž/Q@ûå’áO@»\ZÚ.¥X0ÀÀPX@-ïèKÀú²zÉ$€B„9aágYø¤,˜ˆ¢¥M .>$-½–iê%L —½Ì[>  ¦¥w©wHaF.3—'Ä%ùr2@¿Œ P/W¬ìå’!Ð!‘-ƒÝËœÙR ¨.9À `¼<´-Ÿ–™K‹@Ú’ié´ì[ Ú«€`йÅÌ\v1µ˜ÀË-¦Úò‹IÆÌ]n1á–bL0¦ÓŒÉÆDcr1Ù˜kL4Àâ!YÆ\cÆ1Á˜cL8&óÿ‘ `_¢x˜ßÂÞ¡$€½ôZjx˜€»ï%زoY [Ž ÚpÞ%äòO¸\\Ú0a—f€¹¥n  b>-Õ–âÊÀ uI»|-Œ-ÕyÌÇeŒéÆÌcÚ1Õ˜¬L<&,s•yÆ”eÒ21—sÌ0æó•YÆleÎ2õ˜µL:&S‘ ¸?2û–’_!óé¤w)L!ÀÙÀ'P¼LaÚ ¢–˾eh‹™Ç,Ø2Û˜ßÌ5¦€—©Ëteþ2ï˜ÂLr&:s—yÎŒe¦3s™äL_æ-siμeÊ3™àL1&<³ÌdgÞ2‰™XL¯¥33Yd .™™3€g¦pl©˜ ²™[ˆ¦{иôfò ²™pËòÁ' k@)ô0û˜F€<¦3žÎcŽ3™÷Lu¦;ÓŸ‰ÏLiò3Ë™jÌ}f/³¤iϤiv/·™]KÀ@SRðE(—Ú€B3ši°Ø™)ÌÍ@¾€"@^F.½™ˆËÔ%¿ ÐÈDe‚1ó–eÌz&ó¤ÙÏÔj’4Ó™/M—fM¬ÙÅ”iÂ4ç™+M¯&JÓ¦IΜ4Q M‚¦ëApÉ̬ 5É–fKˆfi€l©Ñœb0—e€<3¹d 453—rËÌ%A’Y/hjJ¸™/MµæL“¬ÙÒdk®5õ™/Mzff3­¹Ùìjv6%—`L HÓk™Ð þ–tMíBH‘ , [.2[˜dËAàIP¾Dü5U—ÑKÀ…@3À`bš2!›ÂÌ<¦d3ŸÉÒüj7/›iK³¦qs¸©ÙDkö3§L#iS„iøð@è0uš=LÙ 0Ê\ZÒ.19|ÍQ&Ür À/°´vPLOºcF„È–cÍã¦gÓ¹yÖliæ2™›œÍø&~s‹x(ff/QvM‚fvAIPÈÔiîštK6Ár@2àÛÜk¢›„Í2ç’  £/¥˜Ë¦åÓ’ÛÜœ[N6å›ÄÍýf}S¥yƼo†5-›N§XÓ¾‰âfÂÞšvMÓ¦i€¿pÐd2Ÿ™­M@Ðcð Tà}ËÙRS°à ¤´›VÍçgsŹÜüer5Gœ'NÊf““¾Éä4k‚7sš6€î%X!ï\Ú8›™8Îfà*¾e’2‘šdKT‚°xhÀ 0ŒœáçH3¿‰ÏlnÖ9éœ$NЦ”Ïå|cª!F›(€€–“0@px9‰ .€„¦/BÌy(ô¶ hN€šs=ÀæTp¾9™˜UÍ&³“Iߌcš8©œ-N;gž“ÉÓäsÞ2c€NA§ŒSQãDt 5?Ì«À“¡yIÑ\o¦9ÇkN¸e›³ÈÉÄ 'h:·˜ÚMSgesÏÙËütÞ9ç›ÇN(§~3³™ËÌZ¾5qƒN˜À&¢Õ©Ú sÆ:÷i€Y§ê²Ö±HaN:—™Ë]ç¥S›ÝLeö9Uœ¡Na§§3݉ìuÚ4š9Í2“Û¢ö :™ÐL²e€dNœ.ÌL¦7SÜù¹ìdj ¾½Mª¦3ÉéLvŠ:ÏKN›æ“óá¹ìu;‰›1è¦!0ï„ èìNEg#SÇùÐ <É–NÕ儳Âyáef8«˜c€ûƒ¹SÉiñqR<‡)ºóâyóœr&;å˜ìÎîe¦sãÙñ„ Z¯Î‘ç¾³ßÙc0rŠ-É–OMÝ&† ›‰¾`r ˜˜K)¦Úò¶Ø$R—FÎ Á¯30@nz5Íš¤NšçÏ3è鯤 h<ÿ˜;MÂÁõÐê´kæ;QÜÍ3'l“q9ÊT[z4;™}Mµåyót)¨P8‡3ÉùÆÔj¦=CœOžg.óñÙó4{F>‹›hÏÐæ‹3§ùˆˆv>"Žž‡ÎÕ¦µók©?ˆt>Ó…ÏÃç ñÙÉŒj..ëGÎrçg³ò©ötwJ93Ÿe PAètj̓vBû fMTçúSÞyÙ,BÎG¨#ówiÉ<°r—cI¦Ûè $phB:3˜ P¶§0Tò‰…~Bû çLÜg(”èŒ =¹ O5hÒ3…Ùý^Ž ÜÈOuCâÉ9öÄCSš¤Ðah(´ZÎ܃zCM¡ƒÐøfïsZôŒ½B힎ÐÒçÞS>°!h LœœÌçz Æxl2>½™[̆§t zù4˜C¿¡5Pq¨A´ Jƒ2Y¡’gD4Ô@üŒ‡†-š(ý ’iðÌ,5 ¾Î<&'”*e€š?ÑŸ Q”(•ÓØ‰ U‰‚B#oO5„s?¸n 5‰ N#(xsÛé°59;™à'f4tÉÞcDž0Prh•!JÙº€4— @ŠŽ'F¢4PàÌ 21¢m„gÓšIÑœ  ~—jË ¨¼à/€ }¸œŸ½NÆçH”ò9ùTˆ¦DA¡gO䦳3§%h©¢(€ì@#4…ùÐh¢-÷žïžèW4q ·‹E;–(€G&¼€ €õT‹¦0Ñ¡ Ð’h©³ í„Fü›͸çÐá±Ì̈JµžCË¡íÑÊ(I”¿éÈê4½‚ æa š´| -‘ Ôƒ-3§Ù7Ž&>÷ž1©ŽÓq©Ûdl"1FÐÌ¥s|ÞÔzª7wR.²%ó·@ÂT ä-™HÐéÞ“ˆiÄ´;° `¤LLµåŒtÊ÷^v@9«äC3'ÊÄÌ\Ê  MP(÷n¹#˜bJ1­¤ßÏÅ%G€IºÉ4ž ~ ™ËÍ@êrF0ÊT6S ©Ñ&©Úr¢9U]>:-—,¼¥nÓ:0·Œ /»¤jË›B$3ÂÙÔÌhæ ê¤~Ò4)“¨ðøs .}ϧásVÁ¹¤aZ2Ù?†Næá³ð@}â.£˜£Loæ5tMª&}}ÖHõŸ‹‡×¥“ûÙu¨“ æ'àåŸÀ^ÀÄ„[~@礟´%Üòš‰ð¼\*6×Ò†Z) €1`{~à.€œ''£È`“8hv@E¥›ÌÌå`Su ¼D)45ç¤úO;i¢TZ,lÒn¡™Ë7¨‘ÓV:õ]z.ËyÒÌ¥ø |»¤X8—h€Ü¥¸x9-Ý,?3—@Ï$³L`/È]J1½™›L '¯£¹'U}6’¥¡‘@MTÇ™¸œ~V1Õ¥)Ð3'Ü27 ¼œ[ÎxœØOÏð2úX<Ð6;pЂ©Rku™'õf>Á“LL©S“x Ê”6äCë¥sKŽ@‘`…ù´Ì[VÈžLËJæâÁ Jè–ª. £ŒËV €¾\dúPMÁB¤“1Pc|9Ÿ¥O€)Öa”Ù»LŒþ8—˜Ì)¦¸TXj#M}ŽLås€<éô“2ÕœKý¥‘Ò*¨ TÒ9@˜Æ)$!×Í'+µ)y>2¡ “L&ù2I ¹ÌdÚJ—øÒ*fËÔÌéÝìa¦N.†g qÙÉì€N­ ôϲ¨O4_ ,="?}¦éM™©§ôiÙÉ4\Æ’¥ €NæòrÉp‰ò=#™ Ò)æ´T¿`Þ¼pêФLË’¥3?SU  /=ƒÉ@¿ói {{1G£(gÃÓnÉWX›†2/—¸Ò¦`wêÔÌd&O—óÒñæSAgʸT™ª-ë¥S^i¿4MÚ0e\–>!¦fNúg²t'šÈd>=™–ZSMÈ4oÀÄ$‚d Ó˜B´^Jô•ÎûÒ4Yàù¹.—âJ»¤@Oµé™3y 4=8"¥ËÓ×@¬bŠu —26s—=àb Ø$ŒO1¢¯Mg5½Ù%uŸ¦c¦ôPÉc PÚ"u]Î-O*€* Mà:ÝhÒIq™+TÆ©÷ôiéÍttb3—ŸL¯)âméÍä´H#œúRú' ¼•Z2qGM¿§­ú)&U\.ú¥ãÍþçj00> ’ÆJ{÷K?€ýÒk+õ š'¦7Ó½çýó‡zÄÜ (?/—¡Ó¾éÜrŒ*.Ý æC»¤ÞÌâ©gÁÿùüLl¢~ ÐåÀÓñÀ9–¦&‚‹À °x@˜z<¾QôeqTÕp5M\šL™ÝËިѓÀ™Óbf.…§®Ó›©7€ª»”.ÛS(»TZºØä.5¢‘Ì]) Ç€D%˜ö5¦âQé¡tn9…\> šš[2êðô ÊØ”¨ú¥›ÔL¦µ?Ðåähb€ôÒ¢æï2sÉÃT—’@O¥ªSÞå5Šè¥îO§˜ýÓê³£‰Lµ’b?K¥ŒËÄ'—p:Cb’7å´'jýÒ›JØì:`3ÃUÔ©0U’Ú†p–&.™9ÍÏXjæò'@N…™²SŸ¨¾T\C(µ'H• 8AÍ¥Ó5jéniý\6e©4Ì(æ÷4#zmbR© .Sµ¥•q‰DbR?=¨C—b*c 2°Ž9ó–'ÐÀ§mSÚõd“r=}¨s€!ª—t–JM]bÜNÒwiFôa€9ý“Ò’¥ŠÔÆ%°ƒlÙ%Í\ÞC?@ªšT±Læ–bN•ëÈ“zP¹M¬À¨ŠØX1¿—C€ Et’¥,ˆ¦z l)ÄÔ\ÎAã¤ÕÎÇå 4z¹4”îRªØÏ‡êBÔŽšòllvò¤pË¿Y4s9›Æ-/ Prê{€•º<åDRƒTËÁeä’ :K•¨ÞLŸ[Z•0@7 [¾8c¨ŒTǪ´’ª¶ä¤BJsž~Ϥ*ðRn©¶Œ ²R…—ÙÌNæf ´ 䘮¢Ÿ—Ë«ª‘cp‰P5‹æC¯œêÕ3]š3%¡Ê-ã¨fÑ]jcà?[3Õôæ95jÉü±n!œ¢ƒËy©[3†šfÍ] P#§ˆÍ„*(³ÂªS—ÚUs—EV;kêòVÊKm§bLǬ¸ÔNê•ÐJýÌhR3—L|é‰za-­Ö6/«åTbà`0U5¸œÄKÛ¬K:*ð²Hà¶4:OY¬?Ó5i–tÉ@\ °f.åãƒl¦`ñ <å›2h¨ÃR)“œj#4`R©åT0«úÔȉ/u¯æO¯©šVéÄ23›Ê=…µ.|¬Ì;+ÛÔàXWm¨½Rœiá“øL¶’j§<ÐÅiß’³;¥L1]«T×¥¬µœêÍ|¡ª-_˜ÁV@ôtñP>Ф®P…¥kVKiõÔ Š=½—jKÝÏO5éó|j_½ŒOYY˜ƒf ¢ÉÑd¢ÞQ묠R8€®áÂjjæ.% SÕÜ%¼U‡ºú›‚6ÏøSøªþàŠM øYQ­ÒÖ;qu©Ja}´fD‹¨wK€éc™x8hö ¦lÖúåõtRºCý“òMsLÒ|+5šjBEŒöBߪËO.© Ó¨JcÍ’ª-{«Ðç©ùrÉJe¯*x EÖƒ+àB±qм˜Mõ¤ÑRõ&ÁÕxš»,ª¢ £j¾Tã*ðŒ·Þ?<5@y3¿Š(•¡ªT1§ž'¸ÔZP“vP®[ g)3ØÐ/Ízº<½§œÔ»)ö“’¹&=²ê8¯o€<)ã†4šÞl¤7á­*Uý‰¡ˆj”æMi¬|S«52€ ±öK¯§êTØi_Ó}ŠAùs.S®ÛTÝ@4‡Z\͇ªTg«¸†F*ðÝÊDÝ™‚=I¨‹ƒsÂíª ˜ÂQã­–W¶kuWz']~jZ1(0ˆ+ϵãúFš6M™˜ÞLòjŸ•)`õ$™_+›WË*ÐÔap¸€Nɧ÷T§æ5ñéͬ¥^£ÚT£jóµÀÊqM|jT7™ÏWÍA3, 2…[úSÏ®€´kÙ•œº}•ªòCK«žË‰ÝUº ¸ØHXW››Ôg€Ûжd½b)|£^Kq«­t"PVݨò Ψ×ýg”† a]¦Ö^ñ¥Ö&5oùB}\Ö_å€U«)ÖŠZN|F`_°œÌŃu­úcU@ 5—êX*yÔÀi×ôfnæŸV×&)þ™ 5ýd¦Jo°ÓׯÀ_5*Xŵ>"\2ÕÞ(’Uý e•j‚@­"×k*Ä”] ô\½öFûýÍÁe öžìü0¨Wi¤YÖ*æôt©oE™ 0œYV­ç⸺KM©.T©OUjç5ØÀ/M´ú8—Á†¯À¸Ô{z3Íp>UŸ¯{‡ÄiÊôÇ`3U¯¦¼–¸ƒÍxÉ ~\9šPXœk²4…dM«&A}¡ýÒ.럀oJ0x~ŽQ=°uX¾)æu¡úD¿ö`‹’X,O*¼™Xm—vEåËÓ½«é2WÀy=‹’MŸ®ˆUĨ¾ê_MºÖ^[«;‚ת õÏúnµ, V®~ÓœiÅ”ÕÚ'•¡R?Ý8gØ «$¡ ˆ—Ž]I™ÉÒe)gŒ®¹È\ÂÚ_­¦äT”§ _š)ÝÃò è¡÷Ósk46Ýúp­¸~bq§„Ýi v‘š{u¬^O!©øR²)ÐKøŒÂ6W™hÖê¥î éy ÄbǧìQlÙ3+Z5pjšÆ®êÅ;ÈêN_SØÀêa4ÐI\µ£2M3±ÒÕ )J€‚)(2¸q¬L©⃉(‘òCQ¤*R ¦ ÖEjFE’æ.—¤ÐT‡éÓG:òtfòHÁ­;L0çÜ Í,X8w±ÿÖl¦:–SàÔvêZ›¨"ÖÕe6óën¥³6a§˜Sg,vlJBÍ K¥Ÿ‰Quªÿ3ºŠ6búIÇ›a×ý_TÌJ-ݧ® ×R[*ÊêzÃD–,3ǨxÕvêCÕжD½Nc¡ŸÙL‰jz“›:4Íx–b?«B×5iî²"˺„Ä`«›T[CcÀ±Ú9ý¦ÒX «jÒ2li4œZë,­ KòÓ~érÁQZB}¸6Nq¡·V”©õ€y¿ôlQå­)®êÂgJxebæP›­Kñ*`“†)*•¢`W—‰Õ€k­tñý Ðcó¡žVÍl†³Núe=*_%³òÒaëË”±I]Àµö5OšÙÐ kÂTJ—…—r_SÃi‘á‹(ŽÞ4]˜‹ÄgêÔ›É+Õ“^4¥ŸôÖÕlb¶°¹ˆÁŽQ)³SÌŠlŒUœŠ@³‚gÕ–s€<Çô‡ê»¼…J1­ºK,`ÓÖ:-H´ö5ýiا÷³^¸ÌpæaW³Z §Ù5C –µ“N1ѬS©f¥5xú0ГòaG öPiÿTMz–5ÚbžkÙrkààšÂ< º˜ŸŒX”é‡$@ŸUК^³N mêr°Y¡Å…JQ9ÄÖaiá’±ÉÛ¼\ªbu´|Öþ'v²0·œÅV^G´4Ì\ªŸt“jœ…\jhU—r€di'ÓëJÃ|\nKÍ®©Ym,öÑØÄ /B´/Ô ,E5ëšþ9)¯8Ó´ìŠ5H›Œe±>a²8×7*ÃU|Àe͈:\{ªíÖ‰ê!ÁóJ¨5|.³¦WZë>T?k;­ÏþfÓ±9XD×ÕäJ4­ÁZa¬OÚlüµ{C]Ô:d=ªXâjr¶i™dBT«Ÿ`Ïë§bVûÉ@½…æRÍç©FÕ9Û}õ¸Æ©CVá%§¶©Ùn”ÂLÇ©gK’+ÐÓÞÚUjŽfã¤NÚÆ«€´ëà,À6k“›+T×À5“, 2|†Jã­S¤€òUêCÍÖ9C‰Ÿæ«ö c͇òSs—×Z8m.9°ˆ‚î)kuà‹°õÄ^}I³ð[mß3@‹iåÃ:59µ4‚Ú.<ª»KÝÔ^¼ïÚ¨@ V«ŠV}lji§‡[œ)b•IÌ\6 `«þV©nû™%ÓV\×·:Øak<•lyˆdª[E£˜Ù€©êò·Û\ý¿þЩ€Y+ŸÔ1Ûõ˜âVm¯QSµÀ’õà+ÙÍiÖa³¤ LÃÇA“0›õ¤ÅâNë³¾Ûˆ-ÖUß û„]Bi[¾ûÔvïº5p{Þ”"dpu½ñÞ$¯ãõµI×åÿMÓºÛ*6[KƒåÖ–>YëoX·~™µ-õÊP·\UY¨Æv ¼ìÚ{5½j]˜éô³NÚ²Õ¢ZmZ/ëDõÍ+٥Ϊk{ìÚƒLÖg¹!Z> „ pgˆ´ƒ¹“%‘q²#Ïi«V(«K}‘*1³¬HÙº¬R6çiy&4Ÿ²ÎÒ¤À‰4Ç™ßeŸÓ´ WÆ€a5Ó‹å².º¸¹²í)UÖ{µ½çÚpE¶Ý_®µUKWe‘Y_ºÝÞ&ï/·ª;v¬zGA¨§Þú¥â·R‹¬E¦Rya¨D`ëë»6`›xë\ó¤à[†ë¶¬ë¬&tT§Ÿ–Ø6ܵgðÉí£Ê-í´¾Û8if@¡kÝåþJd¦=`ømf—1€ª]E@3—²Ü%-÷’{S¸¥òe7šyÛAk 6Iû«÷Fv§©Rþ§{öÿU”N1å§ ZÆ&y3ØIeÁ^‰¸ÂRã¯Sø‹f|²m}¯ïÖ½ìrÁ 9¸Ä8I¯ã`8°t$›1×6´åÕ4+bwñ çăW¦¸ÖLp>T€yÈÇJMÕºâà2<ØIZÑœÞVLM 'Û ékÀªÌ¯+E;>H÷îR´¡Ô&’רiHeÊ2ý˜AÍÀlI7Hòú6GžJM÷Oà;Û…]ZN5—¥Èªh%U ,ºEŸ:Zq¶…Ý´­ùó– ;½û*U•´TS7-„vá‹¿è¾$œÖ>,ð·‘êÁe«-)»/ÖÆ€ªÃÕ/TKï¿àY&:ppYd•®Â-ƒ¸“WÄk–5v»šµ]îRAºSLôp±÷‹2Mö^má¶íV§ë¨·ËjR øX¥¥á[BîÓ÷»Ke¹Ž\®æXmìôº·u¼lö¯§Ö5l–u4ìå Ö|3¬IÞÜ¥,ì-…š„Ѽ¤Õ.ìëxùÿÍmŽ†Í®À_xAÖÓË{¥ ºhžJ_`¬W ^ʽ…³ºjMºM¦€aÕ-K0½ÃÖwɹ¨Öjê˜5ø»¾ÐÖI­½}VñÙ ÆÐüå‹/ËžÞ©­1zåUä VÃMk.÷–ÓJgC~Ë®yØHiêZÅô¿ò} ¶YöªÏÖ,ºb‚ì—UÏ«€ž´ "þÍžä´nÕ§åFö Úür&4åª"â”ìt( ·¼äI¸Fb¹¥Wjnh 4VQ—€Í^ð¶E«íÌ–z4m¥(â«b‹Û®e÷6o«¶Í nŠ˜™ CÅÑZ_'ªÖÜXo–•~ 4EåªwI®ÇYêãR‚+íÕe˜R*½“Ù—®Ç÷éKM½íZP§jT¥+Fö{9œÅÊrR±Á™Ë?z)½Jc®ˆÜ»)ô·òº*U£š? ÅpËrð Õ jýâ~~9ª_¿'°µ¬ú9àgcy ßi1C³^éäÈ93—Žâ)æ` ËÈ8…'ŃU–¬Š¸Qû’µ°.p˜‘Î3@v8;˜½›–NÑ›>×–§×XrдìöTÏâ]])3wFKŽmªîˆ ÖÒ߯5õêéQM3-YÁ›X¸e']+"Þ4ƒ¼ùØPe®MTL,Ìø<3¾ …£¬ XV®±ä§‰vØ5§²…`ãmzÓ€¹´ lI ´ÆU+îƒoÚØ4œ&B¥hŠÓöiT@\/}d*Wç°UÛeð‡ùY)¥ñÞLOšŠÚ|(ewX¼·­©Îx5³T[â)§–KÄMxâ?#™ŽYßë«•«{¹ü-Yóº1ܰ¥ƒó#oÐf?ÁÞK²¥Æ úcØ{’WǨRb-Ë8Mêï¬&ÔaS±[ý©\øi¬Njª-…¶J]±L5Ö[Ðeê†h-Ç‹YÕ%ó¶XЉ ¨S«ªùPæ¯|6HqÐ «ȪsK!€‘ÛÉ|œZyÄKé wpi<«–U_5Àh˜$ëQUÈfD¬ÔnT;x8`O&.“:±åÆ&dI¨â °ŸÔ5{J]+ps÷»ZÝ‘®—];Øë>-=¼Ìœ!ki´TkI•Øk)¶­Væ°Õuûr¥Æ*lËÇçc)@ú˜$¼Rl:Aÿµvb¹­Ú²ì´õáçË̾èæõÝÚÎm ‡eµ-ZC®²W¥¹5Ób.KµM‡-Ó Ê>> /¯HØ©.ÞUòúYÅ“|w¯aÓî¢UC;MEo=ȪÑzéw7:‹¸ ß/cÈT æ$'E_Ò}¿°Ë½ìB´}LE·^ˆ³ÄjKÞqì”t ·$ÌB5˜ýÏ”-‚¸áÚgí €‚?¸½TUßtŒj 5Ôfl«Å[*™ ðd( ð@ÍÂÈÚlxô"`kH—’ŸM(À` ±ÂA)@`ð°• 9sš’]€€bk, WѵÖ])ûw^oµÈÖ|¹³X 0)¹;ûøý\f.¥™Ë] {,ª¹Ì $qeÆF‚Î/}Ù°5<F£9MWk©V 8 ž ,a¯¥ v 0 îdÎ’¸I]Wìöh[r%âO¡±ýÎ%è¨Õˆû@-¶¢Vƒ§}ZÆæB—–üdp]rj§˜BÍêå‚®`U[–“ï¨çd¸¥]óˆlA¦Ò‚˽ìQY( Y†üB®![áÄïaÉp‘à¼y#6”mk¬çÙ«+ú‚Œ>VüɸMŠíø7QÜ/fÃ-U›N#¬ÑÔõ¹nf›(\Kèùz:õìmJŠ«°SÌÂêÂJÛh¥Ñ^X}À e-­ +ì-)R½”ë¥æ’n+„zîn'ª¡c2ËØJ J–èÖsÅÈ™ØVp>tf¬¬•C?­»ÏÏB±J7w‰-^Ùi8(Ë"­—zc¤(€0pêt Ì”Ma 5GÌÒ ëê‰YÃìì0/ ÌŸÕ5¹ö.€U2ï—ã)f²e‡9:„Å2w}ß¾=æ¯r‚ùx|¹Ì17®½*ÓÌñ”ÒiyÚ˜‹¥9æþ*Gà˜:®E|™#Í$L óñ8^ºa^1¯¬ŸUQ3X`ªc~Ïþd‘¦šã%s+!ѬcÖ˜jš‡ÓS”iLÈ9b&4OšÇªj^óì“:„]œ>? ¤µÝðoÓÐŒaÖðš7—¶Ð[è|9™‹82g.ó ÖbssWÕ—\XœóŸ¹/<øÍ5ï—»¼f?ó‡ù{éhÖ2ÇKGÌ·s{™‰™c–;3ÐugV*Þ¹­*x†0ç‡mÌ^Õ³ÞùÃÌ_從{Ìã…có΀×Lx O©¿f³ÌÖ⋯…DˆžaŸ–fLóa+€Þ™ó çý²È¹{™ª"[îžÍ_gZ3ø²Àï—¡ÏòÚ!lúæû´Œ¾’-¯Ï…æì³ðyþœŽñ>·—­ÍgïçæŒhõ¦7ÌpË*@$JúZÀ ``ÀHÚTÁ;UÉû«¯æ…´Ôa¨jc8µlÔ­ß’7í°ÔÝ-q40Úð•¢% þÖÕÞp„uËÄ[‚›—$nŽ—M~Ú kM´ ¶}]Õ/9sÌ^o‹™ën1Ë=ûtM%49• ­Ff~VÑÎãç*t¸Tp{c%¢’ èC—,´¼×™éƒÞ,(>Gž.áÑ,ØŒN… ä.‹ÐòÒIñRS¦z†6GÖ\—ZèÜeB³ `5hê;»¢dSGr°ù]…îC묭€hyï º íX…Bëv/¬CX<ôš• xÐ×¢ «ÀË.ôwà ˆC—x}¨/h™ª7AÈ|²Ú,ϦëÞµ+#7yŠLe¨Ž”O°ËâÐ-½Ô¦<-·ZL)†RbÁüòì®ÜXÆãÝR0€ôÍ{uDd¡IÃGé_ûVž¨*MßÇ7cðð÷ÃàöU×Ò^1ÈݪiOÀµ Q­×fOÃWÚAÏv¢ªí$/£@GËë#hH‚ q˜} £ÂeO‚çFsË/+[”CžsK´²x4Ë á|¢®<¿No0‹T®L\E)3SïÊ+e_,ÓóßIMm»vg_}Ögô"3Ý´¸\æ™l¸,Ph!”™eæ)šù ¬fNaÊT¤9dœé—¼™W8o¾w; sÏ+&€s&Ú#5ä-ñAÒ¼gáTŒºn¦I›71Æcàe)j@¸Pàä |Q¬Vo¦;ØVJ&Ç`§ðÛA¯[÷‚\Þ4‹î”Êù[4€0î«–,“[½®aÔ ©Â×x*,ýöª.çÈ'`Ë!mv³,Îr¢/ë­ WÊ.C´Œg¥°ªoM¸nN|¨ ¶{Ü‚>-§Nñ¥ƒW'èÕ²|+Xä2ƒ­ÁÕ@Ãéxì˜94·N€ YJ͇N„ÈßÕ¥¾@©;bxóDu­ŠM4@èùHbÊWc§r_Y*'5Æúý|“Ö©RÜW.àÙCܼnÚ8ußU"ç¸+»Ø,’¤iNÚ-øiÉæ€[½–Êãòl€X´KXvöÂi×ÃcSÓ´QÚ+Mf­hÇÒäÝe4>4MZÛ4»j‹Ÿ«Üb(1Lìú<¶â:)å‰T³Øà6Íó}Z²lA»žÌ °<ô³Za5!3Ä´&T÷q »[ °â-G½eÏô,Ê4o잟J:Q³éûm÷T‰l<Õ?^o¡XÙo'öÕ)öì–š}áŒmË—3<š.x>cÙ½ ×oòU—Ü„¾°z޳±ÝY 5t¼6G˨á–ÄR–ê±TØ;je+Ó¯³Üqó+8?ݪ¥Ó>U À]NêyöþZ‹vÕ^L{©ØÝµ&—éŠÝ5à\Ù¹·V«þHÀ€5G_—‹Ì×±x6jc ?.a¯²Õ,ë÷DJŸüŽb/їц©€zÀÆøƒ¤0M²ÔÁgEà"Pæ<|7Ûª>ÔÒs sI`²®Ø2Õà#ǸÀ‰XÅ3œÈVä$Cúb‹`ÐÖ †êªãØ{Yà̦OóéSxܺ"âB$/Kµú‚M¬€€P”ÊtÇFÚ³»XùJyqÖXõS8¸,ž–2U¡:Ϋv5^ˆÆ |/}¨Ãê:€šm1tFøG§vKAqŽWˆnVçü£¨T+&‡³'Ë'°zxÁ Èå‹h s-}ïuÆÖ‡gÔÍ6²ÁSlùs«Ò¸_¾Â¡Ú°ÚNöE+6%Ì,_o.×BK«Í¶žcW hÕô²y"z¿l4v GΠ阳 `³,'«ƒ˜ÇjÍ%«Øt/©Ž˜Á¸’Ø6€ãyD¼\X7¬›žëױĺtŒ¸4|QžnxÄA³ ‡Ö˜Â-=Öëµ¼udÝô,Y[¬ÓË•õîè ³vXgWµ¦4ë©€Íúd³Ö)·@Ñ„5£“a³þY«É–;؉õÐ:Ò|ÈXC`#JëkçÇz*ð°æÂF­IÖÙÕ›uVÈÊÑìSË:ÖW­u@fýµ®Y‡­‰ÖüQ°r€n@mö¬AÖ?k‘µÚzj}±†áE5Ö}…¬u°šií³Ž@¬¡ÖAkеÉ:Ò xø[ó˜¹Kkµu×P¸æ[O‚údë6@ nи„\k­›Ö†k¯uåúmi.V0¥9šL€7€ÄXp}·æZ;­)×{kÒõÅ:ȺÌ4XG`ÖÞ´5èö)º–\“®Àëe(¶¢™dN¹¢WùÀÈÝî,¹šþI0 U×§5™žSqB5,]!¶5”¨¯¬»S®j«WeZöT©*¨ «°…•+Ì íUK¨“¥K`š¬ÖÒ4°0Y_çd©ÀÄ+ð! ì’†I“]»×ÙÒ5Æ8pÊVý=|/- Î<ó›[ˆ¤.­ÍÖ´ËêײR}©fdªÕ'ë ëĪXÄ.¬±­Z*åÒp{ü4C[ # Ó8uÀ À<åB|/™}ÚµB÷Òbhl躰ä7t …Ð6³°ÇÍ…âÌe«úU½‰ ~Z‘%+ë]ÃÃzU½°NV«)×Fl «Lõ;jqÖ× æÎh€‡u沈]ýDϬ“ØIÞ%6ÝSåŒßõÝJ±Tlbµ¼Y]ÅVbQ¿£@gò¸XŠ=¸Æb«Šu°Jf1vûŒM÷Ô:wŒCClöh[Y¾]»±ÃZlnKÛye½#ä±—Öìñ(»Œ=ÇÖ Ó=ÏúÚíÁ!ûÚ™È.5“±åØFÍ,,vaI@¤' ¢Í&ìÏuášw »Þ]²M®ç×k ôÀÆÞc¢á؉ìS¶ñY ;¥ÈZÙÂjF¶ªøŠ­ËdÓ±¹-ÝB7o_a’ÝÆîe+²S˜—l>v#û;:V‰dçN‰Ù®ì>ö"“íËvdË=óúZÕ.4;—MÍ>f#®cÙ¿ligý™iyH]¯®W½”lc¶%;Ž­ÌÎd{°ñŸÏ¬*Àø `ÖVç®ËøŠ&=Û€)ºÞ`³.;ØÖl§àAž}Íq.¬óÙÒçB³uaÈvFgÇ3kÈçÒ¡MÑtÒmÛäKßWA›³`K&åV±™ãÝ]ÎI…¦\¬3Q™s he²’]3—HåRj8¸ýz–Õ–üÛÆ5sëĤ»¦z-þÑEfÕÓã Ž3×^3‚C>Z¶ÜGõ¡¶þÉÕX¸_3X lsRSÆÞdT0ÐS¹<˜¥zWj«Ý1·¶d•S‹÷Í“º`ç¿þ`ðï;Úš\¯þ$„X˼žÓ$îžC<Ž.·‰C·ôP`ñ”×Ê[m®J1¹É×ÓvÞ8Æu¤eã\C¯@Ów©UÙÖì}Ýo4­¥DÚò¨PÕÁiZ…¼fƒÛ©÷ÓÍ©íõ]kü}].pá°ð,iÕG]áu§dW¦2¼Iš·„™2ˆ[à˜ã$óY Kš]‚ó_s›d¤òЕKzjEˆ¯²¤ÕÛÒ÷ŵ„|œŽk·i‡ÔTø1JüòæžÎNiúZ”BÁ[x¬å~-ü¡ Ȥx`ÀŠ™±uf6ÆáàQÒlÁ`…o19Ê)LÁY²€”ÆÜ7hÏîº! ]èŒ7A¿˜¥ñÇó‹Ûܽ?,¼µ ÎL‡÷ÂÚ%>”Öð¾§® o=n]âÀ®^­ÞŒ§½ÚÝø`\ä]ú®ù•©ªëÿ§lÖ9.ÕŠ°¡L7+|Ì‰ìµ â’}9©6oÈåè;/˜6£kµ¨e¯¬\2{+Vž2OOÛeUØ+FµºÇS:¡Äfب‘ø¯P>p£.µÊ»Ôè©à¶Ý3F“¢y›½Z3«¬–ªÎ[× ·œuZyÕ†TŒ„ü6 Õ7:jç·“9^gb&º!ë<ùvyõ·^°aåPZw<½ 'y«V´ëj¡XMðÖä|;_Ù£Ÿoòx€BKÛmÓ¾R?©©ïjn„ø^c w…;ÁObµ€ÿUÃZ0Fíò@)ÔTø-ëµ¶ì,õ‡ï=µ©ò²œ\NØž¹’ ,†Lr¾©ÎÛ4º<¥™ÁïágËn1kMP¶]²KOš_d1-L÷¼Z¯ßšÅí·HÝÚk´u–ú|-E ps¥ÀK~,E—K®1¦tjƒ¤ W˜ø÷² ÞG- |Ï›-€1Áçh $àú’\½™êÚ&¼5¼JgvóBUÓ\—yFû ;Y˜Fx±¬j^œé„¼T‹fõYò@c¥æ`ÓôÃüg<~‚Þ7šðVÛ¯57ºû§³V†ó³æp91°”#Š>•& ÚãÑ3ìï AbuÒ¯MrëfÛ‹jš¿£…ÎñÏ­dÚôš÷³r‡Ïæ Íqy’·\.¼Íi²ŠI·¬Wl.¸UoÎ07šSrw£Åëªã€&-eæh³^QÞ1ï}(ÂöóAvÓÞ¼3«Ž^'¹®øf|ü™†záãbák®×‡\G}¯ n ÒÙR¼tæ]AÆmB–Áž%_æ¾tͺn¸:j¹Us xtåúÂ.Èþ‹“ÄPÚFm„·”ò.Tç ýRp,ðp;ÊÜ _¤;ªQLwô·3®;4wgZuÒåÛ\4?1|Û}˜³mï¨!îjr…µ={U“>_ÌØïß%˜x9Î#oÔæ•ÓsÒ0@¼Øiž/>`ö½9¤AS¦"ƒIøŽ_¯¤ç×-i²åKºU“f|ïSßûkõ¦ä›l íD°·|sø SOŽ¤Ý—kiï¾OS@¯¥”Þ*íÞ.£`1«#Xðä`MÊŠM¨RV¹áFäöì÷Ø'€úMA{Ì7¦šÝlïûfZ&Ÿ?‡“²¸ÝFùñw žó,ïR5§Óíi VdÚs­¸æzéÂëÝ^yÁu[hÎî…Í®3ð[ðAóBÌýVMSËuæÙ˜9qhÎ{†÷-3¶eU7ê>5Áû=«-‡æ÷Ë-æY… îÑzÁópïqôÚÿÝû—=uÀð`8ªU+N®H¯ŽŸ¨M×ܦͷ;Kæ­“ŠZU²S ñqVƒ /¾tƒ’áÒ}T7ªÿ{ܹ¼Í"6Éè†U ¯ø IñEé¢~ݨŠtÜnj5”z\û²K;§ËÎ,µ£Mú”'5ùÂRyéÓ}úo>hjѱ¸V-ÓRŠ@ëÞÏ[±å3e.ÓUÕŠ& ?ƒéåËœfÂÜ´-Ø®C§<— säHé—Õw9%Ø øXËÈdtCªÀò Z}@^Óëßá9Mú½îË×ÊMpä§‘“¨Kv}\®ÌW¬×côt¸xj ¾ çlç²tÁpT[øk6€Ò²P£»ÍóÞè3bÿº—õ ßO)ÅYiW¸k.LgM£ªÎÛ­BS¼y)–ÜJ2¿¸¦Àëæ}Ù83¨8Õºëm#F¡â=ð¬©ûÔº°0ÕCÓG±m øe·wìï²¶]!Ò¹ÔÀ-1¼+AmŸh7šÜúô’WFÛ.-m¿\1«uÒ29üž~ÔtŸ²!l®ûؽm5wìšî]Uª‚Ö,ü¶“Ùš*{[ÔPy(¹uŸþ;ï§‹¼/·qbjRû{¹DŠkZY S¼ë¾{ï R—ôÒÅ-®up:Ÿ´Ë:;_t©Oj(k ‚ åRÐÛâtÓêSý¼Km™s_á´Öz¹8Ðz)ï,ïÅ›à®åuë2ýå Õ /ÌMžýïÞh2k™IOW3-¸Úù‘x(¼]%é&…»šTjúA¸Ë[NaÃ9±Žp €\“ë>% ü­»Žî'öZÄzr} £|Ỹފ*»kŒÍu+ÑÉ®ãòH-ñô¯,^í¡Šgó–ªÝ¤¸ê: ^$–ÄqÛëëÅ1cs`ڵÂÖ² õ\¯Ý®ºaE™Z…Eé»ôªGUI;Q îr½‡·$1œ™ùJïxsj™íSI*q¿[Û<¯‹ ÖYb?°ï²®nþÅå~Ïa§štŒñÎjJ%¬S[©« pô% díèZKRƒè‰w½”î.ÓfM¼8ݰì¸SÛgEÜún‰«Fqåm‡5ô°$.dW…ã9q"zÇ•¸*g½°g@k¯ÞÌ躖§>,?·vοÕeƒ'Š÷Ñ=F}­ÏpÉè±XoïÞö…^ÌMG{׋°å5ÒI2ϯÿVŒÎÒ§ªY5-Å¢O1cæA`'u–ÎyœÎ¼Õ¨Ù×Éve{šw¬Wµ}«¹^Ó¯ ·Ð:`¿yWç©WöîªdUÍÚn\–=7Û¶R t>–^["Ëˆí¿ r7A›޾\Š5™ÞcF; €`(æªNȶŽö5z¤s6ý¤ ‡?ʽ½˜s¢r²5û,ö±#Ó7¦–uˆ¹1¸r^y¥œ‰5 $W|)ÃUuô¬îÆs½EÖV«RWÒNi×´ï?kéÛÝ7dUKýôf:[×­˜TíEø •"x÷Âêï½À¾ìý›>+kØ Ò q„ô[y”WvZž”ê5êÜRyÎÊ•sû¨ââWsƼ^Î6G¤(Û}vygÙmúñ\t¬#°k ú[ó¯>ò´ Û}u4«Øïÿ—t«PN›LWÐ=bêRÝ0ŽÞEƒ\³ÃñU†:³uÔËýŒÀ>½ÇpS{|X]-f{–Û¯Ö*ú›8—jXþS!Ý~to&}/Œމ_ƒ™§ãM2:¥5‹¸´§ÑíÔŽoKWI~Ò­WSµëÀ%pÜîQ8yîMFïòѨzÒÈ¥FH÷t#r é‹Ö3ï¤8‘tד…é€ÍîéôLžqïk¢/Ùà®XkíìöTn܆\úE7é®íô戡M€½®YíLuÕêVª«yÍyVSéfÝUz³ÙÍÊ”yJÚ3í9ÍX)V–õí‹ý+øD‹ÀhvTëku<#ÆFg.yíöØò ׆™µmÄ'BeÇtÔ|÷Ú'ˆµ:_%©§¼.Ò—ÎÚT^u‡$p]ÎRíH6zk’•¤KRIöv]y—´,Žý}‡ÚùäÌèì/\µúó^½×wqÔcõ® ÙSNÈWéÊ‹­"s¾î]ѶJ{° [z Ó›Û¬±>ÌGª§ßÀ,ø›zÝO¶~ÊñÙEò§%6ªóNPS”3—æîÜå—Ó™i„UŽKÊÅ«îix´°}è{y–¥§°Òå„ñ KDE_ºãÊþðxšvÛÝf‘&Ø™°aòa«u>ž>{‹5æ%[À§:UÈK›«“º»t5äwèú¸Ô³Œ]ê«ãã::vÜêEgŽšÒ3ÄLí&µ°ÜM-¯mˆAìTÓOª!­{e½F,@žžä>êçx¢:/MSk2ýáÀw ªR½+ZW©~²ãþW¦@ªÜ}:Àö½ßO ²^õçë` õîWŸ€ïDÃãlwõo`½K.w}ßcGºøîà;.×]ÂmßöSÁë†÷êy°“¾œE ¶íêÊ[­qÙýÀÞ.E§6j;ËÐÕA®WXLkíâTC²xàë,{y&flZ¿îÑaÂq|– eF¸@ž[¤jð–?JãlÂ៫ Y lÝ:pnÊÌ—ƒ¾-çâq̹´œÍ(Ï£/{ðmÚ„»âXËúÌmwïPSåLp+«\¨é*Çg§8ß˧.ðtV¾A¦…ÛÊs–(r:Æ›WÎñžbË:)¶_qrxs¼a^,—Ž75Ó×#錀ÜS @èLôÏy²‡ïHç}Y@èê¯oÒ‘ïŸâ÷RÞé@/Õš ̼9y€N~U'çuÏñk€tüî”™ŒI¨“#\ƒ¬h°%_7Ø òfü>o â 䈪¸ügÚ þ/kwyLLÃy™ÕΆPûK †ÚÏj5…yŽ?È[AéêrÖ„~¦Ôç%>Å&Xòü;6ýÚtÛ¨3r¯.µ–⮽†:¸oíÌàì+Ö\?íYu­g˭쫈 ÷É÷,kT皦ŽÚPr©V3Xrš±íW@">H-¤Š0kélÝ)Ítéìø±Zœóñð?ðÄxô­Œ.‹…ÛM×6A–G»—MÂOUò¤ä0ë`ÚÌ$­—J§©×‚t?8!^çÜåbóV«ÞϘ×Ó‡]-è5{f¯X> ¿—ðÖˆ9ÛÃ~³š>Ô4@”ž ;3¦ã:í}·)sçìÇU<Ù&Æ3x‡À\ú+S›ÄûöÙ#FSì¿Züèþöû#oÕNä•ô§ö0ò—¾¥¿õfŽNá®§y)=Ý”->òÌ©ªý²,÷p}œxz­‡RiÉVý,»Þªšìäuë–víNf @¦ú¸T«W‰óÚX}Û~æ}ÀQËAÝ ûp%‡ ¦/‚UîÙRuý”¶ ¶®.VŸŸåã])±OÖÂ=Δ3;‚.÷†có3~íº©MþÔ.3ßWˆ¥·(,~d¿Ì"3ùUx¶¸ƒó@ÿ§ÔWæGÈS3ç8Õ ?X_¶Ãݙ˅K½p>¹n:š_ÒkrÝÉ[ˆ¼©>¿¥ß¥¦ßÞ‚N#lL<›K5çcV·¯Ô`¨MU`ÂB燢?Ò½eHš ìeÆŸG„^…ýmæ5^~m"E|ׯ è÷ko<ÏV |/_ ï~ýëÃL!˜ôÙùÁáÓP7&Üv{sÂf^²¨ý论¼¤ÜQ­˜_¿/ ùµŸßçdú›®¤[rnHÛzªEo/´óÍ}ü>OÀ ‰]+Ô ¿—d~=îó¦ÀÙ_}ë5%š³TÉ»W^pÌÓGNë^´újÀ›“3îÐܳ*©rÔ†_X–”.ù›üSaü»v"ÔVN»péšRho„wVN5 \KïšRfX—м׆¾4=ûßüî1x²í­¸z3OËÊéÔtÎó†K0¿ã†„ Æõò ¾×R°vïçQ‰~zy¾ áëqžn÷BG­âí[¨!ºA{äl«2FUØjK|p`=<„­qÓ.=×Ì~è&Ù¼;ð)ØŒ_ÇCTÿÀŠè.òD³æ˜‡zEéx;Ç™îMÙn˜Ñ¬Û–&šÛÀr5Xù‘3ÙRÒn3Ö´LÈþÞëe÷j›Ñl l¿³´lTÙ=:—f~gO¦ú†ù»¨V›;ú²hxß'ê;à»RŸ¼˜XeÎY®ˆŸê=»ÔüOòújtWª f•¯¹^w7Ÿ¥^ü5¯V„£j_>(ö¼Y ôZ=EâªQq8½£®t-¹u?ë÷õåî#Ú³k;§’f½ ®Q㈪þ±ß*G:ïñGþdã¾8jùIZª†ÖJÀq­Du±-V±I?(WCNË®~çðéTÛšG NEð}麯(sj\Õ³jˆÁØkR³iK¹ c_þÆ©­‰Sÿ=Tü¾¯^%£¾¹ùh^^4¿Ûh¬ «g.éþûfó<¾4“{vôl­‰éœç Ù€]нØ"ã¥êáKù;O:²º¯î³‹ÀÞzé•]{ø.ÏP—§SÌ̮ӭZ' ¦˜(lÎÀXt—jŸ}úZÂ%z‘üâáÐH “YÕÀKܾxUm9ðˆ†sí»±…ÁåæXªécÍDÇ£c°Þ¹;Èx*ìæ”œšné°Åo ñiÚêÉ·µjwg=ð¿ó½2ê3›éPÿë¾Ö­øe/ç¿Ám¹ü §0ûÁÿWŽ@ѹd[vFÞùÑŽîô{'£ÌÃTwÿaïf}¹Mì&eodúo)eüw\U8iŸU§QáLdÉåTë^8nžKóX‰X:[hv£^¥r—uRªÀhçh ZáUcRµ_¼t€ P±T QÄO\m†^´y¾^ÙaYZ¼nèql^œSPÚXs|þ|}^âzÎeíÆq´WMmÔs[x~aK[Ò]OWkzlm=v¥e_x[.cIe…~åàiNc€mLdàjµW ~³b unb1_NM=€¥O­O®xWe-w)Lb›tÒ\rb”N'M»K0^¶TÍUâc:€ OMXÝS”]*wec i[Wwëiér)a9~°{éMÒ]vYo«X½`€ž]`KNP'_À,yuc*X)[Œ€ØnìYºuàÉzÒf?a{g-—€øa”€=&ËLðxŸ€¡€ €UhŒ€KÕ_jnŒfXg¤€×tM›j±€£€B@QtMîmGZ¬€ )tM)váf¤€%fjl¯f’€ÄK¤€?fÿm>K÷sN`B@;)OÖxdffþs†o,i&}tŠo‘St§sGi,} K.}:R o»€$|å|fNÌ€ Sás”€ÿo+nÊ€÷eIãž]Ú\g”~öPçRLL”€WyRoEgzp¢L´K”€vyço@~jš€ ilÖ_HU kW”€vl]×PsdUügB@ƒlƒKEn®e·P¬€¡gw„bµl‰O”€þQUnL%uk(l ÛVAm¬€cn^>dUh|ö~”€ h7sš€âlÅTin²€¸K¬€\C8P<2zƒKrnEô€Ç‹pVkù}P ,mn^£A1môazø†K^Q\=mqK-·kGÆy]ò€¡€\Uy]ÔŸ€˜T<×ïxft“€õ€ —Q| ™`b|rù€ðg¢]s)sfƒV{<Ç .lÙZƒ-g|di|\L’XkMÍz\|’Xø€¹}X: ’X¾b¼-ä¿K<8™Ò¨v«Ò€ó’Xš°ª‰KÀ€ÄMyºk·@NêXƒTxÝqg{(OËvõq&P[£fm¦} dS€ürªV{ ~®SÚeà} x{y j«|ˆQ¾Vhyct*~‹Waw8ez¶€žK°€ oPÝd`{ržXá_ßwùPv\ŸXru]ôjÈ[„m·€Ÿzfd½[‘âR]måTKˆÁŠ^|Ž`¯nVØOZ|wi{6f!L[rªSçmZk€®Z‚Ûg¿qpfâcý;fXgLH`K^pyz©KðòYÛ{üK ìi8vw`8X™]újs–nYwVqòXpb±S¥pp Q`rn'«o³M÷_ˆ\ô´]Ó_ØniUÎ]ŸxéMÑy%d‰VÆnpraLE€hIXÂs·Z¤cž~‰e­bóc]æTù\dêXlF«ZÙe|R¾y}p:‚CWZ„x9•ö~¼P„x¶VÞcXná`ôqw†{Ej¬ZÆ{À\rh‚šYæO`r»QPy5^Op‚v‰Vs‚7cHtLq)W™p¢TbcTL}‚m[5w/X±R=‰]¦[q‚MM'M‰‚áb+`Û[R_8lY8e=MxQajXDu‘YpW{|~‰\ò{Ge±uKc?tªc w¬mWí_Õ¤\J]fSŸZM2ZóSÈ|Y|J]RLÕK®xQG[.U°s_y£mõKæduTUÚzÌv#zV~RLrKqe7LëXY½T`ºP*u^VÈnYeMS½1|'VñVu•ar«}\ zþyP$P-ƒ¡ak|»~Nræw„”ww`Zq’RgÑUŸSòYØDÈ{c|”–>xZyZ|?ooW÷KQdŒm²}€!`%\3uxp$d+cYZyZ×PrW€@Ns¬Zña¨lÚyªT4|ßzÆYHyNrKÖ‚Hƒµ]‹_NvMeOLƒØN‚èKRƒ÷w‚| cWƒ iOkÎomqªs½xzqÖ`øZ0F|æY„]©jj'_*Z¾[õzNMgwHiÚXˆiWRpÙbRMw}û^§m9|6[ÒtòsXeé\±`[Õ]òaþQ4€eXy„6^ádZÏb6„-`£YÁ„ïS‹aìyyKÖOœÓOŒRyiˆQÇo…rÀX?N‡\É| ÒR‚kd[sdzýO{ S®gdKP…;{ë^W{Ë‚¨`Ü[±|¸sÁU6SZ“‚ŒK1XÎh]a›Wgj¬Zèp\‘…6äa:#»Œ{ VìQ\\‰Kv……y>ú :šZ‡>TŽgzDT…¼…zR)m SxfÁM°…TÈ…¿…Íz.²…“…GM‹K:<¿…Á…©K)RÄ…œ‹K>Tž…m jÌ…Pv[*mÂqH‚WHZw_8‚èqls€„GM~rÜa½h™`\S›`È|ðpÇh4XLe®Z¤scÉ|pƒ¢ïrë5_nàTçz!S¡\OP_÷a†„EU½[ØLÄ\4[2iXnffT[Jw?]¤‚ïu;U$ƒ×pŸ©@NeO±ƒ$t\X¸3Q0HúZõRY~ªK4Lr W¢FoÉh¨[¥z‡k¶M¯*†¿K¼y€¢…MC†@S5†¼ƒT]ôZ†‡‚vw>†tz—bq:y_]‚zxwZ2Tÿm;W‘ZjK_ëP‚mvyÀågåZ(¤[^I†J‚6†T] wL‘VÓ[^U™€Pbÿm?Pnö‚ oò\h[¾e†÷TQoa’|‚X¦W W ÒSÚr^†ØM²vËWü` ‚XaÚs"{PYN´x’}£}•}>e[6ea{|~`+U]cÆçÁepN¥j[yOVËz,~Íoö…1ÙRÉ‚£†m…ßp>S*dZ M¥|…ƒ«YÙ…'d£x®d/rìhOƒ‚šÊ ¬[3kÁaºŸKÀSyö…ìQ¨~›vá`N\¬~`±KVeÜ‚Ñrb„[9tVÜf,W¶_+x {f\YqeÓ…Ø…¨…WO[L )L¶…-o¡| V€j¼…»…=L-i)xQÞ…M>?hÀNìQs†Mó€>TYXN»…ØPCT&]6åƒKù†À…hËQë^§€‡ÂS‡fhò†‡õ†„´ø†ß…ôm0TÀ‚c|Ê„L\‹Kˆ#ÜWµK5‡&‚k)oCTµLiaƒ*‡à~‡&]nM7ˆ]:ˆ`ƒ´1UÀYZS2ˆ‡CôþQ<Btn1h>eM^h|‰>TPÄdÞeRYÄUCUT_BUÞ R0‘m!n*‡`VNˆAˆ,¼jéKTˆn2XˆiLoˆLˆqˆ@ˆ4ˆÜRˆwˆ3zˆèZ €•]ˆ¦f`ˆ‘dcˆ_fˆhˆjˆ” lˆnˆñu*‡êX)`OVVz‚¢mîyÆW †hYÓ†GpsK°~èSîX%PöXð`ýRyKuPM«|íaØOLÐx[ƒeÌÀµˆR`×€*iÚ€tÜ€:Meƒ´Kgƒ+}iƒä€kƒqMl=i'ˆW)ˆé†+ˆ=LäV.ˆ¸…–lrˆ-’f ‡ß…9ˆ0t=q<ˆJˆ>ˆòVÓˆ‡©fEˆ4P;ˆIˆ^Q݈‡ô†‡ÿo7ˆü†+ez*‡áR߈ö€Dˆß…‡GNìQ‡j„‡Lˆ1ˆˆ„ƒ‚숀Zˆ‡`É„Ág©K%‡2f(‡–ˆì†ÿ€Ôf7ˆ=Zˆ|ˆªh9=MÁkºrŽnÿ‚ðRˆøibZjø‡YVñzk]T]¶h€MÂQ(b®‡í‚gvdx3\†\ˆ‰\wbœe ˆ§[n`ŠatM{›T`k:‡SÜ_íWƒVÛX‹†Uze-_ÀS€…ƒïZ6f=r,Rwˆ?]h‹je,x¯‚uRþ‡N×T±awzºT{&pÂ|œT-]øR×eCuÍ\Ù_X‰DTR…Â_üaM€õR¾\‹Ìæpb‰¯Y?vÉOùj&T±aM…Ïy“_]Ántñ_ˆM3‡jÍ‚7^ßa/hT/leb'cñ]x­†/ZžPeY›QÐZNsÕwÒZ2|>€(dÒ‚U§O/X€«…D€)W*‡„[ZeY\²R±‹ƒq€gïV§ˆ^q$²‹ z<ç‚Àx`\Mª}mqö…¯]Žwãz] Q{‚y‰Õeº_ÝzŸX¬‹·ZÜsÌvVŠýr߉ed U¿Š¶XÓ^©|/Xs])L©yÅK~]M sTq®Zx{W jö‚ bÆh¼†¾h{üÌpêu<ŠZŠOsQeSÞQd]s‰ÐAwèq÷i0Tñ‹K‰Ap7SÝk8…8„í‡0‹Ze‹€UÔY…ZvY´yx„v‹^qÛbÍ^õ[!vÔRÞQ©|i\Ia‘~Òt«‹e‹ã‡ÛNNŠ»T[‹ØQGzåQæSÁNˆÖn cZ|ðsÛ†ÖtŒMU/…K]àXÇe…^¶]NRlabwT|S[ Œ’a1V©s‹Ø‹ÊuË^T\@SNbƒv]Õ}ØYSTeZøi‚‹€µM[”xž] ŒÉR&LÚ|Ðo}€§m‘‚™\V^Ì‹zx‹€»€Uq{§O„gAÕÕ^w¾uÀ€‰soi €>K»€sŒ*X]~Æ€®€tŒRŠQnÇ€~Œ €Q »€qowùµl}êk<)bKšŒdf¹ˆ…o=YÛ€dƒ(}‹o*}5i t8iÛ8/}7Q+"©ftŒ4„¯[{O)hwamupcO|9‚ûƒÔSÁŠwd„±S„ãUR^`„¶Mi„„ß~~ƒW}oŠfWd„ „ƒ`Àjè‹7}„‚XÕŠ"z…ŒoaÁm•Œ|`OTŸŠbctŒrnÕhX*Œ[}#p@%o#q¬ZKw×{§_c¡‹|Î]YRNº\LMe[wÇVwú„?`¶X¹Tå‹­ZŠŒ%ŠªKÎp…ŒÐŠ$]Ãb•Œhz0‚bb²yGYFŠÿo¤ŠIv‹‹'W‹p1T†Dz­ZçY‘‰]aøSc\™‹r›‹¡TqŠÐYã]&P­{ƒŠ8XËãf[‹&x«‡Û†…v4€†JSÃpÓ‹¡TŽep€7eê{…_XãoWbw¡ŠN]mƒŠŒ)ŠŒY,R®ŒJ-Oy@lR|‚¹ŒšYéz €îi>]‡ƒô†Sd¦]VVvWýa‹Da•Zxt•‹áaÏOPw QÉ`k[犩^UþQ›nÕ(áW‚¿s(€B^„xßd/Štw4Š!„cNpŒJüÌ}…Œ+fõ€Ö O®Œ´]A0‰wŠQ~R”€¬ ާKdU%Sq‰yXWvKPZT…FNÑd{5ü[j7cPŒ…Š%†`KOUìgu‹*rìŠÍt™‰,rjb!a¡‰ðR®‰)[qŸ_9MøSÀjtŒ…þZŒ~³Œ.Š ‚Ä‚r'‰eˆQ³_ÝYÕrªtNRj%z~x$T[‡©c|ƒ+…ªKõ_Œ+ïS‹jõ\z[µZø_éM¯{Yж_+X3‰"V5‰Tž„"j_…Ì`KkN'MdžKds…raåegvAZ*ˆ˜u.^äs´^⌹_y4S&oO=ŽMc¨V?ޏul„⃃€)€1UÓz–Z*^ŽTŽNdƒ+Œ¿ŽŸz®VFyŽSä„_]7^sDb+vjlESË7P[ÆÀ‰dS| eíe—K¤~Ãcøe W·]²hVS\j¾X…„€V•ŒN„Ve1XŽ´ƒ `èKD„„ŽŽ¥‰ì„~Y‡•Ndžá\pWæOÝYgŠÝûtMkŽGMUO,Œ¹Š™dOM€OŽQŒ`w†Šu)L°_´dd\pSjN¨R1yZŠŒM\‰q|L½jN„U½NÃ_Žq`•W¬büV©WsKXàTuzbïZ!w¶~÷K¸Ž…Žýd^K\d=|¤Or‹l`ŒTex‹d¹i|«T„XErjŠqËR«SSqP„W§‰&O{mgÇ‹ú¹…x~‹œSü`¹Y:„ÍbÖSÞŠ>b¨c¶sDVpŽÛwp|]‚€FŠ`[Òo_‰A‚iw%]¢Môa\Ðy'h¾‹N|ºTp`KŒÔZÜrëfÛRbcmc2’Z‹VIŒ³~7†2TŸþ‹bb!ŽqRQO¹`Ó{! G2mŒU&€}ŽªƒqKËZdDvXu†fYŒzYYìUAZu__is޲o‹ÇhX«ŽÊ[óh5¹\d‚óK˜‚‹~Ýu?xGŒQðƒézgR!ƒ²~íTK'M…Ì`ƒx#‰›Zhq{mäzŸ}7‡¾_sRÒZzW–_ Œø_ ŒÙ†mVpwÞ‚ýR<É,ƒf7ˆ±z@†¿*‡¬wÕc7ˆS_LŠPl¥|7 O¨ß…R«°Ž­Ibf{gKl»€y]²ú† |7ˆB˜MðsP®Àƒ¾bU7ˆÁß…Oµ•u]Ç)ktögÀ<Ä…> |¿À…FÐŒrnǪ^ÖM“KËß…Ûæú†Iß7f¾[â¼QÊ×ç,Ü>WZˆ®ŒŒKˆ»€£KÖlÌôéÀ…X싌>T"Ha»s/^/ LpK/'‡"üØnß7ˆæ4iL®Œ‘Œ>TQÍU-PWRHrèˆDT Àx6 œ}‰ÖŠWz_v)rFU¡ˆ{ TxY]v¯[1‰jTó‚Š®X¶ƒ²[´ŒrYr™zúj‡ƒ L~d\T]aÂ{†Züp¡‚>Xk«|J‰È|ÀpÓ‡9S*aú\¥ˆ-yÂ_'P×c™X¨vAuPsÍUüKÐe˜[ÇŠ²yS¾}‹|Oæ‹úp „fWõRêY„_`epeÝ]uCŽÆŠÅ_Q¥ŠŸ†þŒçdüyÚ`EÌnŸXzßdÒyTžux]È|TBÝS5…€ röTˆ‚ÝjÒUUO0Oú]NyX›Yµz«YUŠ[|…§[~Uzs¤zx{i+‚‚zP[-eŽýuƒVXOm‹ˆsFb-e[eQO¯8s†~bTpÇŒ%ƒ¹\ab;S#…÷Sûƒ Œ,€ô\vo×dccõs[Y®€ªpàdWOT3½Ž¬ŽÊŠôz^O]„¹^zW~Ót©_÷‚gY{Zâà[ІA!Œ$fQoveê?ÇU"]1V[-_óUcQ^-z$Q^ „ÀjÕ‰¶\pŽŒu¤aoX{Kojz´K¥`<d†@W䡈ãkg#åknï‡bU~eý…&ŠŠQL|£tƒ`Ï€Zƒ~o¬\UKº D(ižŒÙ€ Œ¼ˆ¢ŒÜx)}3iˆËiĈ/}ÝQ•o oDXºeû|âjŽö-~2LºKÅeœVð…7‹8Xå}:‘`RÍ\‘ªK~UŽõ]‡ièS'MôÝaËŠ$T§QY…{W/Œ‡„t‹ÂR‚RTJo6V;„KÎRàrPWŽWKL8VÞŽŒcæO˜„qkd©CeË^¨‹¬vÒi‘iwMx‘ÊR9kBMnÍarX—nK’Z(ZCa¶RþpùcC‘OSÔüO'*Lõ`Ó]Ò€Ž‚Þk «bþNNPp¼cè{pøZh]´ŽIWƒŽû޶‰NwVS¾Žr9Ž_]‰^)Œ7‘yƒÈ|!Ž'…'tÇŠ×r-yÚdLh©‚¸uï‚vVŽ{jWÕ‹‹r€¯så‡~9†ÆŽ·ZowX—[kTëfh\Öy댱vއïS’ªsXY8X-`ÂaY˜WNŒPLÉ‘¨z\»ƒK@Lpj^qP€übɉÌ^i†õyÂ\¿c’:Œ Ú3UÊUƒ})‰‚ôZ[‹=vÜ‹À„tŽ} xQ:Ž"’JU*\Ps^+lHzcÁN'_ ~¦_ž\èz€¯~—ZM¥ZêK y¸Ž ƒ L»Ž’MåàdJd‚! ~KC|J˜s”‚Çð‘W|‡„‰×‰„†¿c3wë[’Žë„6R{šaÛ†t’†ž|®uÒ„Ùbîa\\Y_9]‘j¢YjüRzR`÷tl„½[®SfW†qT·€5SŒ€TKE}Uw÷‘zjéUSaŽ[s+h©¡T6R«Šµk*Œ]‘}b³ŒOToyÎŽ ¥~U€AæûzñRyK{¦añ[@RnÐ}R¨]@oá¢nÛTàTI’Ð u“PGŠ4wŒºÖkTb`QŽ…Ó„¡‚vzy]ÿZûTÉ[ÂYBUÀaqbúz`Sp+}Jevb6ƒÝYSrfm1Žim [<ƒ§O¦n3bƉ¼~zR!sôudKu>xWv2D{`Z+_„u¿U…K‡u’aZt§mè}fi‡ŠùaeU’vjtšƒïVuuW§uØè}Uã[éMd‰qtÏOÑkÅZÿ`ñs\O †¾y]Ë{±“Lj@OVѵP°ST~*lûcŸX¦ƒf^I“dZ<,y§=W-p}ãU)…E^qþ(Wžt>U^@ciTxtU¥t”ŽTXxwq«tŠTæSöOXÊ‹òn‰trN e}õƒ5wtŒ—‚§ ‹6„…QA^?P½SƒKMu·id…n]Vl“TMŒ©VŸ†[ÑR „F‹Pbœ‘£XìQ›nW’z’W`tåu^ä‰bB÷K½všƒºn?Pïbg_žvZïZØc]öV-eÇvËOiT˜T/|Æ`ȉéuØ’(Œ“Y¼}qÂ|[]g]y’ÎN SˆŠDUÇw’XðVwv¿v÷…i,yFvS€(pŒ~‹tÈ] jGxd P¨dif_§YRQzož„äVSrý`ïz%]ïb¾}ob„gR¨eEvþ|€m\Uœ‡V M’_щ/‚‡s4LøZߨxŠx%–¥Qԇ⎖¿„.rÄpü…V©^\NŒ{£nt[Ћ‚wi³TeOçM(†ÿ`šî}+lp˜zfÚ,7ˆ>TŸq\XÞ•agzýˆÍj³Agž–)_Lã•£–*‡/m} ¨–ó7ˆE¬–€”`–¥–ðl˜ÿ©–³Zˆ—zÙ•ß•–ˆ+",S#O䕺nÒ‹¬•TS[ü‘¹ŠþV¢–¦•¡Oîs‚—`üY9„9ƒ]TM[3SÄzÈ]~}8U»R>Œ“ÊYU–{WÿWwXƒX;ú—LK dÃbh‰c0B|„èKO{^Ús!ƒôZ†,!†i«Y jëvaA蕺X'…iŠ(_w_Mb±W¦•=]Ò\B‹6 !lA~ÌkÎXÛ–azf ”ˆƒºjåËL Ly—®ËL<„u|—Íj¨MúZCÈcy— &fsp—–UK^‰†—ƒ…‰j#L¹hšˆÛjfmO’÷K—&“ÔRªP3abcK•'W j;cp@OÆ“/•u[—úûSò]`€>•µŽ0…¯OS…“óuWUB„Þ]£zFo¿—:z![»Tæ|0y(7‘ûc²ˆt•.OMéQy•%‘{•‰o£Œß€¥Œâ€Ãˆm/}”ol^––öê^[ò€"’Ž“^—ZiI•A‹NXùŽŽºŽd’ü{Í–¸\o^™—L¦KVPÉdqK>–4˜`nò”VÑŒE‘vL–†€ìƒ&•L\yK>{ëŽh¾h`7S/‰ˆ—R.b­cæ SèvNv#…·U½Z”c¡™Ñ^ÎXW” ˜¨_ö…T†ÇƒYUb•—QCLSÀj{}pY:“—»Tç’À’›ƒ QÉ—ìa€¼{ÏOß•ÄUeb§_SRMú™Ø^C™]CpïZ«ǘ"LƒL«„—„<…+ZA…;‚“ºTna‘P´†\Onu‘ Wz_¸]²UL![]™„—ŽK5˜D™eDS~s{r¼n,˜Oy„?S˜-kƒ„A\½‡Ôi#yÉOs†öV|Uâ^Xg]È‘h™ì[¾s&X$‰€ãU^†vKMÐb/x?`ÓLÚ‚VSab zvõ[kNYW•wŠMÃKN¥x]wã]¹Týc]~ôZá†;Q°}jÀSbc†š<a—Äw\’}ãr9W¡‚/ISØ—7•«’þTßio€ñ™{[¡9†x‡Ó`Ý—:Œ šXäŒDzMM„Mµa‘3‡•ÐNSY8i1q'bgo]c±‡bv"xXPòYÈKù~Ë`ž‰x”@S–‡;T{ÔnL^bW }aðtž˜úP†pËQ2p‰Kqe#€7‚j]TSa´KôcûT_‚tŽ4 ž]V˜éMø˜oiTeŒ3ƒU»TÛw,ymu3…¬xÕnÆs3Š…–ÞLG稓Hz*u€ŒdxLU”¨:ZËqæo6R[‡t‰]‡)t†YŠÂŽyYúŒT‚Üš$– Sž[šÊSÙR^†©e_X3Qš ÎRs³MžKv“b/yr†«’*• ›Ì ›mš\EMSqWcaÇyœ,j¯MÁNçÑšôo›ÓUb‹RîyíSmU/ê—`q7™ªš+hÛn'w¡d"]ú‘5_Ñ‘9cõ[ÝYN•QZQ£XäVç’ÔeZ…ÆRÁ˜™u)LÔO\'˜MoÛojÁNÖ‚ÄÿhjP¤DS“KЛaK9Ná‘n•“y”ÛR— pNh?j¸_uÍ‘ÓU4$ÎRULF˜Zo{`HNp`Xn‹@”¬XÅCpÖt"ŽUqÕ‹,rñ’–Vvi­ƒÏUževkRÝW{™Í˜Wv©|“p pÀK–pÑ›å–ê_:–aË|ÐV… W†U^1wõ›¥xž”P u7^YÿŽBc?|”Ö^%š¸K¿sÀ{@p „ʽ|ÙRÔ›O’õy W,Õewo;›FU>uh—^})LÞ)”øijyjÈ|8œ\\Ë“PUY•SS|û‡ZŽ©½jUs|›fm?‹³€^ãu²›txˆQvKW“’RßmÈÊWR€op}gVüŒ…6›)LfœPÚOx†ž])h,[?“qc®mý”gSJ€Vq׉̓Éw<'õ›Ò›uTõ›Änd“ŠVS‚SÂ’uÎh œ¶—áhZZ×\™f[Vóoaa¥xUe¹\»\°Sw˜gT\cƒœ uŠ\êtðc_WŸX†”ì–YêšL{+WÃ{ARàoŠž]ž„Q@‘rWÓyñ›{m„Œ›•$%\0pÔtuRŒœ5\P‚±„K–7”SœsuÑpó\Ôrz›ÊXnußc3Z‰W8p’aÔ—øa3Q LNl/póuÊ–@opY³_XdÑœæuËš¹`‰[˜œóŒlN—Ši‰}–£nÝœUwQLŸ“Ps‹˜óhë*UudünÍœ:›ÎŠt†È›S¤aÝhI\qedS<”’d’K“æ“÷pžK2wJeÌ™›_¢b› a-›Î™+V0›c`yV¾UØÎœ;›š\æO ’_zpkdšVžX!aÂw:CùPšzoLu|^›#Ldko‘£z—‰„×vT¶dsy0T˜ó„ÙXtx>Zå›jRùW^ „D\ÄZ®bÂŽ4?€\^¶wÅT†Ð$®…KpU„‘\‡5|Äœö[RMçVÝ\èp°›Ta4ce‚¨˜Ò`Û^!oá›–Y¨cátíz&^“,h‡{Ôb“IM;„C‹!r°‚¯›3šÂg¸›4VŽ‚ž^?nwY€]@’¬v{YS=ÕtoªOïW'w-_JW½h+j˜ŒÑx#LôwïkØ€Øx¡Œ{OÝ­ZFj‘WzÜb…[Òy j_Cq=:R t†•>RpMÏL&_NKFP †.y«¼TQPÒyçX¾š)–Ù}f}¾U,XÈnb’Êeo‚•ÕŒ›œÎ\wV§›ç˜X’BpN†$„gŠÕnþ‘Z–C J.l_z›~…õŠRøiÐü2˜hµo1xZZô‘˜V;Wirc´›Õy˘‘LísPZÝZn‹Žw“Š‹ S›’UmW7•u|E>œk–¦‹0•º`h^¥T›R°Sâ¢ÛeŒ_X–Q‚[ at˜²’NVowsÔM OBPºeygŒ˜ÇŠõhKPRNù~zRa›ø›bc„\sÇWL‚]Š^QŒ”cx…£™ÎTk[|S0ž„RñÃm›ƒ—`kb€B’0˜eO´œˆQšSâp#j¨VSryZZ„WÍU‰}ôjéSŸrÛsx»sÞ\¶˜?›%h‹Ýb%ÍaÜ\tMZtŠ"žtˆxh[¼]àïWÎ\6Rï‹·†‘ŒcZ.ÀXJñ‡ãsVƒZ1k„µN‡‘eU•LŒÏ‰ã} x0w1TûBZCT1vC€:z½ZMŒ7c›‹S¹ZxR^“ŒcžP”Ž „?Lšj§z™»{yU"fkaúÊœ]nžÛS›jw¤œðZìvosåb;qlŸ‡UûRü•˜Òv‘yª\i‚¬x‰kŸ|R?P“—]Y_]›Æ‹&rAšäp÷hÔ’5šœwŒžŒ‹‚#Èžx’œ€x€toßm›K‚0{ÙkV_®nz¹—æŽaÓ€DU¶VFŒB‰®K1õœ@S5”¨VCŸ y&^äs¡Y‹ÛZnŸØh±^ uGMsš_*Uu]VTšŸð[mq¨aW w3kÙs^1m4š`·ŽÒ™†Žë„„‹ uÛ\לæSTÙR¶o~T㛩Q]‚¾ts ‘iVx˜Žc¹Ÿ¨˜;a8unÝY|sSp©›ëN‘×™ó—¾”‚’ÝŸÚ]SZÏp)beèZÂs Ž•`Í[[°aUKÚŸÖ\L_¤XÆK«“ÔhÀjaW=¡ƒGZqPaU‡”a•ú{|WsPžE‡Ž1r)Ÿ}T«ŸKuóhýŸnž0˜(•ê_ÿWùŸÙ™^`¿t5wüqh*T^«nœ]S+RW‹ ƒZTŸƒE{]V—û˜Ä”P[ºt[—ŸŒŽX!C™¢iƒe¡aù[‹[¢xñV‚FPRt[‹ž1 «Vš‡‹ OA\6ޝ‚Ûo]uDYGM}ž’v$@ŠŽ{’;o+rŸWÍ’çuWw3^¼]+–ÖiEšq¥`¶l+„-”L9/šØúVçn¥ŠÐn±u+­`w…øŒ¥_«Tƒj¿K]|ìŽ}RD·{› úS…~~X˜VnTézx„mH[©q¥˜Zwך´dcTSr.tzŠ…^‡–VÅž[]=Q¤R×tt ø›|m|·”›W>Ÿ˜:|sK< téb6…Ìv2€âšÎv½“]`H zK  `j´z^oC ½XZ“Ì^¹MÅŸZö‘ uJž ’]]¤ƒ°—ËO€‹±œ¥OM[MwØ‹Ÿe‚ „æV>šã =„\^Ïž˜žõ\[›Pz%sptKpïvkvìzª‹ •ðRmŒ™‚êdž‹~È“9t2›;tou‹Sry®Xž.Z^`}ŸŠVw`^iÈŸ¢n@S’vR šƒ¢\‰V{ @Š)hþ}3‡÷‚&˜ó éM‚dUØ ’µPeýdK5éujj`~YZWœ €žw•š Ü‡Øt]€KYæK*Yå|sº}SƒPs:ƒH˜ž]gž0’®’{½ŸV^s+s0“^v\/e¬xH .{5Žn„’Ÿ3—J…u’kRëfY“]”\’ù‡dSÞQËR:¡¾t‰H ©b&XL Àxu ËLè‹a†cT€aq޶_Ñ Šit†Hv††5‹·sˆ¡Dq"ˆµžöPžŠËžƒpYÙ’û‡¥€úZýžìjÖbºƒ-ŸY ~ŸvXnŸÕ‹‚;œY^3ŠÓ˜aœô…¬xg_sš uŠ×wbxÉž˜c:iÇ–P—˜ ¡-\R_´Y0–z³`º›^®Š Q¡“¸\’¾R¥’†Ž’]‘¡ÅwVr`Ÿù BZeZí_ Ž_ÎX“›k‡„_®€„YF{‘²yït›‰áorûžP[ß¡Vđ臵\n¼}$‰ÄšÙWeyq¡¸€ _N`Ù¡cÛjÅ‚„_ëÑ º‘`b|‡œ1ŠV~{VŸaP[þ¡FN]|Ö{ÂÀŸHŒ‚‡ÔR‚³¡ð–bc­v‰ë‹FWËv'o®€§UëŽ ¡ðvlvPb¿žq‘<Š‹÷¡‘ÊibOèK딥Žr•;ƒ^K[Sº‘á}#›°˜«{!Y¢òv‹XQ—Ìc|˜'oë¶_’v{oGsõ|Œ~s™È]8  ¡zpuŸï”If´œM¼ƒïZwù‡Fe{…gÿNUaÇœ…ubh’ÈTƒªkX¢Ò^$f®€dxÔo›ÞcüT X§ƒdš¡b^¹^W¢ß‰J¡¹\ä{ÀŠFŠ2ŒN¢ M+¢e~.¢ë”IÆžmZ¯{Àkÿ^õœ_l_Z{°YŸK(U‹˜=ß}P‚÷ƒm ¤[<”Âc#r™LÝk«Yœ¡Ôžp4Ÿc*Tú‡/^\´ž˜saùR¡TXXÃVcT†}çv2Tócw iAšsû] Q÷ŠÿrˆŸpASW±„¢’V”VìuéM'¢¸‹ðs [,¢9Mèkñ”»Ž2¢ÁcMw“±™}‡ŠrOœU·™Ùx¥*R¨'’Òƒz‹-ž^d{pÓ±Läx´ÿMŒPï•ï”#O9‘ûƒ”PÀK’•˜PÅe‹ð…ÞLNë¢>?ƒk[Ô´›O‚œT›žJ¢O‚¶b5žœ÷O!ah_~0~µ}ÁVµçŽæXOV‘fWN‘ šóŠz–éM€oÝž„™©‹ý–q—.Z^—Ydƒz¿“~–œŸL˜ú¢ÐbPt›WqȆ:x™L#^¬]˜wßR5`{“Km“u Œeæy÷;¡¡[ä²—’P¢pÉiÃR꫘ Žj¡et|[‘‹‹—Vrcçf+LZ\Ötx&h†VÕy‡c{›fSË|%h!aô£¢ùP÷£·oØW£^”jŒ`L¡{ÿš ~Vmq£Fž\€gŽ`)s´PtmÂU¿sxZ:š6U<š~£ÔïX!£Lûbý\¢Q¯“Œs“fY¨m' €[Je„E£è£³›âhw‰œw2• w?b^¢‹…ù‚Ç ’ƒ‡éž.˜'†b¨c:ŽÍ˜jKAšŽI’LP¤Gv³˜›xš“Žcw¼œ‰xm¡‘_•a³vâoPaœ-] ZÒŽ-žA€¥X[U•àŽ¢WõcdZd¤úaYŽƒ„Ý¢TŠ-c…åq€U¼zwK’µ˜Æ›h‡ay¢ßc{€B…1…?£Û‡u¢žR€¹P·o M€Ÿ¢TÖŽêM~›’XÈžF_Dp`‡d ž|M8¬œ†ZìQjReOe£@¥~r¨‚taôVž^ 1w€¤ñŽHoÓyv£©‹˜¡¨_áö‚0ej‰Ëqov6j¢! tˆì˜—y»KÑV²,Rý¢ØŠO‚ô®bp‘8Td>•+€»lÙT[<] ˆ[h—êxW>V™`yºso=UWv»–6¤¤^s³˜qX  ž±¤ÛZG†xa†V4€]þ”ŤÏO0›uã;o+£9`á[àœ©£f}êƒ]o£zR‹¤œß‹¾U¡ZÃ|™Ço[±¤9”Už^iŸk’0‰ñ^‘Z7”¸P€£eu‚6V±“>¢q½O6MCRkhÔV§£á£ÒPç¢2`×PÙP“PéyAVî”ùž)L1L&¥ïXÕ£ìŸóTeimW¤‘Nv&oBˆ O†OÝ›a<ì™°OŸjö|X‰ …iAbz"_„TgW;{jKk³˜*Ta xgtAÖ‘RYš¶Rã¦inž^ÔøP€ ˆûWÝS`5]Ûg}‡º‘Øhü\ÿhQO`öeŒ“bc`צ,\¿Œ¤\è¦?Nê¦U§¦Khzwâ¦7^å¦ „\Xúx’csmÚ™¡ÔŠSZÈ à–k¤Ÿz;yŽs¦´KÔ¢ “K&‚q™âV&T,X‘ÎX„¼ž0¥{ ¥ÈsƒR€`U|ìfÏ|z¯{Þw€z6—eoÿS‹R[} cK€aPƒ‘±ea‘YVŒ£ç}¢¡È¢Ð€e8kÈôwÖ€ºˆ¸™ôkdK¦äšFP©¼Ü¢û£¦›°ù.iOœ] SW›é’N‹xp›Zö‡÷™€pšS[³_b¦‰¦>‡;€:t‚eSL™~—¥_SWiu‚F‡½o—¦Šv’µœ¡nšJXè{ö¤ïpò]E§]Ÿd’¥xÜ‘4Sy‘™myÕ‚Xá²â¡ ž>f S´œx}_Úa¬Žƒiva¨QKy9]`…ò^ \ÚžSj½[ô[fmMSvs[ÔÞ¥âŠn{6 Br ¦ˆ•SY2`R›ZQÛ•~ð…ªX£ÙjE–€ø‡:‡¥dîœ^z¦3””@¿}ŽU…¤7¥3[ê_’³‡^Ц£ÿnß™¾UKwSWxOUÞ™¹v‹§ÝYnןQp0¤ÕŸêPZòqöŸÉ¤¦™vR—O–°’ŽŸ¥ŠÛqiœ m‡ö)[-•Ikctp¥ÝsÓL§ó¤j‚Šq˜ M@’2R0£4”à™&‹¼›º_}rÆžÞ¢ìR å§L|>ž‘,–W„ÔQ~‹Xm§ôžÝ}£¥¢ýXqˆ\žš„\PSŸŒbpŸû€ ™q ~¤w®Zak„Ln–y’ËRLÅTò£Ù§ñ`j“~Y”pW± ½s«˜è’Wžˆ¥·€×YÑV+.%Z¢›ÁbxbV£0T;ú˜8^!œÏ[ÑkÌny–ÅTPUOW†í—èšuRžª™•ñuùpíƒoftô’é+s»TÜhTI£u˜?§ îXÈ_Р¢£‰O… OæšäMtWºW­UeÕTœ™£ʊׄ™IŠ9$ž]›dÍK qºM žÌ0[›;•2^¡Ù‘~c,\Œ™àœËÄx“që¡€üi.•í¤|‚º挗tPZ\M½TZ z°ˆ¼ž¤çWìQpp}›.lk–]¸¨7‡-†ª\•;‹{ƒñœ>Q«§bË^)Zù§V€‡>w胚ëh½]£Axßb{Ü[›ƒ™8nsT†r¶ƒ¯¦€{F›{ˆ\Ǩ#VNQÂY÷T9N–a‹~?dôZJS$™]|rWCš}p±iû„jØjU•w¾y2y_j’’R͘MXœ_ê‘O©|Înõt™e…x žEVô—VY|a¦ˆßŽ#–‡rªk|¨äifzû]ì]¡J…RuÙjü£¬‚xXq_\Œào¹§þVU6R«Ÿ¶R¹ÐdŒŸ¤d€Ôi{OÖaNMÐp†iõ[O ]çÝhDW¾WÞ‚ÆWª_+",xQA\UOGÈuqK0YÝbˆ[‰R^eŠAŠ‹Wß‚‘R‘¥gvR›bþ›n§l ¥U£Y§V¥uVÞ¤ËL!Ž šLM¨Ž?”ä²’•£û¨¾Z c"Vo(Š?׉EžP¡?œ<Øœ]›ƒuy` ]ÒÃ@âŽÎZH—½¡2wÂ¥—K#^s¥+Yh¡9rɇ¦Èt|Sä}oxžu¼n[!§Ä‚L^L¨¸WGíR£du“Ki ‚ï›÷TÅ‘’KdB‘À_à]Ôt·ZšŽ‹`ÜS˜‰sP­bn‡Îv|Šp‰Kz$w £\^1r³¨öuÚ§÷Zq´Y„–{Πâv¦ÛN2ŸÆ¡¹M€›]• Ta¨+ucd€ž‹XFI [Œd‘d©Kd?ƒK@LKTHyRJŠLƒK@™È’VŸ©›sòz£V9^ÉsMÀVwZŒù‹%2{NK¼¨ÒfM÷›Ÿb¢Qú¡@eÜfæš/€³’¬\:eªœGZ˜¢Ps~QÿŽ­^ã¡eZè˜tTˆ[bŠ Pk©‘Rýp™œ¯]Ô§Wi‹R'z&\¹§Vw§ôW†x †¸Xn^ó©=zú©ºŒ*S]{hK³p»—V”cà§L¯ž£6U¨œP¼š^¨mŽB^®¨úr¤—’¥Í‡ŽcdkXiŠQRM§KüR½hÌ‘h¡î©½s¯]àWP[Ÿ˜Fe4€îŠóé¥{oQ§‚À˜àMÕ¢¤#Or§2©‰ZˆhûnªQ²CQe`ßKQQåx>iyQ·]›jª€QlªŽi†QdQ[YˆÁdjª{a €mªàdoª˜KpTØ]£XN¾‰sVŠªj]&s]v2“Ý_W˜X cФæ›>“^ácÿ§4L‘~í–»• OxËv±”±‚ç—`i¹¨ðU×Yئˆ[¢`Œn¨ +žD]öP•˜N}ª ‘‚QõŸ†¡ñX–ë“-š^z?§}y$“—¢5X!að§ì§ê ª|SØbE£$„Sc~{ª“Tv”~¹‘—ôhhásëoÛ ˆr4xªnÜÛ†cT±•ÈS‘ÌXÁWrÌmô•NÍo.nÄXjKa/T™K{ L™K}f«ÀKz(£ýSÇ„Œbð˜Œa|@ypY$/TZn¤M/zËR$‹F«&Wm«p«à|¶_N”Æ ÍÏB‘ûRöï{‡„â`tÛ_,|S«ü`ˆ«sv5V¡—È^jdjTH~®\òP¾‘]¢‰^ˆ_y¢kœÍOŸTX‰¥"T£jTŽšª«¹›õy2œc–@§©«‚˜õ[l«›nx™`u|!Š:i  Í©ÿ‘¡o‹`ôZ‹«Ô¤«‘«IŽåa`ö…z6_͘¤pRŸy‡]»T`q«È±RñiùzÛ}#O`t«QP„‚~«ŽUû—8‡BkˆUqc\A~Ûš“q—qV÷KZ«w—l«aÞL{üšh«’‚YVg«b«X n^åba™K[ÂÜ«p€gŠ›ú«Ch'aÎçQ_y$…¡!\¶‡\…LWMMÌr]U¬R\X ¬Uhe¬|!Uù«b¾—¬ÍsK¬a@˜¬]€;p˜øi{ ¬Ch™K== M$‰/z_«ìžÀX/zvwø€§g´njK,¬dZv»UP‚pKø€Évl/zD¬$G¬êK™KK¬/zb«·€º„½I¬(zQB‰Pw7šgTb|:˜TQB@VU€´Æ $ð«>¬ò«ÏL pëdùz`oy„k„”U€8¬Ò€¡wБY]¬–K_¬k„‰‘#Lo“ø€a>¬sb'aþ«<¬œ€gqzH‡y«ÀxG h&œ8SNŽC{‘i–ªdƒ)z( L»Xšƒ ‚=uâ}=”¤}/†\aÊ£ W—¨ˆY\Mb©Ž|üƒ6ÒHuY„šYùcy‰ç‰r^T¦=kS´¡`[*«?_El]«IrŸU"?ŠpKë”Ìmó B«ÇQjK딚odK딇¬K«¥f6_쫬ƒOi›>`atÜ£QqüœÄªZQ®‘!«,R…>˜ÿhVQB˜YQjRÓ^n¥ƒK„ª+††ª¬Q‹!«UƒƒU…Ú2U–aT9N-Šg\ «|¬•¦_6QžDMžzjRmqñ¬´dºª®‹Q ‘?Eœ}UO&€y’‚rìU1šIT€ÈW`‚ùq §Mœ£QêWmW»„wԋ㘖V |¹^ߦ͑!‹†Tÿ­®pŸ†¬@NšVx,X<_‰_¨V(“‰wq°Š’†7L€;ƒ;¬†[µUyÕ]WpžT8›ãŸl‰P®¯X†vr•{¡¬:‹J]‚†Cp‰ÛµŒŽt\¨ÕwX&u_]Ñ®.rj¯…zÅ¢¹KÆ¢P ‘ƒ„-¥²{'¥N°‘£~dæ´qµQµáL”µ¬µ RóLÕµ”iµã¢¸Ÿ S¤ª{jÖ‰¯¤eí£ê¤•°‘L»µ[L­ÎQtµOٵµâ¢ÓU®±ï—á¤8¤ZZLL}uδ/PÖµRÿµÁµÕ´ï´ë´WN?µ4a˜:Rܵ²aÔc÷µl ¤ZZù£hKPêµÏ´,RwµîµrµOµ¶„PZPÚ´äx‰Pƒ_ ¶´›+cŒ•ïÌ«‰µ¶GQkLâOÙµsµ¤µ³OÙµ}µÚ´Â™xQÀf¦Œ|]ZPδýµÔ´¶ÓµÀµ?¶©µ×µD¶PÑMÞL/‘Ò ”†[¶[L,¶NN¶ÔQĵÕQk¶ZM¶³jµÁ@HmKËKêd  pOVµÆ·r•êkÅ£0QH¸x•#‘µÚ´jµ§xQ½¸°WøT©¶%¸¸j¶¦¸·`µÄµMƶº¸¦…²b†ÂK† ¶Ò¸Ö¸žPƒ¶ä¸¶¢¸Ù¶·Û¶pO³Sê©dhýPÑM·Õ¸ê·‘¸´¸î¶È¸õ¸éO–µ¸›>M×Mg<Žk¸˜prkW¯¸y·æ¸h¸¸ÿ´%·ÿµ|µ·Ü¸Äqž{îk„ÌQã¸Ú·Ç¸×¸z·¹µ{µAOÞ·jµß,öNńɀ ‡„|„’L“˜üÌ„ö”ÔOðUüPž¸eL{¸&M«¶"¹ì¸šµ@ËLÀpp±OŠ· ¸¹‘¸é·:·¹®¶{P‡Z—¸cµìfj\ì`P¶h|䕽¶A¹ø¸ç¸(M R£¸E¹˜Ogµ-¸…•Š|I°NÚ•µ°¸Ñ¶ØµB¹ô¸G¹ü· ¹Ÿ¶¸Qiµ^¹~k” °#¸f¸k¹“·h¹ ¹Â·V¹e·ÛLÛ¸sª¬\Œ´ÿM޶@VšÎu@vó–Öž‰·Kµg¸yN]|F¹}¸¡N÷¸Ø¶ü¸Ë¸·û¹Lغœ FbÞŒ]~y¸ÎºÔº+M'Q±ºÂºbº£¸•·Øº¦0-—r[S¹ž¹´¹ãºNº»cºàP¶-¸øº­£‘Z¥¿\P5ºýL¿º»lM`º¢ºÓ¸øL÷º·™–Œ¯Œ/WîºÿºÉN¯º¸qº¹Ã¸;ºŸ¶ºÚ´øº‹ »‹Íº»Z¹yL»óºØ¸"»Á·ºô¶èº.·YµyŒÑÑž3¹lL»MºÊ¹åº³º¤¹–Q¤º49¹h·nh »LOqNKµé¶$»·¹èZ𺠺ϺŸMµºñ·h³á£m·i·ý%¹ô´)‚8Xs¹-¶¢¸Ž·+ºU»?OÓº>ºn¸ñ·ˆ!rº‹ì›À¸ºoL!»—¶:ºtº<º»„P/º¥ºi·Î³~L›·»•{ µ¾€OKLIºÖ·Ãºàººâº ¹¡ºÙ·"¹ñ·a„³·8»s/Úy±e®¹¯[d»C»öLk»Ž»cµ3»7¹n¸gºV·âúZš•óRݺ8S-»·¸»Ž»v»§µú¸­µçº~»nî וՇb¹º ¹@»1»ñºy»±»¹šO¨¸.¸i·‚¸Ì·È»¶·qTk‚kW »lL(º2»w»ÀºÀ»]M¶?º¸}mTœ¦[l‚)s/“W¹ »Œ»0»ä»ºâL¹¸·»DL7Þ»P¹d¹Õ¶òºç»ôºL·i»îµÚ~J¹V·„\ƒºâY…º`Lìµ­º|·ŽºŽ¹A»Œ»Ž»™û»¸4 ù«„)s ¼ëµµÓ»ŸM0»²»_º‹»×´¶»‘ºg³ûuæŽÿ•p†‰¹Þ¹» Pô»¼»áº¶¤ºo¸yº¸â'@²½¦Éš=Lò¸>¸¶S»Â»rº.»*¼€¸ü¹/¸[y]ÉWò¹XMÎQ º ¹¼Á·Ÿ»*¼+NÖºý¸4¸®€—£L«ºîµ+Næ»x¹Û·)¸N¼*¶(·8»Ç(á£U¸u Áka_VPñ»¾»¡»º×»¿»äº¯»cºú»P¼¸ÆTx2¸¸rŒ·ás¼R+¸o¼l¼ú·Ô»Ã»ïL­µQº©¸/¸Iᣲ\‡¼Ž†µ}†n¿k†s»ºø»}¼»J¼Ok—¸gº¨´$fCÜYKÎN·™vHZ¾´|mmU,U¸÷yK¢¼²´Q¸[¸”†^¸€º·Ç˜òxsrJ«ÇQO»¶ O7º'¼i¹è»‹º–Y µã¢ÛtVwKœ»¹äPX¼ »³ºö¹ º?¼0º wýy¼‡·z.ƒ¹`L¿·ÁºB»J¼n¼V»­¹99¹;R M…½zûR¿z ò¹Q»Ðº°»Y¼Ü¼<¼ ¼µ»¨¸ã¢K†NÓ¤|snºt»‚¼»L»ì¼õººeº µ"LAVxQ…b¸¼Î´sNï¼ »L¼”¼ÄP¸?·”oÙŒ¶=Y.[ô1·%{j¥ŠO&ºGQŽO¼¼Ì¼ ½¼»mMιã¢yž]t{K˜ã»Ö»º¼¼¼¼Ý·à¼³«kK¹•…ÉKÛ¸)v|#aƼt¹Ôº¶/½žº¿»?·Üµ@ 1¸M¹_\Œ¼P¹yƒhyýº¶?»ºÃµi»¼×¶D½j\x”O'„P&ºoºó»;¼¼°¶ä¸½N˜gº-œUVºÆ™Ÿœ}…¹˜ô·‰OE¼ú¼ªµ ½¼êNý¼­µ6»¶¼Ÿ¡¶?P¡brA„r½9¼¾¼ ¼#»a½»°ºÙ·O¼½¹“’X€½Lu~Yr^·¹¼ïºF¶É¼+¼1»I¼;º½%]>™qVå¡hK¬»Ù¼˜½½¼´»T½ð¼„½µºL t‰PD‹wy—£[½K²½ºx”¶[L–¶‰ºƒ¼§½@¸,¼b½ ¶6¶ÿ‘ldt|sê¼A½^Px½Þ¼k¼û¼yL«½­½Îjá£Gö]½iÁ¹¯pwq'œ&ºY¶ÿµ.½ ½åºu½õ»™c µÂ™¤þQ‚y„y6UÒy¬»ßºB¸@½Ü½,ºf»/M«½¬P{ºhm\xO·±¼†µÙjœºƒ½m¼¼Û¼R»B½j¼Ž»˜¼?µI»'i¶·Kû¶·ºd µprêx‘½{{M‰»ó¹ºM¼AO—½¹½¾$x¯·õ´ü¶¨zÝtßtu|Rh¼ý´µ~¸‘¹¼¢»,½ Q¨¸‡P¸¬ ¸-·â¶_·EV|s$¾µe¹‘µ¾+¾uº¼½óºà½ô´.¾-L¾:»i “:‘{¼ê½ö»€¼¾F¹[¼¿¶£QÛ¸C¾/·‘U»ñ··H ø¼^½s½…½ý½–¼ü¼*¼þ¼ÃLRiµT¾OšŸ~L´·i·|m·qž“½·&Q‡½ÿ½.¶N¾¾³»yNe½ò½nÑ…×MË»nf·ú´)ã·¡µµy»)¾¥¸¦½v½3»÷¹«½‚N—·«¸’RQ£ÏUµ¾»­¾~¼Ÿ¾rºŠ¾Ÿ¶²¶N˜–»0¸b¼Í·Í»h™«ºº¼B¹)¼»½¤¸Å¸Ë½X»-PÞLá¼p¸)·nÉ»œšJšU˜¬»–¶½¾½½Œ¾Ÿ¾v¹ º¶»ieOÇ»¶ˆšrá£3¸i·ã½y¼ƒqûµ&ºg¸Rµa¾œ¾*¾ž¾Ù¸&»õ´²ˆ‚j¹Sr|o” •t/Í•7‰ ëiŒ¿QKO› axe-6.1.2.orig/Help/axe.letter.ps.Z100644 243 144 257073 5576304472 15577 0ustar joostusers%B@™Ò"™7bʴᆂ%†È)†Î9:@±“Î5\ÐÈQÄ7pòÈIs 1rà°ÁfŽ2@H C&͘0l@ÉSÄ”7fèÜ 3ña *iè°)“1 ž2.6¦q*‘"4oÜ©H4u@)#ˆ0iè˜CŒ6sÐp %Ì™2s2ÎÀëbß¿Oä)ƒD9cʸ!ãTÈ›:“Ó¸9cOF @×Èa2œ™|²MÉtæ<$b%ÉÀÖmÂLf¢¹¬V Z4aµÌìÚÖ‘9£Ù2X@\¦§Î˘z2„1CG Ô9*—9£Šœ7c¦”¡“‘N<.àœBÁ *Љø|)£èžc¼´˜Ïa¡_€ $Dž ¼àÄö1`ƒBì!†fdhT†}8Ñà{¼76ˆÅS€àD Ñ RìA‡ºÍÁY%¾†™ÔEyø‚s¤¡GQ1àuCNmÔ”@¬´à;²1Ç[€Ö^„…Z ŒÖOtô‘KêØlXƒ=ÙBšVH±f›_…¥Qrº1UT•WÚ9›nê‰F‘G*ÐBšq‚ÐdP Áh&†"š'ƒuÞ™(ƒDYÔ£9EŠONj–’V´a.7‘tä6cxhTºòJ½tfþ*" T'஽‚ìz ;™³Ç&k@Öê*®9qãdÂQÆ:òÂŒuÙ‡‹/‘›ueFe±ÇtTTǾô»ñ²1o½  [”²ë6„˜p¤¹#0ìðGX$ü‚MT´E—ZrÜ…F!D–^‚ÃÇ ºÁ hNØ—D^  17H†-ä›äªlÚžz賂š5hDXtP‘‡¸o©h4Òß «´Ê‘+ÈH‹üF®!»è!¾+mÖ a BtLј…Qe \t/QÇÎd S{(`7SrÓÍXŽ«‰Ù“Ø/;-Y†dìJ®o¼èzŒÓÚGNi‡±6×Ûq5l¼Á“—*+ lƒ3Ǽ…Å7“;x IõŒ\GíôÍ9‡±3êf\é «ŸÝàëVoÑ»C õîç%£L»ÎlX\Äp ‚ωó:`o‘¿”möØÂiA{xOFEa(P=ç’1¾³sÔÑV°Ý£Ñe°äRùöŸŸo³SÙÌû~¿ù­§~-ÀR̰‡Èaêúؾ÷Á¥€ÏÒžü˜‡ò¯þ ˆ¬œ`0X0‘Á °µAv™ á݇,¼œð€.´_ró—Np}tXšqxw+ qzã* _PºÒŠ ZÑ™,¾š½@w°"s¬x^±Ì>cð¢Ó^p+oŒ{“Cߨ°9Ü+ v( \ðr6%Eë{Ù̆œ`è=T@ŠâÖ¶0…)Z¢ù&èñЉ3ªÙ ½ä=š@Þëà%Aà=üé,lK%ÈIûO|ÈBU)[ Ieë'#ªW8™Užò}Ì_K^b°•ÌQxi ð2ÊMb0“¤&q Ø…îÐ/e0Ë›9¬!Z€±ÈD,Fra ¾«^ÁŽHݹïˆ~ÚC.5=é±lEAá79ÉÑùŒtpÛGIOš¥¨w1P@:×·¾Ò&€’_³ü8@&Z½‹ÂÎd-51’OŒ"‹Ø•„ò3£ ‚ÅÄ€’=ì‹1ýJî׸k®Á o¸ƒ,´R4´”/˜BÇ J,ÑŒL&©7ÄÑ" ²B«¤ÆIYÁÆV¯j^P¸>UU 4Te–ªP¥Ü„st W¬ÐrI¬g*ƒ•ŠÒ¹ÏMÈ‘ÉBIŽÊPRb_)Êlz8@'UÌ~ìCW8°ô .…©LCTÓ›NJøbJX›R"Jö°‰éL#+:`–E…ë :u(<½Éw/È”iõÀàµ{’Ó h“¢¶pý)MåÖæ!Ðà¥?5PÀ —"yë \þ˜«ÑÁ BãhfƒÜ1pÁ J³»PÉwÕ½nv·«>>5hQ¢:[Žàp/¾æH Qó%Q·”ímºèpª™ŒyУPâÇ@ûIÐxŠ6ƒÄ 8x hj0Àà&¥q-lé¢Ü×*/°ékôx£3Ä /pƒÖp‡§!Á  V8Xþ*YáH ~ÊYA„xFÌÀƒëa¯ý® ƒýÚ@7jàZà=¤B1Z[¸ÔŸÕó 0@¾ò“Ïüå;¿ùоô£ïés'D¸îM¾ãþŠÁ¿ØGSX’›ñ`¿F€Aúׯþö³ÿýî?üÿúËÿþöÏ?þÛ¿_ Æ70A`wFÐ}2°à3“!©—Ƈ~ü÷Z4à7@8@Bà{8| ¸ x2æ÷Z¯wCp8ûu0p]È·‚C5ÈÇ‚¯5ƒ¯Å|4ˆƒ7hƒ5Ø‚$h@˜~:؃9ȃCx„38TD¸ƒ>¸„Nˆ„M…4xë—~1p1~·}6Ð}E<@‚'øZ1w7È‚„W{Qˆ|2À„7È|oˆ|qø†pøƒ@È„EØ‚J(…x؇Oh„€¸†‚˜‡„øZT¨~ €|10ZøwvW>ç·ìg{jh‰˜x‰0Іtxƒ˜~ýGYX7¨3`ø‰>èZ®¸‰°8~ç¦XhŠ>@ßÇ@x‚½øZA°‰~‡~G‘†´W†ûEÌèt±_ʈ‚Š8ÓXwA×h1€Û¨ÜøÐ8(ˆ†·HÑ8T´—|exEX8¹¸`Ègøƒõhˆ÷…9¸ùÈøhˆ{èúØ©~wC°ŽDàŽ‹xŒêçw®µ_mHØw~7Cp‚ÝèÛ8ÛøZ ’³Øwÿ¨†¯5†eH†7ȉ´(‹þ'x4@x„8@…F€AèwE°Ží¸B )‰yÌ׆,¸‚5ÉfH’-8‹ÙI‚³X‡9¨”!É؈‘‰h•'ˆ‘y>Hrx“5È“ @I ™BØ~wAƒ3@ƒ*$48{Äs”®…†>H”´È‚'È‚A(„˜÷h“®X“FP–ÇhŽ3™~¨hÈ7¯‹¯Å’”¹’+i‚H)‘h‰”d8‹yùÓ‘^ÙwˆŠô–³¸“5Ù“?†1 ‡6 x ‰]XŽ·X’N)‡É‡™E ŽéGVˆȧeèÓ*x,X†ŠÙŒÑØ‚cȚ수’8†„E`“³×‹ØIŒ )ž’I‹xƒž™ž*™–ì¹™i(˜%)œ8TFÕ‰]f‰Œ¤¹ŒôØ†ÑøŸâ¸ŽB‰‘ÌXý'–Òy9œ¹Œ^¹zs’c˜‘z’ýg†…y ÓI–ïèÉ(ŽÍˆ—ᨈÄ)ט•¹Ê¹ŒCÀŒµY¾˜(‰’ꉔxY”j82’1°–Ôéšù¹‡cH‡Cú†EJ†¼yƒ±Ù‰Ù‰qI‡Oú†1•H’{èJ‰žŸ©¥GŠ]E*xI ¦oØ£Žù†œ˜ƒ’‰¦ý‡{Q‰Yê¦Qé™C*§dˆ’a)„¿˜…£x˜vgŒÕ¥`ø—Lø™rX¨ÿ(‡´‡¨:iˆ‹º”p˜¨$؃pø˜c„ °šwa¨M¨¨p’rè© y‚Ÿ*ª¡Ú© ©l©ˆÈ÷——z³Õiwx–MêŸ'¸œ„'Ë—©[º“CjYj鸉h¥›È˜o¸–‘š¬t¨¬l™Äj¦Ã‚mº¥¢8§ux‘JHx9¤MÚ–£ØŽv7Çø—Bˆ¨’Jxr(¦(˜­îÊ›Ä|Ø)¯L8¯È7¤¿ØƒCŠ|öjžô*©´È›2ˆžÙ:Tð ‡)ù©§jAèªáº}Aà6à€„šª©ý'‡œø©5¨„ìú±=د"Ë„ø™úZ¯(²n¸ƒWZ‡û².³IÚ°d(а*®1Q®Ži“*©,h°‡´›*´4ˆ®={´F+¨HK´Äc´NË´K;´R[´ø¨„‰]7»}Ƹ$€Ê‹eZ‡¼¶++¶K¶`;¶h[¶†w¶jÛ¶ÚùZB°§¥X:;ƒº®d›’’*x’ª, ‡ó ‡TªˆtȆ…ë¯=H¥êx¤E «…KIš|—Š¦í—¥Ìg¹Ó8‡.«©>«¹hª°nø™@Ëwºªbkwt{%Q±Ê¹°{¸š»²}K»2+»¶»³ ³+©;™}›±ç ¸’:Vɰ‘¹ˆ©[†:{ƒé‹Î[©Ñ ·³£Ä£{¯e½¦X½c(£¯å½×½âû½cX¢IR¾Šø™æ«¾,¸£åÛ¾U¾¦©¾ó+¿§¡¾Û襯å¥ú+žù«¾íÀVX¾LÀ·w¬œ9dš;™µ8‘ŸeJ¦lI’B(xØ‹Áã¾B)ž„+ž(º¿Í)Â|›‚ç¥'¼'¬ŽûËÂ䉅-\w1œ-Œ}5Lû«„BÈ”-Ü„#‰ÀôH“BY†ËkŒgyˆcšE:…šÛw;£¥š©"é†Ã ˜oHƒÊJ{Yìw[ü¬Žº–èÈÅW,ÆgHÆŒê¨ËZÅSœ®vZ§nœ®Q¹B%y[šcjw›:{—k¼“ µœª¨£‹ª„ܹÜÇv˜»¸Ë»‹<ºŠ¼».û¶dÈ{y±@ùz;z6°±ýgcèÉ“9†©!ʼ¹Ÿ:ÁBL…c8f;•#ùÊQ,Ÿ,‡4`eØšBiœy ‰R­g®øø‘4šLÌ´‰À) ‘¬Ì-ÌÌäùÄXÇoœÄÑ|¤@LÍt(Í׬¤cx¥ÚüÍÖ ÎÕ<Îo™_« r;®> ’¨ ºëº·òŒ°óÏô|ÏöœÏ†²ø¼žúÜÁÿ,xýw¦À‹–Ø™’óZ›Î[‹µ±Š}ǨÊyƒBX•M˜†Žú·$锸Kª¸¬I8º’½®Cฆ{¹£°Ê§wç¡z v)Ž)‡°×‹f+¶J蔄Ó’žÍÂ-Ú)××ÇÔ$¹“–ýÜn„4-Þá¶—mÞúµD…[HÃäzÉzC©Häxß6Š”È-‘‘É’N9•whÎ ©ÅU94=,Ù}I¸ëÚ¯yÖiÝÖ)]áo]¤ÆIáu×8ÜÆx‹°¤ŠÀ¼ â$>â&¾Ï!þ‘'.â?¸ ÁÍØÇ¨·N£Xã5Þ²êçÓŸ¹ã:ÞãoÌã?îÓBüwîíˆCeɼ¨áîÖKnáM^§KMÇr˜áz«ÂÜÌ’©¤D0¤=Ê›Y§9(Õrª”*<£KJÇBHFð¼w!ÜT¸}4Ð}-hÖ>Ä@nçu~ç<Íxä~Þç€>äxüÞ0€ä%8àdhŠà9ƒú‹ÕÞ—|ÝŠ{Ýœ•>é–ŽÀ™.̘>T~M階é „ º7‰}wÚmX®°ç™N×nâмâ*îÆ´žâ¸^â¶ÞâÉ»£ “wwÔŽ=}Gxt™|Œ¨ÊnˆË^Ú†ØÉEËà“ÍÔþëõ ìœäq~^Ø[ÉÌ‚=éŸ>î€Mîœi×˃r=£k¹ÖLîîN>äm~…Ù]Üí<(š}™Úœ èzžçÿƒšê8©~^ˆ€<Уm¸_ü ‹'؆ÿ¬HÌæ]NÑ/Lžt1ØŸ~²ˆ  iíŸíþ:¯ }ƒ>]•yðþÞã¶ÚòÙÛ׸±p ·ô~˜èÇê×]ë,¾ó:ßó¹>å>¯ë<ëg޾-½NðõÙØ^Û£y‚ý÷‘{áÆ}¯L•ÈÇ$ ÃgHÃÎkÒ öO¾ÍÏL†IbíÜ×Îk~˜b ªn¹¨QŸûuÐ É‚U…OYƒ!Hžzo‘{h!(g(Š^oˆ¢ˆÃÑ[ôœ™¤ß=¦=¦Ã‹ÎhO®Ù„QþÕfŽõ[ÿ·ÛUÎJ®ø@}™Rš¥·ÙП¹ÛbHñ¾^ïq®öN¼qožRO×ûÊ÷ÌÇÆyÅ[_øÜ!öøîJnû=¼žJ‡$ݸWZ;¬w‘$7ÀúM“+¸—û’'x­k,Yÿ‘ú A’ÝŠ_ɰ¯ÕÞh?Ú;Õ¬h~~‰“îOƒþa]Cà•Æˆw€~F€<3ð+T*¬ç¼‘霑©µ‡ <ÛóJFbéE¦ou‡ žZUøÎÙ©G'¯³»€g¨Ùa@ X“Ôu〰8Ù!s%ÔÌUÔ€ðŠ¡À¨1àÌJЦÀ(7 \8Pz6ttu`¬3жÀh“LÝA¢BôÇ !°É„•5ày!¥6{Š€ Bì($ #T“’D.* óh›¡4“„" Ã*R. ¢Á5˜¬Ø Esƒb¨ ¶Á+¥åà´ƒqðêÁ<ÈsÌqtúAÐVmR/Š›ì- °£ ÐHðewq')vˆHÒR‹z¯÷T*+–8¡BT’Œ a&Ц”øØD£h3Ë˵×’•¤RÊ ô-1ÙeŽVg¢jžÈ$©¡¿´“xac²X†0öü¥æVËPª@Œ°Gm7Iø¶–T“ºk7)$õ¨*H‚¶Ó”ÛY0ô9&¼&WáY‹rvLR02d w#Cô¢Á™¥¬€ß‚•J’Y¬OX ¿ÖÎÒH%ˆ^ $„§òÕ84†o‰$Ãt–ÖØëDÌ*e3©:bˆ· ""$ˆרT߈‰J¡ŸÁ”ÜCLIj¨†ˆÅ°žBbqm!¨4T)¦:‰&Й+š¦¢âb…JJ"âÄš8¦ ¢!R?ñ.0BÇŽbŒ‹JˆN: ÀS'¨ "*ƒ‘Pˆ‘©uE¥ôVgr|Þ¬*⤠&š¡` Q%.±HÃavJGÜI MBB8†Ö";:N)¦>ˆtêf(4YCØ‘7³fLŽI­´r6š3‹5 Ævå]'rŒwLÂEFÀx}ÎÙÚJK–±œM@·‚œU.Db¨/IÄ“ÄF#º“ŒíjF3ºh͸UfÜL¯1zFÙø†¢ÛòŒ@Q"z+Џ¿TTRJê7J8ŒFŸ_³ò€°p-夨(Ä–ãRô;2'X—"PÝúS® ˜!/¥U™ÒZ‡<¦#ðH•byœEžn$}DõøÙ£‘j…~§ÿ¬2±$á£.´­;:2ø¨øJ£$€ÿ‘?F®(7 éãI3å,š¤þå:™}Ì…Ýñ=FH“÷ Iã„´àñ#‰Dó8£Òcˆ+1D–@¸—cêE5à‰²#d¼‚Š+Êåņˆ'$xœÀ>z¬á¸í_,g?’FFBé™,#8T{èHòH÷($A£}œ‘­ð/ÅÈaȤnÒ†¬’tqJŠÅÉ” d—ä’5"±$Y•˜4“eÒ"¦I éÕd›4IKm[E&"oÕƒìr‰Ú¡¹®¾– (’:ZG¤–ÀlÌI‡’&]7TV“T¢¢ÊA_«ïÄEª8);orLOìR¶6|µ)Q¡É㔟ÒSZÈjhã^£á1•›±Æ¡ÊUYYe©\i:¬UÊÊWI+U嬴•µ1YÝÊǸÒÌ;œ‡›h“Ñ€¢8þ$RCxRÒœ¡²˜“”åS<‚í. ÞÆœX¤¤ˆäMœMH¦ÊQÉæìÑ4Ë‘ Ñ*‚Ëv /¥•lO¤2¨¡Ëm™¯0h#C.î¶Ñ!$LV~|lÜ!<|-/Ę˜Nþ²'B½wiÉáÀŒj7±L)€Îh›xåSZjî’Tn¥h¨*ëÓıÆü4f$\NUò°UCÀ™Dæ$™|,_-ÄR6=Ý9×ÑìeŽF>ø­Tån<ŒÃª?^©œYÑK«qîòHa$ùcRªI]‹öD• ÔB_iŒ„0ªÇm¢ùì‰å³'¶*ôy>A+4gDà2Æ×wù.XÛ³ŸÕSjJ@ãÄ9û$óŸ©ÒwЯ%@k"íŸ51ç%@†V¿ý¬h§+BN™¨Ùäì…§nv +êh;qçw$om1)rÎÇ •¾• ú€Ô°´}­·¨ì|¥ M…ºò2‚@²X{jælZK¾ˆ49;·t=OÒžÛˆ´)NÜ“2 ^$| ô³VOÀDCà ‚.¼$îøDË¢m¢UÔBQ=„E»èÍ¢DfÂIF;9èkr™égm¡ø©š Ó’’k=ʪ& H9Å&›ƒ°rªE;JºN"m‡û0Y©Ì$a #æf*gŠëx‰´(Ù ¡"sSe Mùç4½¦qšjSÎÙ‹rRÌI؇v ÄzÉöÙý¼˜¥ÓÅÈNc,›h“Ñ4x:é©=•œ÷4žÖS™Ú„Øì\!Eq6™?UÚ¬j©,5¨´Ôp¶,„:K*à”h~¢&¯KI=)Z„ÂhsR®AË%ß ³¦Ñ‘VÃQ(†, }šIÉŠ„zRY:¢l{—ò")Ç,ɰ¶bê§ô'æmP(¸êî’Y{§ø4¨êÓ|ºOÉæ<ªE5©Õ¥ŠTóé-ƒßô5®Ê{*MRÀQQÞ!ž•¢gô$A‚ï0q1¿CŸDæ­T&-r’ ´ÊG™êPmª•꨾չªTá*]uªuõ®ÚÕ¼ZT£ª0ü«Í-k–A]¥ÜQ*ÒYS%Þ¤Üé[”r¤aÂô°Ó`4Y£i„ڦؔ™RÓÍšY¥i6å¬ÄójÖÎêL?k $†6µ¢ºš´–Äíú? f €}2BP_Ô'‰«o®¿µÁ%PŠ[MçÓÔŸÍÓkîÆr3…"‡R†jϱ*Öææ8Á¡ZõƒÅ1ªÎw :Ogè´£3½ŠNÑ™àÎk„¤œxª-Æ×;J6Ÿb8K ö˜P³©÷rÆUªˆßÇr®ÖR^ÚGUøø fûåRoíQw™d~„Lù1GúVùéh¤A-Ë¥ÝG9m3[ÞcTW¡½AŽzn—’¼Gêj¹cx˜–DÁ=FYÌ€’ÐÿŒa¬S2®a~%ã…ŠŒW¸srð­e©`8ÅÞÞEcjU÷Á@ª5µ YlË\̇P1°Kv'Ý]{Lµ a—MVÚTÎr ?U&Ž¡`¤B,P0r„­«{æ½Ï©,»…¨èï§T’Ô›yûwNCÞÂÛic“ Êííä"ŠÕ=Á£[OKðŒa'Ú³yÉmej¾¨UÑÖ3&fa!,SaJkR)Ê•zéÊ­´`æ*‰Ë‰f‘GºA *ŽRä‘f“5„¼WÈCqGéä鼕FâM(¯ŒÄtTU"Sr¾;­ù.+¶tsêϬhøê$2¬™5}ÏÜ„¶?íñ´3·¤<ø­JgîÀßÐ7ã¢Ø(DyÏwúÒm(¨ ½aê +'° ®Ã˜Økâ;¼‰=ãÖaª2?ÆhûlI± þÃkübâ‡~ qªJ,©*I·O¦| 0èx‘5Ïà«"1ÿmhð¬]`ŒÈå˜þÀ¼I8+ȵ¶”±LXË?cô©1:JÍ/raã$-IØ&êØxGiãaŽI’(ºi$)A¾tŒÒ\‹d‰_ )M¤x¼æ1äËr(ÍV`*e«D°™ºFþ¸ßÄÇü8`Òˆ> !á>œ÷@d™ª³JTXv¤x±D¢7rI1>¬ë†ÈÜÉkc>3,1+/–SŸšYÔ%ŽA›R‡1Kv‰.ù#®ô5erG¬É’‚$|¼†f"©Øâ)RòË@¯èúGϳEñÍ05;e0 †G7€òÂÙº•Œ/•báV%ÒaéÛ™oæÊÊ‘ å¢WÑhâAÊíPÞõÇ);ˆOq[FÅ'íµ,KL—[£]Fˆx•J8T‡yñ1%mM ;í •’BR¸ãV’®]9¥FEž–cnVÍj}OÆ%‹¤0¶Œ°?F®><²T–jx=È)ÅÚ„õb/’…Ê{‰• m²+´êÓ‰½@]KY6¬¤Å°i.½ô;]0󴛥—PÒÊ¿yY¹•˜ØÞ²qfËÈy-¯åºÌ¤°&sŽËx9:ÏKL¥óHNµ;Ñz¹wP㨿ŽB¶±¨§î3´ŠBZ×[J§Âƃ@U‘]Vàí\¹ùÀâó&êw×…´X!’(–D "É«7‘„ÌWl^.²Ûɤ,„JbpÓ±çsWî¾]`ËÂg÷Ü=& …Ý’¤ƒÇW· Ñ&&µ~Óg1M<9ÍED”f°k^†’Žá©Ÿ<éÄzÓ~Vayú^¡ü¤bÒþrNÙô. Ë!Cëëžjñ@_ç9†ž4jsÒ×ì0­²¡¢½(U`³ÐÂì"qd öb»4gªh +jQ-tdȰXZ"¿3a¦N0Ô Üî‰=K$ñly»m¥æï–&c\úK/Gg%e¡4õýG`xxQ97«¤’€.ÒiO嶺¦²P-¬ÇHÉû.¬ªÉÒ¬ <Éø¨*‘#F•ƒô3¶*ÁÁ10:aGŠc5.ƒJKÒíåf¼Ìæ­t!"œ.;Ѩק‚¯;Nš.+3÷éÖ u?Ÿ’³\q}ʰOŒ -ƒŒg,¶qÝeíu{Ø}ÖåmìJëO—¡osÃ.Q°í¾h tú>øýµ‰³º^V8oA"¼‚è¼5­Ð’‡Ü„}s÷Š´5QͼȢî]ˆ½¾Úõ:¯™d¡ÁtÞ“l¯ŒoÙ½z¤õpßÔʽªW-±å£¸ëÐÖ ±ÝêÄJ™—O ƒÍ®èå-•wçüîóØœ‰Lǧs]ÙÒ[ÚÚqwj Jж ’Cê;+¤“FB™=ÿ[0ò¹Si+U¤}͙ޓ?öG$ZDǧ$Mxƒ6‰®lœ«¶Ù6ÚÖ¶4ÕèÒTæNŠ½Ñ”ÝMûÛŽ:¥Eš ¾l÷7³U±.UûE$"ë÷ÜuÅt³»ÆëY§íµí¬å²]ÃÐr÷ªò¬=Þt÷ü†Ø8ì:3 }¹0¤|V95, n‹ë‚ìÎk±Y7Dó¶-e¿ÃwÀ= i@ËëЧnKá´žmjûK/¾‹;w¾u†úB/K¨¥EôÀjAîËCÊźtQFm&yNÚ-T··vŸJé„òàrí³SmëNÐÀû<ïj×]¯¿óüIâ;T§Áp; 5$Txj(ëÕž”€©–òL}òN=H®šˆŠ>ÍiD %¶_pR¥RÞíˆy“6ÏTüX±ZÄËñu^Ž}ò^ÙDJJøû~w%žžU{Ãw7n1Ø·ãèg_zØ¢›$YÝž¸xâþYfÛl{_–††la è“ñr± Ë\»ÕÞL²i=?%&¸œ5bI†+RÍ«â˜íãz ‰÷ý¾µQšå*˜.xn?^%ã˜eOff±¯_i>É€®Ø«=Ähíèù,æ¢Ðý–—Ji¯5MM›F1®ò>L<Ü€†yD“Ž$ç:ÑŽ#ÌÆ„üÖáú[í'pù 5΂WŸ—H8_2)±·“;QÓeR‰\Çñ¥j|øˆo ?‡PŸ:Q¿›—á¬OÑnæt/Fx DwGÝä<•'ñ4¿Û¨½Låº:EéV*eŸ;MÌ4ÊCùv,ʾR”ƒòOš J9+'å«Ü•ËòUŽŠb¹-Wå¸|uÎò\nÎ íÄ´ )˜ñ-TŸŒÑ"RjÖ1)óíÔ¢)7AËü*påM¤…“ÂÕ0 ’åD§s{¢»‘ÚòõfÂgPcò1•)”HqÀÎT3ƒc;OKàœ.XS-rM’d,prëÉœ8|e\,ÖÏSÖºÜeª s$G;k0Ô Ý©2%ß–ß }¹q­Èê eµdR– ù1Ǥí¢a\…Jô·sƒõÎM”]çʾƕÞ+[ºÃT±q¥¡t'YC•®%R;Ñq¹üÙ³­oš`ÓÕ'âÅú€ÒT•X-ÆEþJ‘Z³ ĉ/(–²©ƒk`ÍlÜò“'bu²Z#VÇ£ÓzuUÖÇ:µ무¬×QÞÕ³ú2Å·áùÆõ²hR…1Ý€ÊÑ\•,`9™!~ {lšÀeÇu«Ô€dv0!_HxÆl.³½Ìž¡¬t޽˜y'õÀÈÑûSòìœü$ö«Ø¸yºuC¾<}DÇT ؤ®`‰<Ék˜¡Yd;ØKd³cœlYÀÄþð­ DMhö±«¡È~=[e¯äÈ]Zö]uf ìì’]ÙAé¾Î§»u¯î+d3/Çø¹sþ­ÁjÏÛÞÔñîE)UHç¦wóN××»{oï4p´«wºžÊ³Ó>Ÿïåý½ç÷€¤ßñ»gïù¾xÃà'gÃT¾a Øn‘Olšp‘ ·Kx8á…à ¬ðþ¶kx ŸÝ…à,ä ~'éÌÝ·(u—éÝøÄ#D¿â[ü¼dñ/¾Å§\oâk X¿ñº~¦œ×a`î>Ê‹òKúNi!ÒDοʼT¬ÙOUÀÕ·f±œS©øé‰ "•ˆS~- +3¨ ´ÍkùŽ8àöÐFA±5™æüg¤žq¾i‚Òáþ˜ö<4Ê©ÐhÍ˵@!o>,ô8àÐK\[äç ‘jôÏõ˜BHºæ#}¥'¿ýS+K›J7½ ¸¿l¸Xê,(þF5´|½·1*9¥r>†oÛn󕾦Ϣ55½Ôª„·þºÝúouë__¯Ï¨Ø›¤1ëæMç­—šÇ~û ¸ìÙѲ¹,wFr´$Èr·%t¯öN“£½(›È ½)h¢ˆ•þu»NÉSB}å*í£¼}÷5¹|÷êðŠ¥uÌ®;#hC‡–)SÞU×Xz1’ñý÷"µíëRƵ}ÐS>“ðq^°JŠv’1êe†2&ÊÙ£\5áJNdŠÛfWð((“€_×{|+ŠÞ]|Çî4žä_÷”Oߊþ|ô[~’ú£’"ý—«ô…¾Ó—\¾éCý§_ô«¾Ô·úÝØ[y9áªÅòº´õ1~ÀDÚ-'DßÅ}™®wºö×¾L䣊SSîÁô~΢¾Üç–ÚRz ƒ ߯‰~]ÒÏyŽÑT#DçÈwðð¯ÜŒ*ìÍld:RÆ}3©=úÙq­élp¿ÖÊÔÌ/VK£åšÙ25bÛ{2*&9Œ ÞOSÕ#PÄš Š{¾Ll?¿Þ—·kø+8¤¶BæD€¦ó~¶òàÄÑ?©)¯ãÙ  §ØG ó ÚJšö"­*é”4ù ºàÎn£ûGœ´ªìâV–X$Ú‰læÕPDIkѸO·!1ψ#®µSS”ýäõq7ÜýÇ *ƒ Ô3¸ BƒÒ Bg š";JQTƒ4/§3H ~ƒÓ`8 ‚ƒã 8ø 6[å`:X O Ýײ²Qlɇœ#ð"ö–cB Æ&g˜CÅ&cÕ-È ¦‚¶`@X „!AøZIþàV´ Z,æ s¨ Æœkñ¼1CÒÔ3ÔF©&kBÕQaØÔ2;uTF˜jC)ýgBý"h‚…€ˆš¡CÔÉDòß6„ þNL”Hæ`Nhx¸Q:ai$îd6¡øUÑ„ÑSî÷½>œ ú‡n‚ž EI @“– hÄЃکÓètMüàDu©HS¡–kô &…ê(ø6…ä”ïµ;W› Ø…8o\Ü¢cµd*‹l"›@NþÖ·Ug1P¤`Xû}@Bˆ”›”AÝÉC·Ù;°I’t}lñ×Iõ^UmôÕANŽ!d9_QeØ \†1›¢JsoNB‚óY;P`B( „áCbÿ„±àh8>ú("A57S Æ¤¼EnMåS¦àKo ¾Ä â+:ÆIR¤at5ÚcRk½\3ß$øRnÜläE`È_`ôòÜ1W¢ßx-¦N/dºd‡ðÔ‚Á‚°ÑX¥ Pµ"hØØI¿ÍyÈô%$ËŸªæÕÄ&V+3„4äúQøöaO„~´¹”>Ú1XPvM`ÜJT‚T‡ÅR"‰¨9%7%hŠoÒiMô!9ôù•CÖ]ès¥¼sá™8§¸P|ŽO §R3 Q[ÅqSØE…ΰ„ƒA|ƒÿ¨oANPt™é`bg$oŸ5ÈXA{ø`.dI\/×ÒƒÉ8,W–†ü-vSw· B>@ÝÍi3–˜dQ1G{ÝY„tEµOÙ× ­[­T¹$­[`â&~‰bb™Xi‰^"×d&ª‰db›È&¾‰[bª•&Ɖn"'Ήx"š¨'F&¢d´'މSYn˜ÊÉFŠ ´AÀì´"¸Z^è=M€CÎX#nhÞÓ"¨(±L°¡¬>6F–wÔ)¶BŸbidÒŠ£\fD™á\Ó*E“©K™`O¹ÔsàMg݉O‚‘œøêa?øeªP1pÙvvÍØ5³_0DdÅD’Tð$ñy0R²Xä)<Ì\¢Ø%’Ž3F-M}SÓ„™)VvГÁLÛâPGáy‹ÝŒéAS"ZdÎAF¬bAE‡ìHƒQ=W!ÅPÒh´éÕ8ªŸY”rÍLh"¨H/bˆñVÌd¡‹dJ«²¥HZ¬Á.mZ–YÂÕ/j‹É z47$Ô^µÊäFE>”–1u²Y•í(º 2¤(úEQcÄÍybÏU±U*‘Œü"ƒã˜3‰‘¬¨~¸Œ£"„ö&!£¬˜Fùtxˆ³"̘IL“W#Ùˆ²‹“Tº^Qðæ$…[¯Ë´4Í€FSW¸%ïÑ. ‘•Ê}xk_}×*>F(cÖx2ڊꙺhú}‚_wÊ…oˉd %Š~‹háLÎÜÕQFVâT/ºŠì˸Ù8º(ï‰%8f×6Ú!pcobÎ!)§b5ã(Úq“ ª¤ßð‹"Ƀˆ—Œ‰Qº¨ 1FJ˜¤Ò7y.æœ÷e*>›ã|4Y)þÐd™%F cÈèz`Ì!Ö¨×ÙŠWPÎu½ŠZSfdÕC7íè9ŽMäȤQޏbß$ÓI8¿#—Ó%rŠG´Ðm;É'ICÈc¤à hDÀa3hKÞ/Ö(2Ÿ¿ÆÏé^«×AÒÚ G$Ñ‚•4&µ–C¦¸0Œ¿£zÔ•IáÌš´.>†(ãŠeã @$ãü…*Ù…‘§0‰ŽÄ#ÿ8%΃£S8∇‘5@^ŽXã@ <ì”ÊÔ7‹Ñÿ˜-ýcÞ˜?’U‡£ë•Aòl¸#É82_õcª—+Å'æœ\ΨB+ÍÅ%c’‘³Â?™G¿#•ÇYñ¢ÞX™4Ê‹ "= sHÝOuƒÉFüÔrD–H=c–Å;†‹§£œ(ABFKä ÙB:‘ªbªXPqu¨bê(ïE‘Wä)EZ‘U¤S(™!‘’ã¸ÈE‚‘G¤™Df‘µùD6‡Xd‰‹­ŽdcL$'~x—£ÙF’‘v¤™Eš…l¤éF–‘Md9F‚6]b9H’[äùGBFDÔiF†‘ˆ$©H⑱%)HN’fd‘(¾S?äêh‰^«£2 Òcòàq[{‘G"…‘/’DÔfù‘¬¤+)Kž³$,YFªˆƒd+IKî’¶¤.éGX¼d.YK “Á$&¹)“Ã$2YLƒˤA"™i’Ðd†¨±#’ÝÞ­’Œ¤:æ|÷iÎ8súž©¤–ñ‹ŽºˆK†‘G$éIGdá(9ŽÀ¤¼×+ uód÷XOÊ“Xc÷ØÍŒ‘êdHµÉdž˜¼³AòŽ"eØd6)6ê‘ûž9 =òΪDe68i‹±U¾È;”¥8yQ¢~eÅDEr”e@YRŠ”J%UL’™Ý˜¥t”mOT2NÆ”Š$ÁˆQù“‰™Ô8ä‚Ç#دh’•b 7JJäJÞѵ$JJ R)FÑ‘ÐÒ}Õ/¾T! ¨ RU ˆ„€E”sŒ¾Ç€é{f AIV¥eq c¶QŠ•%Yi™•Z™$™\3Ó ™O6m%&É:Æ•è¤-ùV.F6äù@–‘w¥;õ7Ö•ne®”W–r¥]iXŽ‘}ã`ÉW–…e`™¬L•Å– YjG{#ey}ÐÈК³"G¥v &I¥”DŠŠU˜âäYFý˸‡H3º£Ø§2%Dä–üÙ.öÝ[F&a_ûbÔ6\îÔªbA®eÒx™3ØËÈ8X:adÏT[Þ8)åb¤;æ– dàØó}s Ë^™{ä•ôV\Y…PFKJ€,¢JWèH:FEà¤÷™KáLn´ÒX4™"d (A½—Œ ço±™V&)X]É™!åœyÖ™xf¼¢/Ú™v œig¶™q¢šÙ3V”V&1Hd¥K§bHø ™ -ÁWSÝ#eŸ Q,Q“ÄTè²R•%›¥è5WM]oõëxuÝ–ÛÔ-a5N$‰f“½d2ÉLÚ’HPsèj®‰‰#—3=ñlçŒWÊ8W˜^'¥-˜Ú"~ÖšIAÑ€µíIH¢LÈf†™lVIËæšx&j˜Ðf³Y'‰MÙ§,•}˜R ‚%>I7¦hjãhE™€>eéH^:… ày î•Ç sizêXЧ")h¦za&¡yjš¥õ‰}jŸÓç“Y}Š×g÷¹}‚Ÿ7Xùé-" t…5®…õHLEŠð§ù~ŽŸágöI}ΟâgþiÖŸÜçþùë|Ÿü'þéêŸýg €ÒŸ(J~BEXTä@KÛ’(y gÐIX$™KÁɽ§c-%MJw¥ŠÖH4å$<Êë!f!®…¢oQ!˜ûøû1CÞ›…4®O/(Òø&‰‹"·(3Ý 3̤ƒbK>h”ƒ ¡Aè ~þ Gètržš=¨ûØ„ò ;(…vˆÇË…Z¡R(J…N¡Hè© 3ñOXè0”1&Îc‚Ç‹žóèk.(1ɢL•³Ù½Çfz]X‚ÊW)hv‚ BlÊ.†‹Ý¢º…‚B‚hjˆILf!Šˆ.¢Šh#zúe¡èC䈊‹‡è$:ÿ•¡­céÙ‹˜3jÎÑ Ò`ç#¹vÖZ¢‘’Õ‘™|EM<—™ƒI#Ý›è&œÙQš.ïeq2‹Â›´(”‹ê‹·è- ‹@йYöáKÃh•O/*!eH Î8•›Eʉ¤­=‹F¦£èMý”W¢Ý2ÙGÑÀ™I¢Èçø9}ª™€f¹7gY|fœygÖ¢êhŸ©‹¶£ðè**ª£å¨DCŽŠ£öguÕTŠJ¹ÓŽ$_ÉÙ‰`\=™Ûݯ£%:™VfÊ™A– i–é^™ZfDúÚR&ò¢—IF*DÇ(d~znèsáq’“ÍÚÇ“ÈSkÎ)Ä‚š¤ø!JÊÉI4šš”è’¢œógËWjB¤ iLšÞ¤ eNÙ¤:)Lz}ö——æSˆ¼Á<[ fœ|¡­`Vœ©’úµÓHjãIt“ÍQ}K‡IKBœ^¦&›YfYi#UHY*}%~$Сd‘LWÉ9dVå T5=N%ó…Ñ‘FÕULð‰>— Zc—’=xéƒí¥³"‡áRgÝ´ù?S#Ö>g5Š]'bêuæJŠicŠvŽ[g¹—oI¦fyÄ·‰›•ifê[‘9«V !bš>’Kª¤à¦N¢ˆ]™1ÐrTp>š«©jÚОf¦%›>¢ƒ($Z›Þ¦‰(mZ‰ê¦Œ(o*›‚£t“$ê›§”ho:vˆyá™tÊxGOÉ¢_yJuÇRé™z™'Ú‚üšSá_âB6QGÞð˜Ýévúä¥LŽ&åø2Ý /Sš 8Œ'ÀÒ- 9rÝ’…ѦR—3Áؘ¿â0…ŸÞqÈçôX¦pTÑ÷§ˆ¨·á•É‚"¬[>¤HzX ]%7É«è˜ptà ?‡m9¼§Å(8%S|£‰.ÂLü"hä2ЍžØU÷9Þ\Ða[f‰ýŠZS¶F± ^åµ{q'3j/b’Ð¥ÄsNYÞc0Yt,¤oé*êLI”ø¡ò‹åÜÈ8꤅ʤ°Qx|¹¤34áCÈÑB)’ÿfÑCoæ)­ã#å€þ%Ö雸pORãŠÅ<ª©7X³Qž<›9 cïè²â2™-";„Ö¤~K M™{ê“w›Á½£:c™"¡Ö'ó¤6Cê›Å¥¼×¨H}#Þ$ybõ¢’J ް%×6ª\»£PVãFýQÇzN`4çùÈ“‘JžÑï$Ó½d“j©1A) &;øÏ5±{¤-ûƒ º?¡ ¯ê«öªÀª¯Ê©Ö#Á*ü“ár7»o*´7Óð‰AYÙL;Kм³"éyc‰QËŠ¿æ¯áfŸköåÅBöå"eÃI¯@l=kÒÞBŒ \¦f)ÉÛì±P±X:S%#VÚWƒ¡ÂlinPð¬ëåå«hdW³¨µÍGPkÔµeNO+ÌÄ&ê+‹ALMZÍØîµøíŒËºø2‰¦Ì”¤¸¶ nƒÖÈøiŒ.k›Ú0kºBD¥¡)ϧÝî¶\!G' BL‡ 𘄺£níQꊺÜîÁÐŒºÄÉc"\%¯®«»åȺ°î¬‹”(:·n´êþlhUM~3×εY‰RòëÞBÃîÚxºÆ.¶Æî¶ž¤v™¹Ú£cËh$Ó.Xë×DµÛ¶Kø5¾J6â×Ì&z îú5-â‰Rw7ÞËd“î&$ënL ×`{ †ú‘È»'†Š RP?Yp¢‘ºÛ­q¢6åy!eÉZ(kð.>oã²½6oëð>¼ Ä»+‚.ŸloGÆ\ºÔS虀¹/m~{ïqS)ÏñBÜþ·ã­CÜ2·â­a;ÝJCcª§E@U¹ûäØc¯E”ògͲì´¯™yÅ+VÌ[ð:¼oÐ;ñ&¼B/ÃÛøð±FoÑËÔê$Koû±`]§f#’˜O¡’³B2>#ð–$,Xa®“ÛÛ®wæ¢`B.µ&Å13öžý„ÇŽ8¿m{˜‘U~.…&÷ž»vŒR÷†NÏU¥äaàn¡ë†BC¯ä¼øy‰hE/ѳ°njÒÒ„Oz‘ÍŠÅ.$,üÚ]†½_L*¹/=6‹„+~–hlNbƒ\«äÈç[¢ljk¬Kà™¾¥oðƤÁ¶«/êËúš¼¦/+û¦~ü.§ÛmuŠrS· ¥¼É­s Þ–¼'/ïûû‚:Äoð‹ø¾(¯Ð"’IjòØn5óÏßAÅ&»ÿi:”ì¶µõ?"ì»ÜïöëýîºHIh[wغã/¾£ˆ@^„ú«‘¨¿ J¢Gíâò®ÿ¿ï¯X+ÿÎ"8 ÞAÚjeéÚ‘Ô¾ÊjM‚è»,Û:º/ýt Á‡|e¬bí2å2±Ÿ«VÛø²u`­ó‹ |Äjö‹‡pu”¢3TŠ:»Sª™ {¼ a üØŒ;VÚå‚Lal-|Öj9am ,Ö€¯ï Úúª¾©/´ÒÍ~³wÁ,^£V’ç˶ªk&ü´ž-ŸÙ\/Á(µÝ|È*Îjwt-‘«õz“)b$-…xŠus Ùßü:‚#­pˆy¶|ØŒ‰™ ¢<+>\ð|[DfÏr³z¼Öo}»I°ì›ïÁ,\xâÁ}p ;Ávp1"³=6l«Ø±Ç>d¨€"œ×›é¼Ö­ÙCd8+éº?nT-Ìõp¥[¦/Eø(Ú1SG¦¬%Á>/["^d¼:_ÈPZ!ÿ)ÂÃhŽgå²ìGnáâ4…Šà唈de[Ò«Û¾@¯*œÆ(DbSÕ”¯„Š·Ö$“¿H¿Ì‹È#Ó>ŠÔŸ–€¡¾‘n.,CMŽqoÓd1–IÑJ’Ò†Á+NÄŒŽ(m: ¬YD# Qkd0ªéWeÁ´wÚЋô¾I/á«ÏÃV R¨´\‰0Õ +ÕL±þî2„Fö|š\ÕU[]¢lÏ¢„ °Ö‹¥…r,ïÇž€ã°5wN”% ©§Ù¹1> –{¹2 ŒÌKÍ̬W®Ìkƒ½SK<°V‚0-|8õRÂ6 S{¸-Ä NÌó04˜ÞP·]ÀQZ#É @¿ÜmH%À.0¶º­˜µ6 ÿ[üÅqí È{8b±$R ›xÌ“6œ»ìÂñ§ÙÄw5*ç Ó¶´‰@µMY,›Å¶*ó¼X-;‹±X÷<Ãu¬Èc¹4‚+í_iÒN‰^f[ƒg¹*qJlåš°`;"™=ØÇãU›f‹¶ƒ™´‡P/BŸàEô[â¯<’1Š#;(ÐêGêéê=ÏO;r·3 Ýñ¥á»šÝhÕ ¦1#¤ª#a‹Eóôî `åßd%V¨ÜŽë‡ÐµˆŒÚOu'[oÌä2»›p• Ç®¤Ë|$?űVl3ºA«Ãj$šoDƒ` ]‘wqu([ž‹¤hÇ.ž»·"¸nx ÇHWTÛ“Ççñ®Ù¿¾Ã®pϸ£.4vQ·<íD»þ”æ±X *¨0ZìŸÅòXL„¸Ål±©£7¬"ÃiŽ[-d¾°#*ÖÇÊq<‚f’2—Ã{ü&Ç­¹ÃT<Ìb…tüp)¬‹@o>œÉF2?üÕ¤½ŠUq)¢Ãë°¾WÉq*'¬%“%Öïå#ÿ2¸Œši6]ÑýÔ(=M¯lH‹ˆ©Ãì°•Ì&§ZX²AtÙ…–8ƒ6<¾w–…ÅzÈÙ6…ô©ªÐ¾iZ.zÄpžÆOÂñt.5®äðvÓ&gÉoò(j‘NÊNç£|%[Ê‘ò¥ìz͹,J– œÆ&”óôqôÒñÑ¢1ò+U–à°ElßþSU;ðxH€ŸÚ;gY„©OI|RÈ¥8“ͤ—äŒt(ÂÉŒaíuÜRÕˆ©‡¸é…iNÔ6ÓMUÎêéMç˜ÔËI7!W%&s>£G—O 5]Y"Õ[ZSâÒÈÐ.ÍbD’ÔxÖÍ©â>†uþ°¢gøÍT%#Ì÷º©|eÊß"vt‘ c²ŒtBGñüÄMyMÊ‘\I Õ—tÐ)÷½Tÿôf„WgÒ¬œ±kQ)zšOD^@pJíéžP5;Í`Y.Û 5 Ì”žþ‘ B(n’¢‘—‹ÑòŠk‹Ñ"­­1©´Ù2ߥ¶léÒÐ'1Sæ&¯Ô˜úM €5råÔ¯ulSËÖîâNzžÕcîÈ"”w0X\ç$ËH½~'®É”’eÆôjç4ÙžÕŸdøžÊT_‘yÙó«%žÒ6ï^íöè_¦L¦•º=K2c71tzæ%M¨Á7™&—“•×2[Oæhò[a9K)GÖ€*’XÒõOê[Oe2eˆLO9”žnµ@-W+™ÙK±Ki]í)ARš–]í)qÓPŃ[1ÇÊ{`·x,òÄó6Ó®õ+•D%PøSñ¼;?Œ!PkÝü5¿RU„ZÎ×Rµ¢Æ‰•ÒU&,7ÊRWsÌÔ3IªñbåØ\¶ŒmåóÓV:b”QˆiãøØï£ Ó9Ö‹Or‰Šláq§ÐäèdN!ì–)ÍNJÒ†\×¹ãdFS6“7|9#’å¤ze¦«WMêÅü>’Ë™ ­Bµ–¯x5·c²k½÷W©ÙÄ›­«ø-îutÀ#„‡?ÿÃa*ŽÄÁÞ±´ƒI&¹¢q"yä™[ÒWMh Ú2ç2 YÓ ´·¤$}N”ãè)×Á‘Œ²"hÚíµL¶C§!Õ¦mÜHD¤æôΡvrDjg åR¡ìª‰âÑ mNÑ·ú­'YÛ #Ñ2t‹Qýã{¢{=Š  VõCüÜl]j?4]k'¡Ösðß‘BŸ€sçɵd?ÛZ#Øè5†kKj´5nÒöü ‘J‹'³€œ\îbËe¿FÚ(5Þ:¾,'¶¸þqU­;•Å+IÞ‘[k!ƒ×šg¿‘4ï¬M'¶–û¦ˆY<±§}*œi‰ÀÁ½9±žx"‹áÏ÷e×ÉŠ6Üx"1ú’FÜmÏÓ‰f¢‰÷})SiÜ÷Æ ‘j‰Â)Æ}t²ÎwשpKÔ ·…IŠr7Ä 'Z´þ¶—9~x>݇wÇ‘“ÉìgÓÛ8_m÷_þ—^"j'>ÜéŸî9r e)×ÉCÍBéÔ*m?ž½åGñh¸ Pì(Ø®›±#Æx?óHcdu_bâæ×-vMÝÀrò2lH€ ÁN¥4j÷œh˜ G·òrŸSݸwKZ±sÞýá+µ¶œ-ËŒzrä‡DfYÝRám%BÙ(4Hg'–_s"â®\çÈ}¾šÝÖÓ¥u«´ö×=;ê׌×]-~˜ô¦æÝJ…ÝdbCv«‰¦7å}'v[b¤m*›°7³{Ç‘ÁØýŒ1u@æÎw 9‹/ǵkwžìf÷k›…ÁvlmÑvJcUGeÛO®£oµP™ÎÌÉõ“övÒ·üˆQg‹©Î·#‘õäj'9¸v¢ŒýàHþaâÜÛ‘Ðdq¯Þx"뎯ã&ì׎ÏÞÓ¦:þŽËÞ¶â<ÞtÊ㯷ÛJfÓ‰«tšÈ9Zeù¦Ò¹x]˜C·@^'yÁûöቜr¨øö$ŒggÙ 8ØùµŽ5È[‘ÆSÎ[l…¦ÅÖÞ\.FÒG‡Iñ7C’ïe6"e$m…~é’·äúŒ<á´ ~ -6y‰8“?NP ~yØ‘d¼“O@KñP)yšUWÏ‹_’WXÌF!uBD#t&W8ÑG¤Òâ´²¦Hâ(¾·â{K9jæÜâbüû-ÆÉS·ÿC‹ñüTšƒ›¥ùé]]œ)XÄ–/0𹬛‹Š³9™2›“ ¥y‹“›?Db-°Ö.™Ø_-™›‡‹ŸDõù±9¯ùÈeûçéö-”y’w ,öÝ Žk›ïõ+šªz£êì8kÅ.Rª§LiZjš(wû=NGÏÌ3¾´3IPX’õ}>WÓG6™ˆ!~©URÚ%{ÏçïÔ}^MOÒòù~nI«‰²â{þjö¤Ísnž¯ßÈèxž|_H­6A‹<%W *N6^ª)#4oÏÙxüÙSÚ‡fr¸Fãq·dê ­Ýt“ÑÍÑm¬h7Ïi¢ûãÆîÆÊ¢“èúæn¢#φ·šóòuöx<ÎŽ›,g§´‰Žçè?z´ézû謷e¹)”ÎJFª{ë*ëLw›˜²³.^£/ãV¬ÉÜz—â#ú4^kJã‹÷–î¢wé¯ÛŠÞ¥Ç܈öü¹qÖàY÷ýle{—ï)U}‚šÉøþŒ‹âô¨™Þо‰ææõùŒsMèž>tWå{ú‰N# êŽ e8”eÀõy²!€î-êåÝ‘%p¾Ò‹jkøiaÙÇŸ,ÞÉ×ßçÝbUæPc]â°ùng\)ë„}–w•x{ß\³¥âˆ"m­~  ´Ïÿàè±0ÆŸç€úÓBx`P&‹Åxå\èý<ÛPC¹6÷&ÙIšá™}™‹ñµ~ƨ­ˆ§“bB/ˆ§„Ü™K%q·®ƒëëÓ ö­{Ù4©Dª®O¤JB:}£ëðºM¯g'_dºÎ®Ïë7)¾ÞP®ç£»ž¯Ëë%ÒEZG.ëCJöÜšÀ*Ê&þ ÍÎÜ8w4é‰9›˜Fì¹ÐD±[¦'ÍÅ®>ÎeûÄî±ç‰{žÐYì;Ä^²û‰!ûó±Ÿì$;Èβgì‰i¹.%ÆØèYfä<-2íš Ö(ÝM¥Î¨<™4êEÑÒsǰ©¬LÄ ¥Pq¬ý,iàI7–Ît±Ÿ3÷å…Ó.]8Ö~RÖ[»§LQP{{µ9hʶW¦þx›Lˆ+0–©@["§Ê¸§S*׆dŠ$c—“½ª«ìÔ3õÍ$JáVL% Ü(~>¤þúôù@æì$£s¥ºg˜é,½hFcßlðJƒÔÚOÐiÀË™Ÿ¥xjßf®»ûHÝÁtqvçë§"«Ëíúª”—j1`¤;srS¦z_/M›ûYÃmÃ%Õî/FÏå¤Ú6þB”ÑuÙ*%©–çJÍWÒf¨ÑˆÆ'"häËzJãŽ|3FdcuÌndv™WÎÛh^Î<¶êJ‹lÖÛ4.ŽºÃýBYv^Îat$úUÄN’hJ9YM‰ O¨n<®É"ó9º4‘b±ÕÍüŽ`×o‰Q0¶Ÿ¤Å©þ[$6‚}›ê“*wiCvz¸~mãÞ³á3| ÿ÷¤îpx ˆÓðú»ÆøãÖßÐ&B†cè¬çI|ê…šÓ8=L§9Çtÿ×n±I`ŸcLÞÕfü@ÓÂô8­^¡W럽ü×0€£ÕE§4a¶ù‹ÔOŒaS$C>Àø÷¤¿ñ.ÊMQ#"qüQÛñu<Íw~-ÅÑ“§#ʧi‡=`òT]2º-)@@èúÁ2òŠü´$31ò¼!/Éò7pW÷[2X5ÞT˜ p„sÞ,4`†ç|7Óq]ІRå4+zBR1¯åñõ/V›ŒÏÖ˜À2䚨ÅraRú*$«¬ñzL°‰‹+Më¹sHËkÛ5’õ½Lóó’3ªÌ3óݽ„˜Ðv#‹ùÖe Ó’{ .ò¢ÐéÈ/ò|8Îóß|˜ ÉwóaTÉX !ÑÔ|%w°8¬MrrÚ$Ÿ|Q$‰òåc®n)RúÓ:XN%Ñ•KEf¶~›Ü!?xs’ (,oQ«x$w:Ë U8w05Ån<©§§À|*~F‚Y}µÎ ºwí˜[ •Ûö"”×>kÛQ#Iü·§ˆÑIŸ| ºKßÒ«Ï1=M?ÓÏÏ0ýM¿v‘Ö-i¢=SG/M}Ñ·Øî ПPI+s€îX9Íi>õN}Tk:È‘PcíIe˜ PH¼q×'~3)$‰÷Bšz¤Ú>7z¾‘¯œm«½€l½CÔ«¶döé"(ט¨|V ¸7þaÄïQÿG–v§ÐËò±ü_ïÒ-T‚ýD½`kJ3·WSO)?©’c’?å|=£·„Äœz©Òdÿ0š™ˆæÞÉE_ösSxµÙ‡C˜}e¯Ù[ö =g_ÚÛ1 áNwúJÊR=/ÝóŽ'õU;ÒóhVu£'íη²NPycßÛ?ž¼}pïÙ÷¾}p_Ü[,È}§õ'ED oͤÉd4‘£(ÝwChP—ýB_÷ôôÚë=éÑ~4}G÷ÑòwG{÷â=xoÞ³RåýwïS£Ê6p%@ …ìç®…¥"ù¢Hz—ø=`ÿ ï÷wüßSØËñz<ïÒñ—Æ.õ yšçòŸ‚JU ÿ½ ¥BcÐkŒ ¥AKû¥É»`~#…^Ó@Wë[®öS•UiÕgwR1†Ý‰ªúÓsÏün/ýö"q/ãÃøÆýŒ_ãÓøÅ=ãïø9¾Ü7ìÊœrÊÛ·“mxÊoøe|e-@b–÷Ê.õ½Q!®ˆ•ýB&¾òè±§½½úø¼§—Ò–OÝ}U¼¨æ§Kc¾g?æ7¥”˜Ÿæ“ùk>šï•³ùzæ\ý ÉùæïÙ«ßyŽ`ëù`þšŸÚÛÁmߦ‡Ï ë6Õc2`ô IàÄÐYÞ…# 'fÓ9=öÞdOá)—~fÞŸöŸ}§OÚ{ú£}¨¯é‹ö¡•iêú˜ýŸÏ •žÂº‚èçŒÓ#'UÎ mëçoIt=]×YuÞ<ÄØÈÃG[ú=B±Á~±OìC±»þus%åús4µg¹ÑÒçíå´7};ÂÑvÛP Hs¶½í)fzš§ €­`£ªà<©‡Èóè>jOΫûéþ©<îå6„þí3F %oGŠ›s€ßßëûÿ=ŸMþJÿ?¦Bìb±>•ÙòƽˆL ¨ÀÔ%ôƒ6m•Þ·Íê}zoñ“÷p´U¼äï[Mµë6(Ö&kn£Öẩ;(¿žé—°C×µ¤\+/E;}\ûH¾ ò{|7¿|ûÊPNy;Â÷‹ÔYª™oíƒüGŒëëÆ‚bœë'ˆºÏÏÛ©Ó®Ó—ô2½IoÓKý(ýÔ ’ÂXÑÈd‹hiÖÿ4ùO¡{߇8APPR·(M2ì!Îc¢ú¦þ§ïö‹ú¤~Ü¿BY_¡}ÝßöÃýv?§ÿö“J1ë”w^!¹•ôñR6"héê“"xÃæ³ç­ÒM˜àhèÌÈHä9gÊ·U< >z6j«Ï7»T¡–FŸ$è=ç´d~ÿ|ÒÝs‹¨ñ‡ÉP˜s' ̉ŸäÛÞ°½ÚÛoÑ×MYŽP£™Ä {D ¾¢ R˜oÖ!§`U~ú50&™¯ò;­CpM·ëÂlÐõ® ýÏňaâ›g ” Ëxw¾íý"ÏÉI'ª=•-âRé{6‡M+; FßúM:·uC@þ]È”ûþg]´ôkœ}* ÉÒØáÿïÈ®;FB»“KNYÁ¦8áHu,¯GÚÚÇ€—z¬!­¿KœÚƒÚ3Y«Ê˨ ›ðŒäˆAùÛL)ž@G˜?ñ\Í.øfÇèüIBÝ2Iùˆô·PÁÃ5ôfy|©5YPl˜ÍâÙDˆÌ3›J*äââûmdÿV:Š J!-h–À¨° )ÄÿCjr\3u!f–Ö°þ ZâT´é“¡gª€XÀ9Fð§³JÚFˆÒVB›Áðæ xԚˀh@2  Ì 8lŠ“?v£p yÂí’H4Š’FP ÷ºb‚3ÁÁÕÀBa– eŸlXéJ‘ô.‚ÀBàÐB-¶ ñ¹sÌp•—sÆ®B…¡°ð¾ Â(]‰ÀL`ÐbŸƒ 4~±4‡ÀP`'Pè'K‚åNr'ƒ´9à¶¦Š•š±xègüÂŒXË—ÆŒ1‘¿œJlMš0 pøä¾vÂ-D  ÚÊhÓÛy ‹6ÃÀôÌÑÆÈ ,"ŸÇÀh`@Âd²í‚B›6 1GkcÛU«zU³p .äg1Ã9Á"Ì$o 6& Ò61i#R8EÆG&0œÑ2AÄ©Y÷3QꢺÄ"WÔ=ˆvµ ù^È!ÌZØšJ¥r©`Ç #â €,Bh›™Tä5ŒM„uA âühñ_Ú¼¬ „H±ÙxE´!3½ "Múá(•)OÌ+Ø7 ]È­€E$jO¼'DË–L vË æ#€;Ud&¨ Ár€jüœC2dëuŒhS¤`©˜—˳g SDµl)ˆ‚µ ýJ+xÙÀ þ8 C?ŒöIJçS“ûˆ ¾ßJAŽ ÁQf "$œ“5ÇM`’Ö~™h "æ‚qÁÚ„b¢-ÈtEhˆ+ Ö.¸q އ&AóÃCBÿÈEì"€hÀbÅMâîÑPÂ?´z\ D(ŠoqDÑzD3DŸ!‘m “†ð ŽJf‚UÁáA$2Ð1 ‰ˆhnÁ  Xå< ja6Ùµ ä¥ˆgüÐs]EŽ5a@g‚Œe(ƒ^€hpKÈÁRErðx±DÜ0•ƒÐÁžLÖ…µÀñÇ©7»ŽˆUUg±Ñ—‰¼°o!œª„°f¦„•Ƀ~°Ì z ÃÐQ]_vƒaˆvΧÌwñè¼ð=j3zKJ‹…3IISl¯10œ†ê¶ú°Ö%¡ ÿæ<Á·`®õôx/ó›O`ðsf¤ØqÐUaâ¡V«t³ÕŠ€ÙÍœJ´°Ú%&fáäñ˜%(ά!„ˆ[Çyiùøt3 6WCkÞÑœ‰n„PŇoC ¡ÄaÆ '°0^Ž:D"S‡8Ý4fÿŒß…dbʘô”òf6²EF3äóæð³L38,äè—ÍèB>¾„í›BM»ÜÕиg6ÖY˜²0ØôÂCSÁàÖ¹gÌ1»ÍKA#ê°psŒü:íïàc§Ã’aËàRÊŒ0FÏ&(6¼B}ùH©õÃâ@Á‘¡)9 ¡ƒÇÁè sP}%¬² d¤ oÜ¥þq ðOªzÂfUF®.ô &|6mÉ”¨ ’ظ­(D€ƒt½ zè)1Dë,¢Бõ„à%q« “()ð„ïÁŽÔ¢ÊÚhá,Bnù>Ùüö<®'ˆLˆ(Áö¸´ÔÙPId©©KÚ²• H8†¼2Ñ—Vâ0úR‹±ZÙbL0ò¼.{ipœ™9aÐ"‰±3ŒÜjm’9\!t/‡‡ÃÊ!áP!‚òàŽè)":«Ž‚Hdb^¡¶ZÕ1ÀJ íEÎ`1ò¢Ô1®np)³á#è4ñ¹‚Õ€~‡¾Ãà!¦äBÝÒUO¦ô£J€<“Ú‡ðÃôaüP‘>DŽwŒ·ñˆÜêmŸx‰T>PPÏwG€ç°Î 7ã:ŒÀ¦F1„ñ™˜ÿŠ0÷A#ŒòÅÔD{`^Lüx0—/˜ñ ²A¬Ãœ)¨HÄ̰Â>8¼!"`äVyñ!ÒˆT7ù"yR)<ÈÉØj†ø”R >‰0 Œ`±‚ÈAì!NÇÄu’ÒåŒã!þˆ›ÑZu†Å–+DÀ3lb#ÔED'˜§w)«•1¢€‹£Œo#Ìq©™C(> I ža.$óZ&†‡n0:H¦x8›™øÎk<¹^ LŠ¡3£k=¦6p™v‡f-ý27$[Ðþ¶ ³š—ã;s³ò[ôÜ.¡¯ÌVf‘È8l$šü‰D«•ÄCtHI”¿PQ*‰“D°•<…‘øHì$2_8‰ŸDGb(Ñ“ÈÕ«%€`Ô!¶Ïë¶ÓÀ¶A‡¯D\á–8KŒ%Öo‰®D\â–DŠ"ªÈýøeêR‚ ,Ø KM˜ˆ!&:#„‰k2c¢2™XL<ò§¢!@ øKòE)±9OL%ÊRçœÓN>HˉDð‡A˜bL0±Â™E„•ž†´ÎNjЇ˜CDÂô²¦3ë‚!¢H³ÄP]\1ˆnÝ£‹‘Žv»‡ÃÇa&Q—ØJ”œä EY™Ø_‡€¨ŒÒ¾Áv…&ÂáÕ)žQ¬(>/ŠfÄŒb ‘Ž0JXU…éˆüUžô¢×ÙjL¯C3%ñPYÈüwÑ^+n.EgLö¢`·–ðújŠÒ¹„5F§hx0¢P vŠ×¡DMñ®ñ¬ˆil %‰6DM1©XTd*Öç’¾åaÃã©8U\¾qžŠWE«¢¹gy(Ã(*ÊqŠŠ˜¯"¥†A ƒCøf¸¥•·D&ï0û븄Ši >Pì'vhÏÐêÕ_|œaɃ±WŒIh$p/ÒÜKlÂÓ±<´BóŠK ¾Å>F±Ø[‡‹àáE!G²¨XT‹>܈óÄôhy¸ç9h<§/+Îbº-qY Å!žúA'R áÛ8*È2žª³ÕãP…e˜±ÊT q¿žLw‰ëc“é-ò#›ßâ6Ç·¸Í‰#ÞŸ?†‹Fmqzqæ8 ¦Òr4¯E_GesÐêm°fž2²›¢³³óbÁ2ŠCËáâP¼¸Qt:š7?*7ЊM‰¸6ÒÄ›ˆëÅ%"|‘½è6:ƒ\F¤ˆl˜Ó”»í,¥|ñÉ`ÎÅó¢ãd5:|-šk1ëµî¢ñË&D„Ÿ‘U²TüăȂqÂxNÊÜbtX ÆëG гQMjHúŽ/â TÇ „ŸùîŒ6 u¾éÍ[Pð‘ÓÀZ)À…& ÒL»â1ÓÂ8X0dÎ`V¬h_!ËÍÔ 2¹n :…$vYŒ=\¬/òK+°ÿq]\VÅKŠ…¼F‹XV@<ìTt¸ßc7£eÔ2FÀpE²¥0c@)±$б‚JeFÊ®ˆ´fJ33Ê–²3$ïŽEƪ²‰jŽÈ=‡Ù˜ FÈg¬!ú÷ŒÆñáMÏ(h 4ÄB# qÑ8>|"òqJ‰XŒôðåC.‚ Ù‹"2ÖÒ&îõHL!…ˆ²‚Q!1!úLÜŸáßâ½!~_Ò?$Ì &ÔÙY'*_wÇ—®õ‚„y,öD"&t©fÅçCA!Ù`vÈF0a$„o8ÛÙcp§(Î>̛Ѩ†I|:[ĉ±ºa¶‘3 ‰Åt/` óŠªP,ÜØ½ eFŽŠ\ÂÅsTäúˆ WE釯!&Þ˜X„Ì” ݉¥ ˜Ç£lˆÆ¹.|rÐ8 ¸cÏóÑèPã3jaÊ(íw¨p<¥ùLö©´Ù…Ê¥UÓ‰˜Wü-dÌÆÆE*%àBà³£ #ÜvŠ,‡¹ÑëóÐ~ˆ9H˜¡ÉIcàø‡9M¸ÁÚˆ›KLuûS5ÔÉ…“WµäÓ<,ÁœCqa¸¡hvH®ÙíMEŽ)¾ÄÆÅ*1J²KQ) 9‹$7ÅÁâgb>|öìb@œ ãô"pÔ¨Š¨É!qœÒϼ„޳ZÅÄUq#´£êO¨vﱉ—ÿULéX®à„ØIîŽÜ¼#Þqïø”ˆPðÿŽzÇÀ#àï¸ÌAÝŒ ‰Ã)X Â’‰hFdÇ‚'ÈŒDD6#ÙŠÈ´…$ce„¼©#škÕšUÄD3ÿØRà)i>ÙÒf©´)GŠÅÈ‘çHècÓfɶHÚ¤#ß‘‡Œc塃 â†!êcމ7dò!Ù¹ÁCú#÷T®†Yr ùìCþNf,"H AGŽ1â@_ŽÂẊÁ kÑâ!‘Œ?¶úI°·—Ù…‡Aq±y%$ÑU¡æcç†U¶ñ“]^ÓGëcÔâùx„Y~©´:>iYòQ y êÆÂ?'¹˜Šq6Áb¼þð°ÖÁzX’I”<@–eb@Éž?æ#Q\ÚIP%z€™²¨$°æ‹'ã’‰ ùY©H×ÃoÂÑ]š|IÈ”‘ÑHg¤åÈ‚ Z jÂh˜%ZĪƵðWü+¡Þ$q;§‘–†4Aš žPOú<ä›#þ }ƒ¨á­ 箚´ýÅøÇ{FŠ7:‰¡b’9›IÎÿüo-s!H$ [@‹Ë$’i™tºÐba¼×­ !©2ƒê¾@8Ó­¼¦±„Úô‚?D’ÆØäÌj^‘å@R¸œÖ½ó åË0ÓY”:J²LáAA’ø]À éZMÂã…œˆ œ x̘Wc­Ô‰^Ô$Ò6Œb‰–£÷Á„³Õ1:xjˆ‚Éwb;–ÂâhÐ >àd+`såˆC\éw2”†&DJÁÄ)~\#@ 0¢Ô¦›† \ )È+È.Çñ)P3êÑÃØä¾¦ÒH›üÞØ&ã«"™nõ5…Œ /”í™’íc²xÛø[¨°l’˜°ùصI'±±ÐÇÜ — ˜ÐÅÒêr(”H_0PÎÜâ$ BXQƒ¤ÉU‘üƒ`ް‰0>JY­4LîÕ¦‚#ý(ÅTY·°Ý¤j@’â…9‚ÂF~© R‡0²×ûæ¨9´>Ü;ÑSÏÄ·Flì9÷FèºÒÖ¤›£12m±S`']JÕÑ­(±ôo±‹Bæ\w£…uÉ»Ä\ Ÿ!ƒK~#ˆ!v®LÉ|¢Þ-³Lö,ºÒöm7§¤ 1˜Ä5:¥ª„Ó³q™Ä±²”l‘ºG‡‚DÊQTÆ€Jj ¤ ¤ò¶5\ò/‰î¦+MÊ?Ðt‰8½ =*Ý2Ä “Çy·n'%L\•jJÍÓûH—¯6¦o÷ÒÓàmÒÆªØUf~¨Å\‡6@j̃N¹%:¥lÄTÕ1Y¥4áŽOÙ· @)ÅωØY´º1p5Y[®J2cSeï¶•^$é ‰;u8â/q™6'z*ªÝŒdn6Ýû_9Šäf¯:.J‘dÊ(Å+curªÙ J5Ä"ãU+ݯý–dìC‰Où¯6€aÅ8%aW ùW*”€x>ª.™8µbR¬(ž²o¨ Êá(Ôv³›iý N†‰>Uo,åÔ7é2)‹N–È¢õÝ| tDzÔà!î^–ÜÊ ÓNm–nQø”ÒÊ!…¿¢Û7$Çĸt¨òrÚtö, ¢°ä©d[î/e"° ¬:gñÀ‚ í°+p ¬ôŒ€ @µð)x ¼È ÀÛá@ðà0ð Œ)€¨ #PQ¤ÈTK8ÀÙò/à'¼$1B `oIP ¸Pa,@  ·LjÄü0ƒœ€EÓbVèÔmÀY`p‰QˆPU  `@æ‹0]ø1 ìSxB @ €°4R‰àœ@ÈäÊ~…ÎÂkÀ x è)2 ) º<<´”š3@ à €˜Œn€Èì²? $ Ô.1—n>AïÀ(/}—>†Ñ%ñ²sÉd¸l/ø‚©Àò°+HÄaÑ¥är{™ðÀ.mÝCNÀviH(Øÿ¦€¡s‰ ¤@ýýGíR- dPìR!Ë% à  ?Hü-—È#ÀÀ \20QjÀÀ>h X0—L & ÂT2ø Ì—Kô¥T+¸êkÂ%ýaƒéð`"0­ ¾’hÀ!'(,Ì-Ëô…Ô}. ÄÞÁ߃Á¹L0a½Œµ€uédx$—bõåÝá‹I¼d^žx—LÉÀ 36pÀDEˆ"˜F%C  ¬øb ˜9Ë¥  à^.ür€À@~y].™—Î%àRp » (´N(€"S’ɼ¤dF2å—’ÌÎ¥%s“¹¾”dŽ.3™—ÌJf's”ùÉœdŽ2E™h€Ã(““)ÊDe^25™§ÌK¦ó‘)Ç„]>BdpÌÈevaŽI.\.'—°Ë’ÀåRLЀ¸/‡—~Þ¥ï’)¾4˜.u)€4À"spÙ¹LÞÛKó¥kÁr©€e /Y™—ÌR&,³•Ê g¾2Ë™àLOæ93¹¼Teb2M™äLN¦8ËTg®2G™ˆýA—iËt@ü÷—(€ì‚ ÐËüb Ê>ûå³^H^Â.ALXf`IʤhŠ2ñÌwæ8“žéʼgf4;šðLަ9Ó£éÎÌhÎ3Ù™ Í&;ó¤YϬhf2Kš"M{fH“™Ï|dF.šßï¡4`»Ì.Ìš¾Ìæ¥Z¡  ph^!¾˜î<ðr¢¹/phŽ.ÇÔL®á¤@ÇLt3Gš-M–æEÓ¤iÑŒij4½š)M°&Vsœ Ó”gv5WšgM&Dr‰Ài>B€˜ €ž¦H¨iдXh ÁÌ/¦f_@ È/‰—ÍÝåör_f^5%™¬KN¦Js”‰ÑkŠ5eš‹M®¦GÓ«©Õ e–5¿š(MÇff²ùØTkr3©˜(€ŸfN ,¹^fjtÍËeæÒ¨Y¸\B5™9Lße °ÇŒ /™~Mæeé’y¹c8fÒ üš„ˆ¦W3²IϬl¢5'›ÇMÎåeS²9ÓÌj¦5™›ÄMy¦;sÁbÕmþ4£#aÅB®àeþ ~™øƒ¼æår@p`0Q±Mîåp!È l™ÛLáæ=–Ýti67¡›Mqær³¸ùÜäo"7›’ÌÄg3riÀ„1Ìà˜J†fór‰Àfþ-Í—’×&6st9ØXÚ;‚Cæ43˜ùÙ \2%B—Ëäf}Ó¸ à¼o†3Ý™õͰ¦ˆ³³ÙwÐgÆ1Q¨ÍÑæîáW Å¼iR›§Ë5Ár 2ßlm¢z›¶M¢f€ ¤È/™ÂËÀåà2< ß4]š5ÿ›øÍÍ&f³¥‰ÊDqR6û›ONg–3ÅyâÄrâ3á6M'ó«@ÃØn¶5‡ 7NÚåå2à1ø*oØå ár™)ØqR-†&§Š“Ê©Ùäsr69™Í?§ŸsÊùÑìs:­ÌËf„“­is: HM†€@“ ùÝD®Ìkf6S¼‰8% ä—€†ËsàÎy{hr–2÷œ‡NBç•ÊYÜ´r®8¥œ,Í6Du3ryptÂ\qÍ3§O“ÒiǼ zÚN§§s=êÔqŽ:™†M#,Sš)å¬rz9Q«N-§}3ÅéÎ$qf4c³N@­»yëdA\/%sM5§¥ó*àdø_*59œ—Ëaçy3Ôiçd‚”—Ì<§¡3ÚÉåôdº:ÖNÿ¦´ÚÉÊœnæ9Ùš9[çÖ .`»w¢6Å—ÎüA Üɽ5±™INFæ€þpñ}žQN*gµîIüì|?3Ÿ—ÌD¶ó; ð¬;<ÏœÝM^'x“r‰úœ}¦jŸ·Ïܧ4S°é»¬à9-ž=ÏçÏé‰ù¼|’?ÏŸœO¦#séã}ê"Z PÏFçÔ“PàzÒ²—›…æåR7Ûd_ òŸË0Àú²ñIÛÐ èøÖyïäV@{ pÏ{gÈ´Y†¸b"B€ÎÐ&SÞ©ädª?¿˜@1Ád@€)¿4fö1QíËÑ¥5ó }pÂ7ךL·§T Ý‚¦à´Ì€fÀs´y… ä2C›iNÔ'0“õ‰°ª/mžCÍÁE@÷ þ”dN4Å ‹Ð1èÔ à€*BÏ ”Í2(,”šüün.='¡Œ¢+ÞŠòÔ„†79¡ÊLöåk`%`ä”f@ý ~Í—ïSÞ)zºB7Ÿ«Pôg;sª Eƒ^@!›—Mlg˜³ a÷¼M\/gQOç&õ©Ý^ÎØëK1Á13t÷LD¡›Ë „ž³ø¹ï&:í¡Ðhhú³üù ¥i‚9ÙšÜPJh5   Õ{úB©ŸL=¨ýÝûüwò>Ÿ¡Ñ(54J½|¶Bñ¡ýÐj¨¾sGú ˆŽ>õô&:í̉¦=•ŸÛÐ9æh“%ñ uÈ?¢èNþ€ `Ì´yæøš2Ðw',“ µ†ÖCešÐ}¨4Ô*Êö”…ÒB¿¢%ÎBGtމÀ¤@i1• Ìç4Óálxºh qNiæ·  M˜^v8/™3ÑTç34 j~ÖDIœC—êf‚Ó­é€Èñ4Ùš4€L¨s€ó”s.4•š’"Aü²s9üÒ¡o×ÿÓÝ©¥Šþ>ý¢WQ›èNt"Šü p:Doš„Ñ ÃÞãz™í…~1ŸPÍÍ%'ô=ð•Œò.G—•ѺhÔ@Ì|ŸÑ/¦N4#J-†Fù¢±Nyè>³­)ú,Œ>hœ(€Ä¨Ôõ¹ÚÌ><]›áÍÎ%m42çÄê袗ј(ï–‰¥‡²=_™>Ñòè_Tî‰à؆8ƒu‡ýåóŒ€/;—I€†@çùÈôpJ2á.!N'§F”’iqšG·¢–MŒhUt4šÜ‹FB™ WLêåó3Põä]EQùÑÅÀ~ô¨ÙýpB4'¢ Òá¨h”8ª uvv>Õ£ÒNͧ“èAZëD`+ £uÎQ'ó‹™!}8@;¤’Ì æ=9ê]‚E#¢ØP)‰T *ÏyÐp.>7œ$OÔ'Y‹IðT °.y™OR.)'tÙÇœ;¨ ¤ƒÌÎ%™”ú»œpn87i£í&[³:Èd^Êž róÒv ]LCiÔwÉà“B3µ£eE) @3`m€*l›(†îhŸRJUd24qžgÀê’½i0]Fä—ÒÎ¥MÁ˜äôk>5ï÷ÑM)ð’yù(*¼P×Ë6³s?àzÚž—jÌe&ÀÇ ÍäzÖÞ×Oõ%"›9Ñ,‡.39¥ÝO3© ôðð v®@µ¹ÒÀÂà ¿ôÔ ™£K(h窙Ø\Ž.O¥MÞæÚ€.E,ì‘ÏÎÀ…œM JŸÎj)4“yYÛä^Ê/O ~Íu© ”{ ì\_ ð¥²M`}é ½s¦Kï£ðËèe@UʼŒÖ—¨R”b*¤Q_Ž. ¦ùƒüç¢ÔŽ€Í´m’ êëËDæDš÷„—æ?O¦¶Ï«c€_ ø#NHy—PFfÇT ºé]æè—¦ËøA›ÓÚY_Ê@߇ófGàÊ*Í~ÊæªÒ‰físWŠÌ\–þ5í—ÕLhKejºä ˜ƒKÖeE `ù„fBMQáKybʽ¼þ.wXÀ˜)8jÚ. œÎÅaöyç„}†7g¦,S÷åáL *Å‚VLë¥gRì§Îôjª* €NX¢øiÌtXšÕtrAy¦ ÕÃY4 yã„„J.¡äÐ̨™©Æ¼`æI‡—ÎÌt)ïrQÊÈ ›j:œtÌÔëB ÊÖ ð.¥™NPÛ)!”Š…‹â ꥎS! ÝTÃi6–.¥™¹ËØ¿T Íì_*ÎQÑ>©1sZªÈ,˜æ.œGNü¦”)@¸b˜à˜L#ÀÎ@2Ðò\ÆÇ@ŸwÌë( €Ù0¸]î¶ Sååº4;Šp´OÿšÎÌýiý´Z2 V8峂ÞåáA*°ÞD™:5¦Q˜)¯hú» oM=§N~i[4 àÌ|.™SÌ)"hØ…Âr¥(S5fºtp(8f>/ÉýO)RŠx”Æ=¡øSó¥ÕnzppNý§¯réÐÔŽ ¿$›2/{;†ÒT¶IР57¡>N ª†óQJB-ÒLO¢‘Å€­ÔK ¾4]žTBÔMiì´‚ÕLjrM9¥ÔS2ªéò×ÙÐÌJ3%§‹ˆÜçD“ à% rv²™\€€üÒZú»´à5;—˜1Ãöryj+]œn/_ 9€5NJ.å¨0ý)ÌÈ%¹´Šêy´]®M9¡'Ð:ªS3€ÿT^J3› T *õ;@øŸJ3¥ÍûigáÚÿÜmÂM·—¢NE¦âáyj/m—5µ >%è´ýÿT l0ó£©8güRkÊ€`N `gKè“yI? Ÿ®M'š6Tö%­Ô^ C†ÊP×—b€•À†`}¹5f¾Kñ<?êõµ93­ÆLq¥¦KèðÒIà×|£ú6‹—(€i*c Õ3…¦:3I¨IÙ¥írª $(¢Ú5ã—ÌË9fÇ´ ª-íž¾S?©ÆÌO)÷’FàH˜fA?¦·Ò¨&?UÃ9M}`K—¹OGéìTÚ¹< &P—™ëKZ)üÒ{ù&X¤ÒHï©ÇÔņ™šyÌÙšS™—?ª5žêÛ”ÐSs›‡‡žÀD @à5]𰧦Ë׿è’ê=ÅmžSÕ˜ˆLQj7U~ÙL„ŠMY¡¼Ñøå2ӪȀâS3R×ËÅd`%`s².± ±Oôfäó)zm|ÒQçyTåfum*…¥²Så—5ÌCªÃ`y +¥ðK©ÀKN裔y©í ¶¨œRÞf ^0H€jMi"ÓÆgl@UŠOM]/±g€»* ` ÐÈübfl€€Ðà—–!¾˜êÊejàr©0§Ž.O›]Ò-@uTyQ•_U  FÕÎ¥+5ëùÛì¨JG—~…ËèntP9%]ŽB¥Õ÷@8Õº)0¦úH×K⥠šT]›Ê>)´Ï*“ótJ¹snJÝÁÔâ*Á´˜Ú¹Œ¦ K]ŸUùeé²s‰D §Ò/š[ëjv5Î93] ü?•—øÔ˜tô§še‰ ^pÕ )Ö4 z9õ©ŽBS©™Ñúéá1p°‚J5c†D*Ï&à”ª0›’ïçvusi]ÈvÆOó˜(€Ii§S‘©\=m²ÖR“¨Pð%ºUjÀ¨ž;;—eL{+¥ÕdºV]jnJë¥Õdéï²§ªIM™*/ùªÀN êáAÕÚmM¸fPG­z€iÀåz4í¢®Z§¥p\òuÛ†F«ëË”+÷y5…«šX]¨)ÖMkØ¢Ús%š’@9¦×Õ$k±udJáT]ÎL…¬`˜¬êsr*sE¡æLã¨îÒ—«"37Àµ"PÛ®Õ.êôqu”²1ùªiÖD©"“¾*]µ¦2ý¬SCë†y0h•¹æYÑ®o“ëå sº*˜n8/¨.Vó%¯´Pzx4ˆ ¶¨@‰)ÓUÒÞl­.JÉj gŒ5WÊ)5œF5—§…7§è5§jK5­Ê]I¨£¨!ÁÍ 3U|‚=+¨ÑTbfE5™i±®9­oU)R ;ªádh8S®aÕüˆaª:5€_—™¯Ó(ëÇUL€H€^Yª[ÖWjRup‰{½B(A;§™×¹«nš°¹œ™^N]¯ŠLÍÀz5~©hý¸šW»¨LTùeâÀœ Èô¼ê¨¨T•«ó5êÊm´ÚL•—†Dæ‚`:uÕ~†]ŸšŒ6À s¢©\åR™‡Ïîeo•¡:}m®ÞF ƒ«€•À¤z¹Ìê?‡—±Ñt*,U19¥`ý©VSEfLuκ`ÉbvMã¦3Uÿ«5ì S½À"V_¢ÝÕèåD`õªHmc† þˆèS@@3pý¬P\7—¸Wì„2ÕnÚq-žšCÅ©`ÖÍê­ÕÃúOݨ’[?¨Ì@3•uiFí’6`å·UÞhèËÊQ•j2aϰÑÌÃ5´ŠvíeBGK«ÅÕ )Cµ9ÑÜŒ@¯£Rh?þ Uµ~žam«,ÑÜêàr¢ùp¤U©ÓÏéåòÖZbm¡ºL³®;Økj­5¼‰{m°^/Ÿ¬ŽÑË¥‡aĪUµÂRJ#ŸÙK¼ë¢ô›€`ÝœªUï«T°jéUª™WÁªN /Ó_«àyùkø XL[®]Rv+DÐo‘Éh†¼¦jÓAj ri;¸ Må—«­õ ûv¥ºòK!P‘ØÏ*Ö3ºiý¤ú ^§ƒþg&•ú5‡¾N¡¯¥×+°Ó¡‰{­³~b«±XÒJg¤p\…ŒÊü§¢Wì%®€úª½œÊV« بËÔÆz3¥Ç:TË«JÔ.jkåjP€]ÏpÕ`(¸5kvž&@Û±¥VÒ% aàŠ~Í¡òK‘¤(#fF '°È ä1¥Z)&[ÓJúÍ’nIï˜ÂK”)˜4ÙhÝ“Tƒ¦ƒË4éSÁ)#²Á–D/—€ÓŽªå%°)½2Kœ»‚“( U‘‰ ¹Š_á—XQªú´”úHÃSm ÂT *ÙÀÀšc].aiŸðX+1³Óê8†\/‡¯m×",ªU¨9¸´|âaãœÌKpçO³«4UÊΦ²ìÓ×"·ZmlÞÀ®®TÁi3¶Û3õ?ÄA'¦Óƒf‘Àȹ|Õ´:4¥ÐK(ÃóÝzŠ˜¾WŸ­ˆÌRi–%V}ÁâLc°PÕ®¬T3 0/€Z`] ßÑ;'÷´»zÞœÁòU£Óדé;¦š6p8T§ÓPÂë3 z½Ì¤¾Vy­FÕ+èæÒÉŠ4]65Á¬¶ÖËÀøJ]…]ZWc®¢V2+¯•¤HÃþW¯«šËâ*ô´Ìšfí­rJ7±eTͬÜut¹8¡ÂLAû,ÒÔ"K›pMé¨:L¦ ’Ú MHV‡®×_Cá´æú½Ü°Ê6Õ˜ÕRl¶ê \íÚPw®Ù˯€Q–%:m5‡cs¥“V‹ÀöÔÑ:~%™’Ri©(ÓéÂ"VÚØ\ˆ.[ѳpPÛå¬ Ø™æNç–PÛ¥ v-{h#¸b'š§ÒUéqVJjþfo›Š4lr–ª¹båΚC3ª(€Nk…–XšxšÖQá—Ó[©s•«Œ•m®[_ œÙð¦óüºU¥ð.“œÖ;«rVÀ*wý–6i¦ŠÌN«Ñt°¹l¥Œ: V¥°XCJ´K*Cm½¶a=³\XÐ,àr"РV:}¨îìø`mZ¡ \ ®¨>Ú+ëpöÇY¤Ý^Ö6‘´éÐ ìf@5k/Å]ú6Ý›žTd&›VÖzHMÄJL—èØæ+ÔJ‡Õ•ºJ™ŸÔ/­‰Vš9yUc /_¥›×õåw–kº<•†ž±jÖó³ ›.¥Ózg]yÓµìkÓòù‚%˜†e9¬Ö(·”ƒ=¥º\ÁVkeÖ`JzÕpî^}›XÍi33{x˜ Ð^¢Œ×_*}–_ 9# |@)˜Ó fXµ¢jfÍ}NPçŸVÇ,˜µÕÆLé— 0+@µÛz£=€ÆPŦéÕŸ¶ ;¢ýÁv/Ý =°Þ,¼Ö·é×”´rNɦÕì,–uÜêr´î5ÅUÜj öw©AŰBQ¿˜ýÚ-³Õ5ÀÐ$ xMaŸÔR•ëT )@€}¶&l!¶qNßBí!<`»$׊Z¥™®Ùš«ü’1O¿"M©—YBì3ÇP`¨EÎ%[“ê¿DhPå›Py(ve¿”ØòZͬ2XËë¡Ö`j4õ²F> ¶¬S¦jo€%: ^†—¾…Ôõ2c[¢Ý\&9™¬ÓЯ~•`ZœõfZêÔC•Žš6È¡¦U'šÐ", TÛòÕ¸².)Es­öƒjt Ä2i—µeÔðæ)•ÖÀ´Ý¨ºl½¯¿K°+`@žúBµ#e!²MC TÂ:¸u›¢0¡©ÀK­A5ȉm °*2Í— €\+ÒtQºéTÝnu³¾…Äù•œÊ µ:h¥³ÃKê¬ Û+U˜Î]­¶²Í£ªÓtK»¾ì¾^K“´$Wìõ+Ðf›S)°±Ó­"óq+¨e‰êg­ÀÛ…*¢Õ€* -Û¶1_Û¥ˆaì:Ce]îUG¥ÄYÒí×s{Ë ­`‚TQ®QÙç)‚6; —ݵ/ͬÔ)¸v†ŠI­¡¾NSùå`u캠¹Úe ãÖË)ór"ºì§š^ç§àåq•ïp½¼¶¾Q»°Öxë,6È U¥£šgÏ©|Ún«ü+±Ÿnm¥¯Óö%¨´šºšýq*^5¯Ò[Üè ·:Ø4Ò¢LÛ¯ŽVߦ7Ë?µjÔ˜fZ?Au‘*ÁœTY©­3Wƒü×0b5Íji©šËÕõ)ºÖt ŠEáNCí²;ØÌ+Õ)«)4˜7a¥Õ¯-°Ö úG (ìSk±0Ûî-¡ÑŠ2%f>P§¬h€# ÁôqrPåœÌñÁùön°4 rÒÀ®šÛuj:ôRʽ„ÍigëM¿UU|9¨-¸<™¥;×3L¡°ê[à=œ__¥ÂKWj&Um;@u n¬ˆH]€þ Ç ‡šNÕ|WÖ&RS<;£âÊ>‰·3zË–­yÀ¯Z>çXË;çfvYË& «>pO¨qNømÓõðj?寯9©‘K=ëš³²ºMå6må®ÝÕò¬9tíúxÕRM¡ INÞec³ Ëte^Âqå¸ß×…+<ÐviFÕ : .—Y€¢íevÜÍ®n—l:-@Sª¬UÞF>£ ß„2išuA˺ÜÔVS½¶öK¶­B–[êeuh]i±TÍ¡)×5¬:²=o‚b} ĈBËÐ^%ÏþXO·”׋©{ ˜qõÝž^S¯KW•ëÃ6ö:¯©ÞoÓ¬×XëêQ€±ú!ãâZ ·¯Tƒí•N›§eÝs¹¼KŽD­æz+5Ü2q·&[„n?šfÝDi£šÔ[Œª»tçú:UÓV™—Üun5s{é¹åšNZÝ¡·TQé™´ôÐ[…j~`ã©]þª_3ˆI¨àîX™²݃nCwx»¯}²:Q%˜>ÔÕ§¼ó§kÏ Þ®Z·ŸÄÛ­+GvÒ ŠM¥~ˆ¨¬Ë¥(NÕÇ o}f*pÕ¨Lÿƒ™³ ›¾å^ögÕ©œÚ ­ý4_{ÍN4MºÕ—­A6¨ uÐöhŸ¶iV mEUwËj›Êfß—SY©þœ‹Q%ðnqµTë*V·DKÇ-‹ö(m—¨KÀ-årΙ¼³²J¯µóZ5­Ý4ªëýl¯PÇ _´ª† {MÒf»ÚÙWêæ¶KZÏõåŽfÜZ“,ÞãzyÇ…êºU™²á7À ƒyxàæiG—ŸNЭÄÓ}¹æ¶Dqº{Th¦Öôš.E½Z8w°ÎÕ«!7îz8Èß~1•NN']—®zÐMê¾D˲ èh"þºh-h^ë¦ýOoDÖ¡:ÀÅn/s˜YVÀ7±ê5Ýp-§ýO®n7­:¤Í°²wÏ›×ÖoiB÷·{×»ŽB¡ª\ìu§{ÞÔâŠu¦]Gí´UZ¡å«BFá¢MÛÃÃøVZU-êCçÈYΩMàÊeñÎkµ¸oÝ5ç uúÊ!íÜÞlG¥ÌT@37Ðø Æb[¹ÏÜó­Ì” +ªÞ:mOº?Ú`íÂÔ©«á$îžn©ºÑYOm­uaZz0ìþZ+¼Ü&ïZwtym}åR5˲’’w,pww{Tݨxï¹=^ûmf7Í{ä Ù U;¯@†¹ÁDà×z80]Jxe§UžH—kª‰mÃ6hAªÞÜ®,vÐ+Y½c"0u Û%t7Î)¼œÁ6v ¨ºÈ€ ~õ1TK-¼oÓÒl¤–v»Ö õv}» X…n ÕnV=Â]·¦ÓÐ!,5ÁP[S޼èTòjf7RÛB ›BZ Ï/à2û ^Jo·ôÛ’îÄÖ®z¢Í-4ŸšÓ ¦›WVê”%ðrKË46l+w!+ÔjBAG—›Þõ¥V•zý$ØÊ/×½nX+ëu}‰í½ç®o%­‚×3ï<ÕÖàÐt‘><÷©ƒMrÃÔ4ª‰çM¬æI¨![./¢÷ÇiºÝ»fu­ž±Ý/æN a@ðšjcy£¸^ô¦A·Þ«V ö"Y ¯¾ÕÄ) 4Ózäµá6{™®.ÒŸ9oÚÔÅ׎f»¼gW¯íU×Ê8ùv::Ì$i à0P€ à`N”lsJº’åã¶dÕ¤/Y3ì—”“Š']_Úd]±8Ù¨óõyÝ$ºØ`cN<(7¾‰aͤªS[´®Ï†BÜ5“ú¸MÝ*u•¹Lu. –™;§ ŽvÔ-j­W‘9ð+ð8Á® ÏWm¾Uk¼¬ÍÖE;—v‚ Ã=V-[8@˜9Á¡ißfî-õêÙ†m¦J3‰¹ÏU+ŒwÜk¢->0oX£æ\µ/ß¾yÎí¶æ.ý48À •©)÷]•’SA°¤_9À5öC?mý¾~ÿ †„Ù¯&•Õp>¼žR­‹û§Ÿ@ð‹4UHZ[·ÃËõåÀñ{¥a¼ð—×ËÈïr¯9Ѽ¦¢\Ý4×Âo “Q{-wŽ[Å Zþ,ô—S+@m8Q‰ LLÛeH óûÞÝüÞ/ó¸üÓ¶«-õÈIÍî‚æ¶K`¦ð’N{(  ŽW¾$Ö&ësÌû;…ær|i¨KZXì_SžÊP•ºze¶éÒ6§~¶:*ݦa!«žU¥í¸a=ð&P•Z>G¡¢ÙÄØ%p^MòVU§¼æZ쥶›Ûm­˜’`Q'c¦ÈÕ:úœ¥™rS°l[Òínô'€@µÍF][¥ÄY½«ÛÖJrU H3Q¹ßß)[³í*xuÌ&ίºYÅgéÕ Œ!eÜ6M­‘KB+#7ï*~EùpG®·_7,åÊÁuòºð¾›PÙ.x*6 §v—¶……-à²a+¥%mN,ƶ¶[*¸·q›ˆ÷JVǡ̑n WÂkíEÞ’M ¹R1î´ö {8Hÿ‚R»­«Þøå)•cÛðØú` ÊOKjR@Ž*çUŠêZS¨ `ºkªZíÍ‚BZ'¹¹Ë-7µÝ{Ï•éÚ¨‡^&ªduµÚ%}mR@ÛÀóØ\°ÁT²‹.®ÂJž-Ûqo:_»8-oöS›µÓ9ðÁ̾ÿžxëªÒ ®ËUë NÒBzs»ËUêîb¨UÎ0ùVD̪m×Rf_©•ÜŒ,ôÉÚhÇF§¨ùÖî)W· } WA5¥b`ö&wõÀ:~—^×›âáó-ø]ÐvíðÒ^A®KT0­qVîë'¨ÌP} ¥Mr.ÿ4M¼•í­ryšãVVìRÖ£Ûme9+À.a%m®ÔH[˜µ®/}|MÝ/;W‚‰îmËZy ·)׉À`5›0NåŸ>taÚMžnhצ:þ†Šy1Ä”]®©T6[¸Íók3£¾QE& >kø¼ ¬J[\búì €_ú¦H\ß²Ï\¹lj•K¼—§ÖEG—ÙïíÂézYºžzaÉ ŒâªöR¶éÿ½BX/ÀêÜâ­ ëvºîx GÙó°±u}dÕšŽ‰‘¬ÓŒn·•Il fã*N¹—*T¥èj÷ükü /¼ _,f„‡«álSo¨Øaªö´dëwÕ cHóª•ÎhêD˜yé'àqޝ-ܦ¬c8n:޽Ůš¯ÞRG«“µ [/ “Q㦄Pní¡7Kš½çRë­›Õ1‡uŒºcÿ:Œé°œPdñFUY UÝwW§¿Ír/pA™:Èl‹úˆÛ¸¦ÛwéòÔÐ[‹…ñžìŸÈÒ8o÷+Ítóþ‹¹¸3P8¯gwTj?5醎o¥ÉËFkû2 \>Œ÷S\CaU~ª›…ùþfá—¸Íïå2c ‘åtV`3©hcš-âSUëò¤&´]a¦ÒL¸qÉ•q,#¡nv}µüá´*»·Ì›å ÑŠUe›Pà,t7éÕ^2cæØÍ0¸Ü ¸^^V} šUÓ¥ÀNÚIe‰>¸­¼ûeYv$ýgVµ°ÐÕÀ€xøÃ»Ùåóžu¨]ç® sðpÀžL€ååÐv¬Z´»Šf‡¼PbÖk£U°«½è^vúqÏkçRÄ«ºüa".ÅÔL‡ë2u„ ?.!GAĬÖÎ0Ù•£º³å {¥ ä°pä’h›¾´’ngÈCÍš­ÿ— òðEÀF§¯(Wß1¤¯y®å岬»aÕo¦V„ü`ýÙÞ1Y¡ M¢­.uãÊàl Ë6!ÃÎÙ/f½·Y/}<Œwƒ­MÚkŠ˜ñIBöŽ¢Lg½cÝ 2 Û0#ÓgU¥ÌV°X|™‚…ªª‘íW!ò µs‰/eÆjS륺ÙÀf\Õºµ-fg­½l0î÷QœjxfRë¹Z¥-~öäkCÕ!3œ EÐfüRn©ôeúf~·‡_ÁwSê+%í[‚6Y²XR¬¯Þ”K“ÝúÞIi²^_C&ØM:öýb¾G×K éEàŠu¸r›P€'À h{! ‚R€ Àh+@w²55Á(+@ÑÖ*Y@|öVE³ù °ÈXåúµÍ·Bhg±•`*±,v€*þ•^2/š&aøhÀõÈ:¤¦a9z€÷ï#sƒé³58ŸƒR®ÃU 8 œ Œ×Èå¼¶ ÜžìWݯâØYlÞ¶oÌuU×R[ža-ê^Á0›-±ªˆ_µ¾Íɰ¤¶séd_ÊS™N8›îÕ;¿´)÷„Q›|døqQ•ë0þÉîl ÉT€r™„œª5ΆW‰¥€ß¯á(«f=Z“;Èä2y‰LB^#·EqƨO±üò´yãìÃòM¥çWòæ×JB†ª¶7y¬s€f±"§l4Ô[M¸ËÖIp·U­Ln(¢>ß›Ù]€( YË¥\ÆI÷ÉQWñöXR\U}êÂt+É€Krð36½ 7ý²‰É´^l*É­»¾œ›‚˼GÔ Ay³¯÷|+¬Ä(vt)VŽË†C;—[ éö˜·I¹¥æÒŒœa¶é¸Up‰ˆ…ž>~š1€ºrÓ5´¼UíDwŸ/Ü£ª¦4‘Ék†Î`ÂÎÚ«ë%¶šÚ7˜6wßÇêMEæã³ñY„-CH07¡Ö.º-<~-¬@Y¨u€×€R¶ SÈfNÈ—Q½rry7:…âžœµe3@ÜT%<ó4vò8¬Õ…úp@Õý,’6g9¡|e®)æ8»|2ý+‹N´¬ ù(h˜Zö|qƒÊ f«ƒY)\X½ìVh Ëß2¶‚úÃã6y‹M€;¦ïr0ˆ™–JéÇÀ΋ÀTÖ‰] qZ“1«äa‰A“€Ì޵®×— äÁe*b/0=^„€ÅMyçAs @y0ªR7/—W¸¯Ç4 OÅã˜÷˜:fýp ³ÉŒ`^.Ó[º@ëš/h83³Ì(€£ÁÉŒa2#@§Ìv訄d–`Ò?­µäWë*“áÜiƼøk¡°-Î"s™ÙЉf^ wð²ÓK‡i@ÎŒcÖp6-!˜>æ1j9É,ï$3™s˜hæ%€ØÔË,¹\˜>šG—?fæe_€Fü•ý&šo§a+3ùÌ,ïT3/ºÌíQ°Ÿ9Ìl:µ4·âIæ/¦šYz!5Ã~ƒ¿§æˆ‚Ãv9gV^¢™›RSt1¤Yä  vN PŸ¶f|)š¹ÆÊPÎâ1i¬uÑ)sòæù9gž¡¢™ïÌãeóå’Ú  lö™I´-YÔ€ÓÖìc(4§ƒÅÍ8àP+×Ô-çÔ6#B¸Í8f5@ùrY¾l¦^H}§ýÏ)­à âT™[z€\3iU(LD½vŠÌ[[æ%~A¦ ö•u.6ðÍdL³¼SÓÜp¶®Rü¤æÎåyt9i~ ø8mÍ~Ía‰y¨™§½î™¹¦nfÞ°Å™ ‚qάNLÑÌvwkÂkÖ1„SÛÍZ½/¦­™ pFpœ'¦Ò˜s°ùôKlÆ1Ë@UÎüfo3Õº€aµ5{›åàæ–³u•Ülmî\*µ8c "«ª9³Ê»D3¿œáÍ“æ(´ùàŒ(:/™¹Ì~Í"èåòèÌý:[œËþc36Óì,uÞÚþ›»oçöå`À! h>2w0ÑÌä?&;Ãúc®žJqµÍÿ̼3Ù˜ uFp ›ÒIsÿ¸ðÜèa¢™Íç1*¢ì\bhΙ7—hfõS`DZÀ]Þ¤—OfÀÛùÕ̶þrž»ûæ4óE€ö,‰µ—™´ Ò3Ár梖G´›·­(•áùbò†‚vЦØùÔ@k(H¿ ÜVÿrTsk,f-Gå— ¹ìá!¶¬_u˜Ö–aǶßß«’Sh(£ø¥Ð¾ëfAáËÄNE³$FÕ‹.$†»¤)W%'øj]­¡Òl™•Ú.ª’á!½lðXW—Ò[˧‡–kJ;îÈf3½³Öûia÷Õ»šþ¹R‚ޝÓÆ¬º“(ÌnUÙª®—¿¾&oXi;ø½ §kž›ÝŽê`)K•¢*”!ÑËVNèõx;¥Ž‚§-Ô¥]53³Q 1°êKý½½ãаm¹Íà5UÙ"m—çài¦dµT[XÕ÷t£©¾`¡ì¸8¬ª4­©Vxõ­Uciú‡k uÜ’OÓ¬ø aö(Uefv.C¨ ÐhXxés5_A¦ûÝD³šv©ÅÜ`>¦êCî {¹ÄËúPgŸ‹@¦ó áİÒQÃÏ5è% ñªV`¤U9Å«FY6zwO$a5—qÔ3Ò%À˜%¨ˆÕDT.N`1-p=ÁÀóéµ\ŠÁŠ…HÂæ ž±ÞÎË%@@Óœé¬ðáN§íàÌŠÆçXiΨârµª—¯ÐÈlý&ÖZ;­#¬iU°óD‚jM‹ÆZ­›Öe®õ§ºy‰¶~Z‡­e?Hªuÿ9F[«­ Ö^kï1¼àm]U`îS9LQ¢u¯³ ·æZ/­ÙÖÝc·uÔn MÞ§.a!‚ë5çÙiaí=3­×`ëÅ5‚wœ+ÕÜUÇÌÖ„k»uåzm·V\Ÿšk°ÏÏ6€Üà O­[S®á]ë¶uæútŠH]'^?×åjÉuèúu­´v>_®ýž¦ë)3µ"uhÎ];w×[ëÊuìùwýµÞ[k® ‰œë6@`n¼4^»®“×°ëå5âx=»^ÇÇRûT&ÀF›i½ž\c¯{×_LæµÞj}ºæ;ly¿²VL,„óz=0\ûª·×õëٵ÷>¹„¸5y»;k<2Pæû±Îf>PÁÕ.êóQxÌNÛÎbÿñÞª™z˜ŒîõšÂ¥ù§CêÞêká!;È,Ë’÷Õ?Ö¬!$«$¥[’6M “6”4%KõMK®¾léa²[Zâ—¶pv¦ëÒN^úrÙèÔ6g1®¯cêàÚsm¾œ£všáÕê8¬ŽZÛ Ñ賬nà›ð„¸é¨ÇK­Ca x ¡Ì–hdz™Ù·N†6àò* ¾vë>+m ./›Ÿíàb#Sã¿ Sú'“¹_=¿&wÒFeÚ9LíuÛ{Yÿi·³Ú0Ó«Íà?pîä4ÓQži€…'mT}L°~ • »ºžÄ]Úbísg,w$ð…Ž\ˆ¨+hÄrÔ{šG¦ÚªWI¸%à(hôtð TMô6ªÅj*`@UÚÏ…f“I·éU„€Î ÄL<îâb È­U-°ÐàÝ[ê^‘ÂÅÕõÓþx)¼Ìíª.Y—|X - Ð-f»\/)Ì—åîçëTZ$é–1;ÙFë×€` _Îa•ÛÌmïðr9an~Á¿ÐJ'£U@Ü(¦nÔöß,w“<2¥¿6Å…Ámvù¸Vk&ÍTS:­;ŠàB%ÔÁ ´ZÇ$™Æë6€‚€±j]Ý]ºv¦»C1¯šÐ»•Ђ]õÛùõ§|ÛuµÍ¶Z,™s1€ìº:˜p;Lé§n"ðz€ÂþU+P¸shìø¶¿K-Õ¤E[2ÏëS¶‡[U;‡n91o×6@þÙ’I¸´hÅ­öR ·¾× v%À¡Ü6(æßºó€ßŽ“¢$¹¾þö ðV»¢ Ó8n4L×ü■ĸ×c€"÷³IpÍTrObÙ¼îTÃ;2P5àŠYŸÜ°ˆô ô$zOcN$bÜDlK¦LÁÁ68 Ø‘á ï7Ï}#°#à¸ÁzÐÈðbÀ'¿ŒoÄ1î¾6cÀ’™àèæ޽vn?76µÂ‹|>öê¹û©~ 7÷""$ÊÍ^Ÿj¹/—¹ƒ8ÀËMºœ$ðÜ—âBƒ™»Ômcد¾Zí· ­wÖt8÷©Óë¨À§[ÃkÞ%uÇLÝï°ë¯ÛPá½»MÝÞ=& tÁ²±fkâi—Zàn–zNS¿z ™Ûbo+™xPËÍVç*3¾÷èíçíúHm†hg3ÖƒMÍ28ŒŠg½Æ–:›³YÞ¿Ã ¸˜i%íÊOS®Ýn~°¨ššþµv£7wÓ/Vxê:ø¯ë0ŸÂT²3ÕåŠïwó¦í¹–ä‰ÕÕšêu=ú6–Á¶ðQ÷±?×ß'•!7jñÌt\(&iÕXÌyÛ^÷°7Náå˜i4%ÖNNY¢xVDìŠU7Ь—Ï®éU$ª\Ú6 @eßžzý¦nX°l ö_ìx¥È­™° S‰„Ùµ¼Ë|„ò~aÛõfÔçšÔi’ý`³5YÞ1ßÕ´K: õž×þ¦¥ÁéêF 3ÉÊ-KØeCx Åçоp~›Ô]+U– 95œr+¦‚ï*¨6ÿÝA•wú RÕ©Ú)è=9_V]Y“†9³XÍY t|šà;@G…»½`QꘚÓ[ñ~ð_ýªõ‚0XÙ}òv0Aû°»oÖ÷5ú {G;UeßqåÞê\ù´jü¾ÈSñfNWêò;ƒ Wed®PŸ™¾oØ+€yb±‡Þ`âPï8Ð>käò,ð(Õ†æ¤ÇßþdÌ4ßxü7f±’ä—†V!/»x$MЦX'¦¬Ëv* Ìä½O€µ)p‚3œüA%¡F[¯—Ò²³ú‹Yóeö>Š{Þ¦h|«3h*½e^B–邞÷þô|›Æc[ÒËÝ-ªÂXXUíÇö?uÜvpd0•wI†åŸÂÛPâµ$7¯@Ç”îÌœÀ̶¨¾õÄÚoÝÁöF¿°MUìòlóí»÷h¶` œï·)ö û=(ç[ËuÙ˜p\ä¤Å…Ó¿µ·Oj¹ëîb»¬Âñ®¾×.i.|¡ª°žÂssãÑe/žì­³¶Ó¥ŠÌš/c ¡Y«-d®^ý¿‚ßvxÓðÙõþ¢§é ¯D®ÄµÞ, Òþ¬òp ó,|KnGSÝÐ.åµqÜ3Á •¶+CZØ*[¿õðRžºüU•Æd‘À7Xº±K•Y–•ê€Ä!UÉÂ~5Ö:%ž*°Ëµr€“h7¶ éõk»b¸Xð ÖOmæ<Ãf_í¦-Ðá4ºY{ñ¯ÆÁkšã¬wùJžÎžM©¦jVã4<õ¼¦R!á]ÏñWl Á]žæcm¼ ´ª˜}«Ú½Q[Š•À!ÜL*á³RzpMƒ—À½½MmLg \º=pŠß€=×ÙLøf¥Ó Ü?mŸnQ7ØëË»@åôð°‰ÜÒl˜nИ@H´»k¤fM÷}Û­,g˜i'|C |–i‡µ,TkÜwyÃu„ãlÙ°ºV­8­!_ ­m‹ãWÅÛjU$qÿT<[ªvƒöÚ‰LÖ%Ù¡ §ãüÀ›Upyg4u'ÜjÂE­ŽRn+Q|=€1¾‚‹:³à@Î+:)¾=–fª¥¨[Ô6Ø{ŠZ^Dør'ŠìþØÐ½éþBo0ž$Lu6Ò·µ“r;n®Ðñׂ `6ŽÈzÆžýx€bÉ 0·Žÿ±ã ‡»ÀvNÏX2Çã-€!Y»¤?0½OžNï!6ÑT0-ïŒxö—±àTïÄ¥cõ.`Ï|Á¬ O´8ñŠ ÿ…k8ÅÞ’Ü çX×8ñ»|¯O¡3ÌQëB¹¼ãvÂßPhø{«“vŒ/€-ÄëËÉl"|üŠŽjJQ¹Û›ÕÎx›uI<›=‘CJ¦¯M‹ë­ÛY<>x‘'¶ã·Îíê5œÄ†º†A¦9×Jµª– ŸØ?¯ÌßÂí®Ø‘Ú+.ŸÊ-A›Ãâa²¸/Þé´ƒBSË¡øT½@ûEn¾­—ú£}·wÝj-¼×Kïæµ^_Q˜æmQª_ácJ1nŸ‚]O¢Or6l”˜>fÀ¯N41Å5Ô°À‚µöb!Ÿ `ȧ5ÖgÃ~÷Z{àŸNá%òÝhè5‡jJžÅR¤-ß@l­ÊO.¤ÙŽˆã¯õR7´—òZâ­˜ÊÓ¦¶ñÈwùµŠ|¾U‘çM˲k‡+¡Û Æ~ $Ê÷±¸W³,ÜÛ%m„¯Là•r.mP¶8-žûòO9åßý(c¹»ªö³aƒâ¥]Ï©×ê(-‡ÖÉñ«¹r»Ãõ>¡POå Ú9¿[~iþͰ¦ åS 8æ}ü§ÉÄÔ][±e£>Έ'ƒü6Nõ&ÆFwåTyþt}YÅŽ1j¿Þq¹˜ B^õ`?|®Áâ4A˜sûÍŽýz¿Så2RbéÚ÷¨&ˆãLAÙMbÓx3ŒxyæIÕó»&И¼ Úü#—¨o¯§ïö5›É ͈°ÃÒ&ì Ä6s!u{û’áÞ/ìµôå’î-ö{nóÞ8l'¨Û‘‰`‚°?ãAúô]øž0óʳpí¨ÿmÚ‚¥fš·[ÝüòQÖ{J'—[ŠGÆüá‘õ2y4þÜ}áò.AÊ‘äµ)îU[ŽCn—2UqÇ›[²úÕKÄ-Á²1³ŸðDø©zm<Åp¶Ä»)àõ»ihN»áVJyh¸›‚>îâ.1°þÖcjò[Ы϶ŒJ½×)ùζӊÌEK%ÄJàѸÿS:¼ªe>G5cÔqc?ô¢õº·h±æâyiSôƒZ-E´,¤’óð­¢Ww{%šoB[¿Ûm¦ëA·Š{¢8ȧ·€†ï1óµ«VðÈœ«›!ó°ÀÈ\­™ílZK¼÷ß\-fô¯y%Oæîfæ*LÆ\úãŒÕ²1/¡ s&ðX þ†®vÃäÁÖ±†³þ©3íöÒ€3åãð‚lXuŽ9|6—ÙZ‹é—l^’ò°W=LUÆN‹-©íp‰kgüO•ÎY÷XϤù‚.ïŠõõü*oU`\]ÕHƒéy|,ÛIçüF͵Êßý,í– ,ñŽ{F‰=®ib,häÀKÙ®¯Fq-ÅàðŽê!/Œ ÆS@¶×]òë1u÷0]›².ÿ Ä^¼éؼ'¼²JµÀ\Úæi„(^*}ˆÇ`™®ôÞÚ0 óžyMéæ¿#ÐÒó­Uõ˜úDÛ–×PÝsíò㜡*>œÓ€­ÔvnXi»Y y¯°{ͦkçrJîp•dvÎè^]Š9e4‚; ½¶òe›¦UÔåp7Xâú÷?#ã"p˜²•k+ó´·XßÄ/àòõÓ‹Âd÷öWÅ_à]º;õ‰ÜGm|ÂâjTi拟úI®:3Ù³Ðlshoµ$ >XT‹RE l.틼<6}§>Æ[©×Y®ù zºí^Î!Íßå_¨3‚*51Wh¹é‡.Ûåá<Éùo¡µ«`-yýÝW¼~[ÉÈÒLú§…™´ÌÖßZŠaª@Ãðõ7z#7ÙÂ/¥päí}™ ÊÀ$aG¸P×nŸ:®Þ•k_£æŸc=µýóÎØm /ç7×ø•…J󾟾U)Ãà`(«×jþØ/—p·²ñ×1j{ùªŠ„E §`·Ÿ!êø2f:=­=Ž #h£´KaNnï|ÏJ¹lýæÍ›¯lðåù0XnšíâÄÇ­å®\{;­m¬ÂÙzÐßè5¥MÿªÓM—0Ui•v›`Þ #QËÁòóÁ«W 1 vý˜ ·A¦äíIòN=ÁÊ¥Â*[G­Cè¨Æÿ ¦Euó±aU?ÁÉUîš^¥ªsÒCÞÒß¹^» Ùž×"Õ¡ÈËÛ,íÂt²~xÈ 9±)U\¦íöÊó†ªÕãÍÞØxÓUÒŠ7Å͆¶èËÇñwàOíp}ZKÑå¡Wï§¹¼óŠî]Õ.¡ Å\Ây']i®n³/;ËíÓ$µÖ|äjQ¯Ô6“¥QÓÔ¹KŸÊw Ò†Õ%ÛòÔbê¹¶ÄK‰EªW¤½èUÃRøu®)^Ëþdµõó¦]ÝŠ;Œ…›9…ÁÐî–èê¹R{²mš.Ô[ÐÞÜ΃ÓtG`äüÇî»·Þé×ÏìËÛ~š\ž£ ÉY—æ]Ó%Ô’„~šxƒ~@︔Ññµ¾÷Ä ïÊŠû¸ÜKõú¶óK]çÇ_ƒÄÒt™mŠ Ί»`'cBõgöý¸IµžØÓëU×ëÓvé¡– ÛWgëK±-8úë2­pê€ËÀÐL»¯¦”œN5Þ“iw°sPn…¼UÍÁ|Zû ×ö ù%têþ-]Âhëˆó䬨¶· $°»@o«ó[ˆm;0¾î¦Šì‘áxoÕØk¡­´ÊÑgÐ;òëD3Ã> >òÏÉ«ôóï@ˆÙæéèe®î•ê¡ÛÅ©T£šf% ]_©×î~®¢ö/@ÇÝ›zäÞ_̯:\§{Lµ¤VÉÏõ)¨tÝ¡:í¶Óùé0W«§Òü*øD¤dÖínïê\½\Fo”¾i‹º…Õíls™ñ=î¯ß £¶öê6x»ÛkùÜn§K…‹b,±S˜û6´ëÀÛé_͹ s ,¶óÊ/Yé*L>€°X² nß`rÛ_éœÎ÷ô·[©+–g|ÝçŒeFù‡Ì”…´;MÃÄÒózi¹¥ü­þ d6­‹R>0[UÑ µ=×Ò{ñ¬&dÆ/  ÜŽ·£ÛÄ5îÒܶ ЀN4 ®?êtëÖ6ß~`ò¦oõȧW-êÍØXܘ½}ó§aËdv£´L½@[{N3åÊÏbgoµtY~ÍdŒY¢Â×´ ׸ÍmM¶çÚaì ôé6 kýäZOÑÜUtNç=ù+¤ùƺréÒ.zB]t>Yïï`÷äƒbÀð Õ»8ÅÄ:T¯ËÓØì¥é[kƒ=Ãâ}WÉDæñ,í\JŒI®ƒBWívêzUÚtt_ËÖˆÓî×9…sÒ>Ú3/î®t¶æç|>Å­¡OÑè€kŸšž+5²‹Æß©„aün`2*Lç^¢Á­€tx*8‘ûL?%Ÿxƒ­ÏôÉ6;ýñN8®¦£bÕª#T¦9Û\ºÁ|…v#§=a<º‹76ZNook8Ñé&ÓÃÃ:}—]K‡Àòô>h=½Þ}Oç4ß1£°MÛ%ÃýÜ.x·eblÁŒZáj°œ²¥Z̹¥€áŠôß=…¹Át¸7ßÿãæÍô/Ö]ÃéYG smº´×J);öô=˜z~ ÃmØvw„´û¬NÊRtñ²/rúVZ2Ë+'½3Ù‡—áoº¸\íßêÚß[±ñÁýµ :›˜b„^2•TÖœ3µïÌëޛλw:Ô†M—vÖ22‡æÌ€§ÅUÚÊ¡FÄ6f›ÒÚNG¬uƒéÿ–¸~WoÁjLP(“,NeĶa+¦zwÞ»Ìö⮀OÈZÝ­]ŸÀ"öªŽ{r.Q¯ã_Q«ð2Ú´ª\KÕÌÙ1†5ø.<'£Ž‹ælq´‹=ÑËÄEíö`Çháµù´LK]Sk8AÕrWÄi •<Û†‡›«cUµCuHiT€åº•]°]èÛHÙ6'E÷*‹TÆâ]ê¥ã8éâo‡˜K/™åÓ§²å».ÖÍywâß¹Õw(1iݨ^¿u¯;‹%ð.ô×(J6ýÑŠ:ÊWhæ4á.žF ÕËŒõ¦®$yUúö}«–\aÁ Z>ïÖøŒ Ö¿þâ)ëÏòÆÖÈ>ŒÍÖ|b{Â~Ur¯h@ÆeçÅ#Xá×õl“8ý9ÊušŸogñétË+s=T^垦RðKYifÕ]Q •Å̽›°VÓëuãzÇã²Sð)ÌÃc4¯úî–—ÛâäĈ§gr=_Î&€gZ¯ÚE[ñìoz›ëX†“½ÉzT<ـɼ+¨•—nåûÑ!f5ë»e®É·O Ê—\y‡KÁo6‡Ëä\š«P<^ŒT=Á³OѦKæ ï®`Ù=‡$C—àHê˜é!WëqÖ§1gòRùzëîŠ:”/kÐÛ[½c²€¶x^;F„®¦cx˜/ÞNδÂ[¢quõÂS«0ÑZÁãÀ_Ìó¨ý(…6µÓR3©Ôûè;liíÊ:\¯ÓA€%À­©Q¯œâ>À9vûYå²?å§gÀ¨« ‹¿Ûiñ>àFxÉ•[Gh´ªiS°'Sòö`*_²uÀ_hùÑêW>i†¶ šžmÖÄy›ãø vJÕ± ¨…Â_Ýò4¸|ÌoºKu~&a¿bt/jÌŒ¯ê˜KóŸíÿ{@~£zE·–.P[ó$ø§º¢·: š“Òö˜0ÚÕ±96ÌU·‹Ž7íí¸øÑ¥5üG7µ‚—jqç•\¤e3\=} Ƨ¡óS[=ùµ^:¾ìÖ»â¨r$'aWvJ¿Ôã‚Y¯ ^u¼‰ù ,Jµ€‡«ÁÓ\¤sJ•7{–ÏB1ÓU»ÊëÅB,½uæü¸îº«‘G}–Jå§ùßôÞvQ”¯–äAÖr®öÂ3%ŸBÿM·käDͱ·„ü{[“x¢³7™ k(À8üÃtŽðߥÌ+:mu7NØÏ†Á7¬†ó°@Nq\%›fîðÙW:ؕᾈÏJRǸ£K†;eÝŽ‹—²î‹Ï› ð ïÂW\Ÿé¹ï(€>@·=LnƒíÚÎé©äœU3½çTΙØÖJîÕhªp•¢{u‡±B2œquµl¬ùbûžÏ¯;™—þ¼º«´…Þ½ N°×ËžЦ2P)ë)Ø·™/f åi‡«†›±×Tçïô÷Ò»r¾‹šý3+2áÆ:[úP9î|LEœ_é¨iN=†n,?اƒÿæ>XxêáóM ÝÖ—[3·ô á÷¼H~ÓýISØ!÷ÓP¾ðvÿýfdãt±Û”K'Aœ’¼ªG„ÓR°ÖÓqëZáœtç„âr%¿Îjw‚Û n?… óZóÀýÏ#ëŽ5L°ÞÓâçA¡àg—–ZH« /ië7iÄ9Qï»ï»Òìcþ»¹b¹4²¯ºÍö2_Ug: H˜7˜Ò÷É@{ÔNÚlª+ð{å‘rüò²^|?Ť`ÇÇŠ_‡éy}š~NäkQAñS{£ôø{‹Ã=¡2g7¡qR‚¸ü­.we]Îç§øtpÀüåòtÏ{šìYµƒüúùUwßmeÚÇì™Êjwï)±àE«P\šVOðŠàÀE`ì>'¨@G=ùµƒ=&Œ´Ùiíþnãý®„ú}{á6Á“|M.‹„«Çi¢&ÞU|©XŽãu ¡_ýÒúFÕ§Þ—Ùöׇ.íÆgYŸ%J©Ç¯–õëM|Px¤š€Û_Ÿ`™úXPXý¦Ôå)ñf]6>q—MÚï¯ùi íãËÐoôVi|Õ0k»TöÚ|ÿà¤×®ñXÎ+?Ù„¯«TÍ;Àb\VŸ»R.ëÍ}Í[Lp<åâ¾Ð Nüx~øáÊòì÷‡cžjþÍ3xl ~b7ö98aÌô¥tÀÚÞ÷{Ê¿)¨Ýu(ݘ \¾]:\¹íŒWi¦ø:@µmnÞ1µ¼|«²ŸUA¾aÍ`†³ï˜é‰eà.©íÍ—èKí\`D³…ߺ^p¾¸ýFz;i}‡–`rÛ¡‘î‰i,·H ͱÊO%ôñù¬íföŒ^©íñÊa…ä…öt7k–š€›‡"Wµd?Ñe§ËeWñ;´#¬-~P7­ûR\chš2/Åí>U`÷~T¶jê–Gë6UÝ©îVw¹7—/ç¥o–wümX—/HüI,6‡d_0ÖƒÝ)uêwúé6·‚o·{÷¼Riîµ´y+º-ÕW™wµQÕ»kÖ3¥œi¥Ä>ø;—Ykèvsû“JÝþ¹‡†ëîqÒ³™6ÔœÅÚð3­>úÁ-¿÷î+ÝQt摲ÆÒØñí6¡Ž’¾Œbç§•÷+Ã]ŒÈt ¿}à~ÏA;u x•x{t¹À×m­‚;Ó}HªøiÝ.g¬Zá-Šn˜®£˜—Ð드µ‰ÿ] 7ÂËùù|HüQýÊ«Àc¯“Ÿ±càùî@ Ou7·LÞÞ;oóíz,…^:h§Á“øúÐ ax½.߈ç®=6Ìv–ÊúõSä·DÀ¿ §PS§ÒÏ×bzry}K[ÖSë—ᩱO.pÒ|ÙÊÇÿÈ{VáÖº¾ô³Ûß…™8Ïnw(¶Ä=1%DiñœÖß(»sYnL¨/¤snó¥ñÚô-Á¬ çz sãOuÕ?`’ 4;­hæ@°~óªØÌ7S+ÏVm˳Ój¼¾\º—ëè¼ýHÞÌpŸ£Ûg¦@ä/ÈõðF΀Wµ™Ô!µÄód^µcß—3©Úö &ç\ðÞ¡Î ¼Lg¶Ý+oöþv!uÇ&ƒ§³Cýýj°ë‰#矺ቻ\SK|k~¾Ôí·ê÷À]û(Q8¥ï†Åp¢ói·‡Ïƒ«w4OŒ›=/×UûÆ€]Ñ0´Ö$ì·P™‡ƒ—vPá)¥üe®ƒ·%#Sa°y_õ-Âs:yæÌöó¾v;—–Þ Í©÷—˺çõþƒ”îOÛ1‹Ò-sÐñ9ß»÷”î?DòNó mP}fkDw˜Ê زï’-á^{*†µé£±cȵS.¹ ù;'¤ŠWa­Ub.é23szWfIó™L9µ)~:úT‰. ŸDÔB|&5­oZÎyî èœWí÷æü’ÏðŸ¹Ãœ§.÷" nµÓ¶çeÛóKæN¹RáŸN=SDv˜dwn(c€ü^(SJrK'*f›p&e€ {BM¹RâaCŠLfl›–QT&X‚Zóy‘ƒwmyžsMIe»mðT~:TÍKdUË^¢Ü×KÔcƒMrVÛht'­aq`Ä]bYôWˆ[©XpÙãi‡O½vf^xyuû^+íM»^‡SçoÑzt»YVEVfœN`3U^W[QWnbXd¯ltXÂKbeÒLdesL*oXoi}öhƒOûh½eCcDu‰Q_i†OOxÖUÛQàWL7w'_vnÑKJb¯R Y~x“VårâY€]W^£X”RçVL`uorV«XÅU3dÓ½®n6aMÜ`„PANVþnþh ZçWz }®}_\CUÀ|ífõWfvdTm¯]¹Z/t¿PJ[/L‚u¹\ÇshVÚ^â`ãV’e,WãjÐ`Õvén0ØN–T—S–Oj~«bObûUqO×Yšq†XaY7`ww_L>båt´V»x!cíKÞ]oS±TWP…]SU€®W=bß]|¡c¹eÇ`Ãfÿn'sfa~{|cZ€Ïv€‰snßXe4 M“KqSìVƒ\ÁÏyùo^€öKö€ÝN!QmvÉgsäSÀKö€G)ÕoÅyÐgd-Þ¿aþ€Î!Q3ypg löv@uØ}>j `lg\Å—\=ju‹ð]o çW-nBfÃ’uqßp_Q0xfü€-\ÖÐQ?n¤VÐQS}KpzB+j¼Qin ÍTyã€Ù-ln)QSƒL ×K/LÛp¼j 6GGYŸk8'M^òhþ€D M³r"išUs5l­AsOx°MM‚?N¢6X¶Þ¹K‘Q[µkÔb-È3Ttl×K«gÒþ`}lÔb»g¸M8[ßkN¤}åz-e¶vˆ€]g^s•ZõW„VRsQw€z›e·R%fh~aUZ¯Y}ÓPóV´yu‚~u›SÝb‘WDv$&žP-eŠ` |&e˜x­\]!T=|ðPïdÿ[³v|€,Q™dqv-SœmjTÂKóòK„€ø\Æ`ÈTñjÂ|—SâZT{gƒfwÝSæé_Ô€mXh‚1hõ8€Ø[Ù€a‚tˆf ygpi‰p]øSðb1cr^_V›]ßxŽ‚pXjh…[¢ssS§w]DYŒ€ùXLæpxWPU`´n9€ƒ\ó^5`BrY‚ÁN±[¬j†[3U!z¾c¿Vo§€šq¯€š®VÃKVpX¼Rœ`˜X[žZPU=]oqp±\LgL°Y¸Y z`oŸ‚¢VÄRÁyŒ GðT‚Tˆ[ëVÏtGJaéUS“SEXLû[zZzrË‚ZP`¥jäRÇUÍxžZ6OÁyTjïW(_?\uÐ{wWÌ‚v9TÙpÝj‰^ž‚éexWM`gXäRØ|öSì‚ÉtTbׂ…wµ[ó‚Z:\²Nñaybñ1Sžj9iAuñR‰bisýS[|eM|·€TpcìuåcÂYên VTb_X™SÒKcZÂm(T=ao‚âXWc V¡h¶Ky[eU†q‹ss_†z•uaWËLu¸`.opW¡ltXÎhß|{X¡at}·‚‰LNe¶w vBo“S2on€cep€öY¹StVþ`ª^Åãz1aÁrSÅsw™wÒL½ZÚ‚?ƒ;~wyÉiæwjbšb±\OlmȇTP—j“€YìsÃ|«Y‡`zzTbzºbxzzzw¸‚ßvxz¸gxƒBY“o²tï^wqrUY—n™VÙT²y‘OZ[Ía ‚¡[¾U›KmSÒb q``PcVp)kzt¡eƒS½ýbHS»€o¬zéZˆeL'SHzPUP™ƒ R«K”y%r.x«ep}uOEƒHm;z€%z¬h*t¹R¤iÃoDc9Zxee6w¦VMw lƒ~kY\{½oSPnvåm–o¢sª`ƒW£PPšq?}8\ʃúbÔ}N`z(vzëKauzxƒÛw€zezåƒzW{ƒ‚w½Ujz‚zaT(`6!ÊwƒÝvÐT¼‚ž`Ii!pËt}"cWis{t|¼R¼|ñŠb«Nuvûb}*iZŒ]GZŽ]ë_p¢T]°TnP‹fc[N{”S]Rš^MMËSe Tx×8j~ãrÌTCb_™TßiÅ_U =~Æ|i OõQ aÎ~ãNÅT_ƒàT]õ[.„œd`Vrb5U7UIoˆnÜ]“bdZ\SptuY`W°YHpäUt¢Rú‚«WjU)W'ÓaŠäRX bžs`yÆVX„dYrU^=„#Sv@ûOÏtÖd„Šu+e”\cüxjTc„¬szûRu\ùt»][n'tÓmœoÌX8{xlWšS±Vfu‚7„V‹z6VôWÅ\ЃÃ^úSjwQb‰v¸OÝ^ãreQä-} [ã{£x`bÓP'RA[sŠ„ƒwX‡\/PëK‚Ll‡TYržvkZmSŽe_xÃZ“\æxVSæeiØxЃLÇ~îcÀLDtXT]Šï1qèM`„ߎ€q|ÃqÚeQe8„ u€|(z¨M–O±e:zh‚Np}‚{ôr9p P3oÁƒÃƒ½g5b¬€KZ§{Rûk×K¯|Ï`„wµV™|Æ]`\ [ÿmŒd#µwj‹Rªx(+_pc·u5WVP yåi+Q-\It)„lé`¸aÊ`lYzUe³XÑ„GN0eÄRZ„zƒ``|YÎ_biÇÁ°…Q_Axhi8s¶§Í{V«@sNx¢UÑÕ{?M3~ÏO¢u—KP‚P¶WŸyŒZ„\øs÷XpN¾\6rçwk€peœY![I„²z‡Tz[uÅ…cU‚Þe®M-c©{kcY^WdrØtR„mWiX~JQ›aÁÓW”Ýj(qä~žrFg‚†iXLwŠvûæ€b¨sai!bL«w iüR£KLc|pr„)W>TöKxwN»€uAøXœY†îd]RûcSfCÃ*)p4i6Ia:#¹ }žM—K\\¼KL<K³M>õ :‚EZ†tTŒon|P)†«Rgm=SÙs‡†MT6†-†3†ûR†6i.a¾K:,†.†ýK¾KZR2†‚¾KtT †=mW(†*†F[hmY¿€KòSÊ_€4}µy0„Å„EaŠs©‚ä|£RÎ_Ô`ï7„Å}Ê[Šc–eüs¦qqRO¹~}IQÙ‹_»YGU7{TSx†Ošb4bÞ„˜iLX Z²`jSÞ„Wi2YœT$VÄK™wvpWc ‚}'‚ñK.w–†@bZƒPd‚w€Wjƒc„…A{i iy†°o¡Yw[{í{ŅИ†WZocƒüS‚¢R(S„ºpfu\zy†hs­o™{+tèYjaj—oyÙWgT `?nne¿ZKh_mQ ôK±†'XX¢T·†¦u¾Mº†V%xwV‚7^\s{uÐ{\(ZçWº‚gN&†]c%‚Ó†zUé`Us¶X¡]•v6pµ[]͆‡Mwœ]DrɆá^ `¢{~Z»{hé}øaähý}–Vjj¼|¤€uyEiKv fŽO4ƒ™c·„©ô@—P{ZBl.UÛc‡cUÛe5ƒMbtS½\5ƒíP:|©zeT†e†´|~+iÌ„ëKj‚á q(|“ql'X»wõ_ikYü~évJaTRiÝcŠpÃiu}sNC‚\|>V]‚hømRW„ÞôStTX>NX†]‡øK=xzq¹Nb‡>[hÿQ'_äj‡uz[‡-myTp‡)MuLD†d‡qR³†#… a&…Ô„åfÛKñ#XçK4k‡zTÄ‚§aËQ…e¡Xód“VW|‰a³„{oÆ„ÝU˜kÐiijê4}}W SbRÎa5H†T}US\è‚](_jù„§{d‚þT¹RKZ¶mfxLÂ\K’ibTëKš[bÈs]¡KYMvu¾qÈ€³X}rQMÏ~žZCT“a’vÝcî}jqñj }Y‡]u•~ÎZíp‚L×XÎg½_[n a¨Y0P©€•|Sb{oqÆ€?{xZO¦[Y†c¶€ncTkSµmQdfx@eX^qém¨a¢Z̦[f„ÀWé_~„ˆaýYýÔs¤U,sáecT=€UU•oÞUTR¨MÕaH‡±t£K_1[ÖM^ŽuqW²XÑT|x%USƒwo„w\ÀS.WRLˆß]d&vo^¹Vq^HƒóS%fô{Maº{wyz›ÔrÓ…ô}.v¸iÓ]Ô‡"Te^2]PU~ÐZ}Åq£çWˆ}÷czs$fC]]cR]YP{Õ…¦K9Lv_ôt„±g­}‡¬m‹R:{5vù}¶V]z‡ƒ9uãK2`U†x }¯w}`ˆ€9iU•]Œ„§ƒƒpˆS&\öKÚt’…qß_ªtåbxk|f}UpAM{\å€âSÀiQM²k¤‡‹[Â[¾h¹N™mVWt!TÚfÛFz OQ‡S‡ˆO’LLp—KW‡VeR–k\‡‡`D çWt‡yTêLÑnƒ³hUuz2~‡^‡áÊ®ˆ„‡]±ˆ]zöÊ´”‡ Tªˆ¹ˆóƒÐQ<Btn1[h>‡‡u€ ‡tTPe)fRY`WCUT_BUÚ R0Òml^ĈYVƈp‡Æ „¶Kʈ̈2ψ Læˆuz舸ˆ€‡þ Ɉˈn3ñˆjUÒˆ-Ôˆ–g׈àdÚˆÒ_݈߈ሎ ãˆåˆêxĈëhþ õq M6~>NaU—~Y’t=‡‡±Xaàp‚Xd|J„F`¬KvuMŸw!vP9LÂkãhIXŸˆ†(‡VOBO`¥ˆ$†Ý‡©ˆöˆ`; •Tƒ‡.†°ˆÀawqÁˆoƒÄˆ·ˆo‡Lp ^Mt‡¾ˆ>‰ÉA‰¶ˆ9†7‰ÎQ8a‡„‡e‡¹YÝŠ8Ĉ¦héˆ8‰ûG‰„‡v‡xNRy‡i‡½ĈKk[‰…QñQR‰.†3nú^1ЇË|Œ‡ë\¾K‡³fŽae[‰8‰ºM–ft‡=rn ‰uzIÎje~·c†ƒ>„4ZºmˆæPîm+dÏo5Wùbª}nWçMaULˆ_|v|€€Š[|ˆ ‚ˆ´T‹q“…¦K]x2iàk‰5t‘ˆs\YÖaÝ_T]HS;j|Fus&iJ\>N ‡Ó`¶f=H|]Rúˆ?ŸhÄ„.a¡‡ƒ~ˆ–‰)v›V}…¢†DMÐwÜxÑ^jw …a@dPdc*SWióˆLm÷vSb^üSì¾MÕ]åfÁZˉ½R uYtQrXb‚dY¯Mg‚-‡|‚â`i®…Ã{ü·H)ËW¤.l·…œP¸ª?sÑ{½¾…ÓUÌO³/NDƒ¦SiV6b~RûZÉ€>ƒTWSƒem—Pp~DabH‚ÖW?jždZÐ_T{XaŠ„:h‚ZaÙc[dé_<„MLÅbŠ“fUy•S^aé`ÕpR\sªRÊã\!~žnSÁyÞ^‰ýU0ŠS: ~³~>}„\3Ußc#xO„;U Tÿ}¡|ãc\ Š¥_¡uÙm[öj{:Œ \‘€NwâxmQMåxá‰DŒu†\u³‰W…Ufo­/n> Dfi´…ooµ0lGx=sIxù‰¼½…ÓK¿…±¨MLÃ}›K ÜXÆã€þ¸b¯Rþ€Í÷ŒšU$MS…Y©^lMþ©KroLÊ…í‚ýOÎRû™j´„Ff}kZ‹‰`â‹u‹_XŠ•ynrŠ`\`n‡T:Š[[°iÎ|—P-TVpŽÈg–‹ÞxÔ`D…yTÑŒÙewc«o“VÕ!qÄwoê]mUà~[T‡€q†¡K–S SizW‘1X1€+UÐ_ój$VˆyÈtÔväbcX4\oSéeku&ZfgŽRŽÏV²OFé„a~ˆÍ…Xcx¼M/ƒÃg7w’R(…Öf^‹¹b´YTˆâz^éuZW²‰ØVMkô\Q÷{&x*Lœ„TUùz\Ke=dkdoL“X挽Q¯RèYCvŒžŒœ_ǹb±‡~gŽLƒ”†½g•wï{˜iú…÷OXvÿŠŽvRPPŽ/o0[6S¥a€‡Ç‰UUÞS`|]R\B‹Æ|²^ÚcáŒep,Q‚Œä^yLŠ•z¯}ªžŽ›ŒßyeŒ‡÷e5L»Ž U½ŽWLwp¦Vp„\jÛ€ÀXÂKŸN­s3‡€d•W‹HrmT=VìZ¬‡5ifŒœa„DuÁŒG¦RSsVŠÇ`WâcÝV¢Ž eÝŒŽoߌ’€Òm>ŒÁ[ÙZ§K?[‰ŽNJdÃ_Ã|ždŽ®¯RÖbƒ]¡ŽµŽH„PÃ|ŒbÁw~Z)ZWES‹PA[Æ6Š<ŠLÅfº~ø`“Œ&XˆSSŠjÑwÛ}Ý„ìbl¦„oShiX—t„Ž †ŽþŽŠŽZað‹ÍƒÅNl]ªXŽV׃ødÅ“† Š'aM¡ˆq|†OQ–ŽŸ«~WiêŽüX¾QûŠÄ…9ieGVš\¼rV\oŽl5„}ŽçY·NÔŒj„wN–Oi3UÔƒ¼MŽ—VoS¶^|wSG^VŽ![—t®\e2J…d§|H\„MYÜ`ç[ jŽŒGb SÂU¸X£xŸ`·Na–T öU*уŠIaÝb7ŒùäWsˉHbÍ`ÀzãrÞXxQ‹ps`Z“ˆ–eKËU%x|‹L]ùU¿Š²M’[p5W\{”ˆÈTĆAV}ùh»Q·|åxx]¢ZX[fV~RÜ`«om\ɉÆZñsU UœZ¼OŒoŒpË+‹Ï\µv †›‡RZh÷r8UUæT€<Œ“€_Xvn«TO{-}Ä`↛YéU[t_ÞŠO{ç[uhS¿VœRŒ‹i#fèK\ utH{—&Lƒš~4ˆˆS¸ŒàK2}S_ƒ™RÇŒƒ~ÀKM‹]‹?{¡^"zË_ÝbC!Q:‡cŠÄR({(L6e²WZ|ŒXu††D‡q½wIƒ~M„„dFft‡ýz×fŽbwÿĈðŒcgt‡S–L<!¼fNdt‡R')ØZVÖg¸M—l¢™,-˜Ut‡s|t‡B/MbŽ|W*\Ù5h<,t‡O1òŒÜXCtV#.2†>s|.„‡FKøŒ´nCrÛMÆK;„‡T_.†IX9é`[WºtU.†a¾t‡W‡‡<=ehØWkc‡mlk5zH‹Az^t`ð„jXûZ!S•ZA\ò[˜w)‹âXâY°w xÈr4PrÂëMãƒ=L±d’Tô„œzûtå†yhÿuŸwòSptxr‚ºga5]:u'ˆÆÜVZXÍX÷v‹XçN[„M^¸w•xÅt^&W¬WƇSzŒcS͆҃ïT2^P£béX[fvYfV$Vƒ_+VaŒ^wœi^b„­_›Piw$~!UV•RûWóæKx<y‚ÚV O ‘'³[ªŽù}x–wTeÖ…=a½Q¬qïtIo©eêrÐO¥SKŠH}Œ ŠA~KÞOI€Re~+PhŽA~ÝO|‘ȇû€[ãSÆŒb3p‡‘Ñ`|WlXÛQÎ…ùX•›{¬Wá‹`pÙcrûwélÙ‚ƒaÇ‹µ|9i\“^’[ŒÃdt‘×R›&`’|Ìsv$V³z‰UÉKYÙUW¿†£Y;ÉK±‰²|gmY•p¬W£‡Zƒq2PÆ]®t­…Á{žOÞeò‘­M󉶅ñÌ{óÎ{õ†iû‰øý‰NüåŒòŒ–óSòðQ©kl’;Åji# ’’’ýSç—’ Žâ‘’à`Ml'Z¢»r%f'_•WPà_šR¦sM^»‘ w¸Š§q’LÊW­_`+’òN´UväRVpIv¡t£u¡|Ýoæoy”‚kÞ_ºRlDUfÎŽCMÐŽUWÂKÊ…ýpzTöSœSj½[»sz\ˆ3SP‰e‹eÊ„$i¦ŠµX«‹¬p¿Mß‘ýR9Î|PÕ\„|T«cÐK‘:ZYwmbÔ‹/d¬‘a…–Žƒ‹R…u|÷‚@‚B|˜i&Œ4WÎpËXR|xW¢”„ S.NMoˆŽŠŽ,ŠbŠ­ìo‚‹Ç‹o«Z…Œ¿Z-\ptÄb‡…RbD^i`¢zk|SCX¯{ZƒÏvÏŽ¹jUW {yúptO_ˆ¡ŒÝrÚQ>ÞƒZFvxË[AU~RGr xCŠ;X‰L02€‚b—T•NpXà^b·Y~¿ŒbVŽfĆwL®jËòd¹€Æbw’ÎaoÆ„y~àuwSÍ[®z§‚oyeZTTÜ„ŠyŸr0_#’sPw‚ZZF;ÁR—S0ZŒš’þt:~ q5UYYTïn󀚇2k›Rz~wSöOˆcîT\VŸeˆ€7SWLUy‡Žxz=LZa”’ù_Xލ~de‚|mLÄfNRDoU]¹’‡{¢Z#ià„š‰íŠ'{û\©týTŠ’ÿŽdd‘KgR¨»=a™’ U±‰}y0…e nCLS?_÷\‰d‘QTjVâg¬K`’Z„WuÀc®y¬‰“ÿOÒKua9iÏK‘÷‹¦]=‘I“pSDa"Vv_tU—’Ía¨¾’©Žo€ýŒcŒ’’ï’„\’Že0“(ˆ±\-ÐQ‡mßa8…å[ãadaLá}@‘nDŽr^Ï]”q¿Q…uƒbUÅ’{‘¸xb \ãSn‰¸“q[dT„cT2…yqc[ò]Ô`\÷YyUþaªuù²`C`ú‰ˆc´b1]*W—ræz ÷O ‹hd-oÙKènª‘ †«RCWjq¡v~O|C’í,¤‰P¤j—t“[­bowsÓuŠ=aï~ަ‚x”d|ŒjÛ”•xf[)òD^5•$k+…çg½UULH  |*L"cjWÖUó”Œ":'õ”$PN•LnlOVU•ð€fLQ•L:M•òaZX•_•" Òh^†QLj•J…_XƒwÀ„ægk\GU‹_d#‡jXa\%’[’ep„Ÿ|w]T–OÙaÒ[ï“ÏzB•{T„uY^Q‰è«”ÌK5•Ø‘ SÌ‘i#-ÍxW"j;lQP•a4j•I1ƒlMû`‚\œPj}‘¨ˆPKUÝ’3U y[€“ˆŒ‹eƒuÆx pt‹~^8l@НSRˆ{‘?LfyºRD~½Ò‚%‡¦R‰u«‡­•ZráMÍv6…ºmn_o…­sð†Í‚b‰Zq]«‡á“vTúcÌ‘y=•¥VW*Y•ðfb•.ÝTma•^){M‘‚[b•I_í‰eGM1r‰K@xQRµ…ð:sù‘©ºxoú‰÷SmÕ{-RlRqP ’ÖUôOÊ_FM¨O¢Y-bkw‡PPFUD P PëhÄuW€Ž›,Wgd#"|°Uýs–![3XÓt w “ô_I[_L‰9u¯€¾‰ÜyÛ=ŒS>ßl{¥a©ie‰v§Ž€ˆñ†c›ï”v@RXõx±b‚Baà1‘‡G– Pö¬|ÄL–ØLæ1‘~^Q–'Z;ê“·=ƒÈŽ@Z°7–æS;yª^y…a±tÎ]Ø–AN‹–…¶a‚yss¤S'Z$fN°Š_—qfûhÃd-}–Oç~Ô`SN k›‡|^n`H„‡tTxP[–5L¯c|‡—iPhG¯ˆ)ш#–f‰ kE#——t‡E–Lm–—7† —¡ƒ4F.—„‡0mŒy–3—‰2" ÊTIQ\–•(–5k…[h“`V¥W–hs6OîmNƒá’îŠu=‹yc`j‚O1•{yò“çWìxDsÄmþvb˜ZH‡†„.SYYiX6|[€L…LÇtɃ3—Û…ÍYkYD—P{ÁŽÝ}h~^~qZÛ‚½Ua”Sù^NY[}“¬Y³}çoâ‰O…ýOÆsÕ‹®gã_ã„—H–§Zé_¢–`!‘o`XŒM„-|îmd\Á’Ռߎ0ZΊêéXcœŠS[‰•!rlQU×}‘^ Z/]±2[Û\ß·X;ø›’Ή/Qÿb]ùOY”W¯MLÜa¡{Ê`a«”ÐeŠgL`ÁxÞrß’çM±p¸MŒôXÏD{àŠáŠvT`t3—:t²‡PUƒYo8z=V@V—Ó–¬’‡©{mmÖõa ‡kil¨b(=Løj¤V®ˆsò—kýÝgdó—ÏçWC·pî—Æþ—ë—¦hzT]z5~—Sò•zLâip–‰’dë—YÞ‡aN`¯~]|nycç~Bbˆ«ŒcuÎù0T.^ƒZƒ_nbi^7‹‘…ÝOOS@ŒÀo9\6óvƒXXÊK7u’€jüUÒ—Jr Y¬ŽJŒ‘‚GW{ê—ûQ`º~eQù—ûiÚk–¹'LÚLòX–r^}Xi'L/P{}S]K6P‡¡`KRâ`‘eÎXÞ‘ ˆ=o´_ }`¬y%yàcꊓ§d‘r'xS}’ipÛxãr4eE[[ye˜vO€¯}üRÀRúa\/Wª|R_ü’š“–oS}Ç€}•ìuàRjdn£~‰%\Ö¥~~t±O?~Zsu'UtpÏ€¶—R©…œSîY‹\äbypØZÃiJsà}èZ£}ÓzBUm˜×LIlùR¯ƒ M-xxk=i‡be£K¶ƒ*o¸ƒh‚^qrj›˜»P¿ƒÊWÎg;p(ƒakJ[‰LR"[ÎÈ[n^ýeÉ‘¹Z„gfÖUqÍiÙÃdñSÖU¸}Åtº}¯w<Ž`ˆMõWs€_ʼnA1 S´•‘mL#‘Ìi¬—á~ær^XTŽÍ_Ý_M„rQž‚ö^SMó†4`¯ÊcëMY_ƒ³’ }–ôc?^Ÿ|§^:‰˜ƒàa¹‰òSµ‚õŽÅ[P˜Zd¥dUU[ƒ–T)PSdy{]`†…]RÙƒe lV~³‘¹”f˜È[êP÷o“€“cŠwëzÝjAXwS UY•W…U–O¬T~t#9LƉaW¬K˜QØ[œ–øOi^ÿWR~MõWxt?™UU“bŠ˜it‰â–†³|ÝWU:ƒJ]C™wi˜pdp{–ö’uÖaXä‘ qš‰Â—vS—`weÙƒF•êyºu”dý„4ˆ|¦`‹Z¶z¹‡|UÝ•ÕO¼—ÊKš—°^ñzL¨Ox…L_a¢VèhouK” ŸUÚXö‘ø•·¹…oiü‘7lÿ•¿mP×{£RòS†˜Ä™Š•D•v•ÍZvSB|ãWaWu‰^`Œ¬VT“ ˆhq¼aòN™Q[vS{L¾™\›˜W[qWòh¶Mâ”^KÐQ©p«aé‘SUÅU‹F_ò|Ÿ}Zc†)PEX¡hª–šSkP{b­˜xqX>}VOÅŠÝ}ÂKÆ™`p¥ŠjLÊ¿o U7U¶Lø_lâY§hÒ™+‹ËSÒm–™Ñ“¨£ƒÍ–«{Ú\ UÌ™~RÏ—N)P~l’N¤…«V=SžBSšN’{j¼‘„`$’pU½Œ –i{zÇ[¯X :Œˆ…Ö£„–ud˜ÙT7Pyá—Œu–mL˜‘¶KÏn4lèTi™Xˆb“5–{d\ŽÂP_Ž$ˆyŒÖ™-\j¶p^sPW°oÓ` ˆ7eñ™®b-rÇŽ¦–qW9VÕeÕŽZú– U^SQz ¢–KryW­uÜTƒŽ¢“'“3d†DWd\ä¤o¸jÁNU^e…„_g…àPsLfe³XX‚ `|WNƒXx1Zx½g3XÊ=aŒ.eS‘½›|‡›Ž•\vˆó}N\³X¨…†sʘ=}…{~v p°o¨“c…²˜QMµ˜(zê›â|AtD¿˜]R˜44Œ2"W`Ñd\›Jb^S®‰ÿ˜áŽË`Òro$‘@{ÏWn~TlX¹–¾aÇp@Zo‘QUPZdÖz‘Zx^iY\€³a?NÿSégS6øp`¯~=vHYhtf`9œ(™ãaÏ›I~}bÅÎwg„cÅwUÆKž¾bRjT]>™S—uIšcRë4{‘hÒ~ÝaÖZœ ÓŽN^qÉ3{Ò–BŒG¦›çŽ`ƒWOœan›q–Gpª’nro„—âxIj•bc1~›i|wX S3a°“W‚W›†ifëdWœqRiµ–ÓŠ°WrVéUsyÕ•&”iY{v­R{wsœjwÄP~ŽóX_[ÌYBJ\©|ƒ””bzšoÎ PSš‡shºxóX>¾b’r¬„‰q’\ø]ÑréW|U‰uåñS>NE‚­”¼|­œ´a3•жœ!f:Ž.qivtˆÄÁžbqk—|‘š}(޼^-vŽLŽOŽ\<lòŒy;|;œP´pýOƒk›PòNâœüp„âŠî\]T^[œ‹ìb¼ySš\€(ƒSyíŠ'„ÈxmQ'Oœ½a‡]²œÍWè‹ÀVÀSµSF“ƒ]€Óp‚[xZ„:‰qƒÑ0œƒZc[|R|ò\¦m*“•ÚwQUOœ1šÀ\ðŠ•|¼†Èiæ–¢”.TäeJ]ã››mªZœzqR p‰] ‹ø„AM¨Ò‘j0U(p…c‚c\RœxxbJ`ˆ^|u¹R Z“ƒcpÅ–JQàRq6a–SvLqCøhpdà’ÁWzp¿wå5b>NPeQ ¹NŸ’*eŸZGv’V\©cH!]ž–ó`Ð\X N ‹ÈY<{Œj¦ç{Ù‚œVˆFX …¶†ó-‹aê•ãXúYš]iûUmS—SD{’Ì—a2eú“ÑK‚œˆcàŠŸ™ „Àh¶K‰WƒM±›9u³›i›ºYû›5p˜W‰rWP’÷cxWždš{d\`,€:CÒL‡mS&Š›zϘߛY^9“Ö‘ïz’—cpKŽE–u=ÖC`›vŒZŸ€“›¾p­ZxJs pË\U^z\ýs8œq^…4ê‡zŒoW-ŠðQ¤øØ‚FŒª›eRðtV¯›ìK›œe$P;š4pUPsq6aNÙ…_bsaƒD`ÚT¿V¸Y”׉”[t;‡Î^1‘že/œ+0hGœiV÷‚·ˆ˜jX—qaW—Œ S»’ûöe‘†)Õ^X·O¯sX[%˜B’ðTl‚™Â{ð•…QØNÚP‰™Ê{œNÝÃd„RW_æ‹s„L„&œò|îR1oZL¬KROo˜ï}ÛXqu-ž«SÔy¹œNo¡^KŽrÖp@UdXztÝ’œ\oí‡P{xtdÇ›B^Ø[Ò’£„0_Ã8W$œ_›iqt’±ŒªbIùXO¤jzv°R¼|PžX¨˜½›öoçol’KZ;–iÁi¯‚þ^<™ÆL»„A]šŽ‹Úwb ‹å†’Þt®RÃxéš——kYEhv˜TŒŽp¥eÚTÎRšRJ€ý^µRz—™‰´TÒ¯‡×ƒV³‘7zÙL V™,è}˜PsL¦S÷u!TB_ÁN€RøK|iSpáM®|ëS·jpÁNgh@ž§j× q¾VŠvžçŽ~ujluäb”XŽ˜Z]·iÈ‘£šé_WX‚–smLX³™ |µÖY8\>`¦ð\›} ™Ðú³`ñàd†‡p œ¡iS—™¿|=d f‡bx]RzæzÒ[Ç`PØš$nÀmâ›°žGcè¼V]s&e:U·T¦˜'SVPp ‘î‚ÆžBr PbxUà™ÃL²vÇSÕu¾aTh“xeå†Q€ž˜{äX9œPUcdœxCЦ˜¼o–X(V,\ø‚i~¿Z>UØ~Ãi0š[¯Ssž‘žŸ_p#˜>o QjWŸ‚W–O¨‹›\²šYÍc …Ôu‚X…~Ä[èc~hL¡lëo ‹×rUê¢\6tà”…¿Ž;ƒi•œÂxzž}_ayTí¸m[7š™Vµiyž­Rqf£P›“ŽžÓ^TbòtÈ–PjŸ›Ö“ –òc¼a«anŽ‹{sµT½’ƒ]—›LyyŽ¨ÕŸ½ƒ×žyöŸ’ƒŒ.Tû ™iwŸÌ‚ÉO|  ­RÇUó“Up­_~‹¯¨›Ò–Z \Ï…)„v~_tøž!‹æP—°•ùW§TVi‹Œô{u’¥a—†R~blNz‘X:\¬‚¿a Ž©VëVl&›ƒ€Œm{¹”faiky׉;š—aŽ‹1dîZiì^é_ p–eÐ]º‡~hÀ›<”Ê–[)_¾š¡lm`._1Lm<‹éX1‹’qQš¾y1šX\¦qÖUY|p S ˆ·eha^tœ›7˜ÛOÁa;TMW•\³Œ}6rxF€0_ÓsC`R[üvT‘Žw—8{êb*_Y¬†ˆ/_uÕöS;•éPg $VAV€bÔŒ XÒLh_ØX‹œJ.”Œ/’WÉ“ùƒyZŸ?i\‹Ôa×d|öžðPšR“U~bóh&j7 `Z øKmº ôi¨•>`a„ »”õ_S›_‚@U’†uƒ€{aT._òw±\KØq,Q wTÆ‹PP!|A‚‰ 3qVnZ´[ …bÌ™ÝKÌeÿw œSܘ¡xIƒÈd²RgÇ ¦˜›y‰KĆ|q«Žƒã›Åx ”iŽßž¸‹($¹Š…Þ’Éy‡q•phYQ“‚awÎa^’w™ñ„Æš,Wé~RÒK°”á8½YJiÁUæ–íRaS„†pM|…hSê…¿oZàTÓwÚ\Ðe!kÁaöT&š‡p&¡,W²XKZx OJsz[ã”ñ€Ü]œËi™T—rÁšˆvYtuyqw ~x˜]åX×R^›þ °ži†Õ|={X­œ"ƒlx/ŸRwBZ_+ ALƃwxŸ|¢[0_`Ô âu†^ŽW´o¤U„žb«^YX=‡“ŸHŒZw˜i¦ƒ’š] z@ŠÇcB 7w[“½  xW %”é Ü‘l¡=V|‹„Œ¢T£™/]ÑdÐTˆŒ»Ò•/a~Ëv [¿ŒïžañŸr‰]UfÏ”6[ê[µ›K„ºuŒ‹—rwâXŒÊtëKL}0‹ÃVºwR g—Ë“izxzÝ ÍwÙ\¿V w¡o‹ÁšqOdˆˆ¥až~¿—7ŸŒšU4výO\tÅw‘~ÙmL€Sõ]uÕ’·ŒZŸ“á?j¼”L}³‚‰V¨ƒ{‡¢wN5¢çu+SL Âš÷˜yb;X«o(‘ÊeNWçu£‰ÁRN蜗²^b‘ l¼CL¸`HTti9[Øz.žzjŽìŽ'˜œšáps›b»T‰£SàPìri£V€ñKLuÔW|L ?aŸ)ˆÞb5zMgLRl'Ÿona«o£³s=]££–y‚„£¡U\`n¤©Š2eq¤%™“y~Èt|‡WÒLek±[Å€açIjԊΞì[TÙYsRUßyèPí“óZç[¼šÃKh ÒœÏz¤£ÍBM©\ÖQ2”/v÷“Yˆ]);rçj‹‹ód"™e¤ŽxÖ†ožud>¢[€eWƒƒ]Ê“Z“æ|©c¤˜TVübuyd“Zœˆ~IÇLɤ®ŽŸoŸ› …!›ô]wb x?¢€U/eduy|`N…q°o†wçMnˆ›r©£©–fJ[OŸrE—“Nø—Z“`¡T|…;”ÐQu¤"T½oórvN·U{ªK’ñbSb´a|wàyõ ‚“VâpÄPÐX®“ÊìŠàa\Z=] 7q' d‹q0˜ y˜Ž¢Tvuôe0 Î[Wˆ=p¼Rœz‘t¼K'`ã£@Ýb¼Wƒµa TÚ^µ“€¤¦K$™ R™@Šö£Ò›£—M¢#c1Xze“V”› lû¤–b Ö|´Tò¤7xT] |x¤ñŠoÏŸ¢ nTQ¤@Š.¤ñuM„U[m]Žhåê’œQj¼]ÄmÓ™tU€bÅÎxWèPµsŸoÛ‹ B`äŸ)Q•—¤R¤`Ç‘E¥ü„J£ù„ƒ{•G¤Ûsb0[g W[ \ SwLý\ ¥×\aaV T„˜W€/“«bY\tÚ^ôŸç’ü†-_–’Í )¤taf‚Á•¾vÁ¢•PŽÄ[sRïbh_ÓŒ jJQJ˜÷u Q|’ÃP І5zkYgL Q£¥²žäy5ãy·žÆY¹ž{¤Ža¢„ô™8Ÿ}‹Â|Žƒm”¤d/š¼”UL¡wSáxçoZiÓ˜-j£S™Š½U×£«Rÿ+_Wº‚¡TKZ]x{bÁj—â ‹ZjYOo—ZYºYL™—mR…ŽÖf¢qŒ{)Ÿ®RêIçWäXuYÏUØ~_ €K€Ü“•‰€[Á]H\Gb–r8ŸÍiGr¼oh ¶`ó¡©¥}Pñi‘ ML`Á¢; E|‘¥¢šÙlXÀžeh§›4Tâ’a  _ðfE¤³|'^Í–Äsâa1Ur¥k†ÑTM¤a;9[¬¤9ÏOò¤‚•X™d×LdðW%W ¦Zjopb÷’ælíymQôŠo[Ö¢îbasqOÑ¡ø‡Ú›. Á[2^F‹ÏxO>NÙ”R2“T‰}“ìa«R X¼è]Ô¤Všœòš†¡¤£‘zÍi¬q$’UzÎS›˜ò`¹šŒá…VSdD–ÍY{x…Z¸uŒoöd·š&^C‚Ît[T•^Âswy._Ú•–wé_Er¬’#|WŸG’¨’àXeb„¡žÐ^%f¢q‚Ÿ ˆW^ñSô|ULfr6«TÓÖƒª]çÞ˜8}*LgdΚʆa©W|€Ëi]iaXeHdZes  ˆÃŽ“~WY.b…¢¹Nò¤R™l¥™oQP΃3‘+¨sàžêMS[öZ Süy,{÷–+v^~q“¯ZÚ£€´[—rFvéU½tŸiþ‡[…ûTN C”‰ lt¥]n“æ“í^Q—gR¡NV~Œ\ØŸ—™•š´[A¥e˜T`£–LíiŒxîa¢!Q^O{¢YsŒ£ReWI“KšýFޏ‚éamzE£ƒæ¤$š_V&‡ep€¡¤¬uG£HcV;Xƒ_9_`™Û¤¬p ÿƒHŒ[Zœð‘bi’L§OR%žqo'ž[R*ž£)e>ž¤£ÃSSžM£kR±r/NàPû`¤œPQ³+Q }/QËnôzK¬K‰r¡ŒZò¤¿rŠs¬[s¶‘¿V‹q,˜¤`)WÊ¡Îi~mN›»h¤iLmФ3}‘˜r’Î~oÌy}lšÞOòSoš‹VðÑ}\S _qW`özlW,eKBkŸoaT¿asw«tAÖœSSYl”åMNpN|jšRÓ+QRŠeT`q]1ht˜†¤‚ïuà¢SÅt`Af”«ob§z_ ’ro§Êiw§6zO(Wµzwn§óXq§Yrbˆ›—TG›}`Á›•p†ZP¡‘bÀXê]ËŠlœvS©Œ1T¢”¾†5WAœ'ZþØqÕcdXðZTmZ¡x«¥z“£Ç ¢*W`¾|W°Wyƒw~ œj W•rZ`Øc}•hVoqŽâ[q˜Ãž¶TVžšAXÊÓS3› Øqío“G]Že’tmN—j5 ëMá‹0‡ApÑ öV\`€k{baƒM*Ÿ0_]¨¦¦‰îpmXOÇ›~˜iÿ£w¥¦Êuh}¬põ³–7£tˆ64ÉU]€ÍTqku#“gsVM’§§~Їept­a.¨9uÑ”;X]šŠ[Ï]ΕðsÈyTS”¥bw¨¾‚€‘ê€Ao«o|šðT\¦_8~駬£”qã¦#`}Ú>–¬`ß|àÔ\M›¢V±[¬|tüSaׄ5–WSi“ã”K‘Z$¤¦jX”#m#\Á£Þ§ï•ÑK Zê‹+`Ÿ²†`¯OØœÓLlm™—oŸœ\—ZýÈjñjNP†O‘p‘}}šè¤V6|ÓqƘ4jKn vV\Ÿá‚]iyE²RŒy`çN¸Qb³y楥¶éNüp ‘9M#ä–`‘´Z—›†¨‰jSd“ÔƒspQ ¨ PÄ[Ng ï‡o.šè*iKZšò¨?‘­mœ Ô{¢„¡wW–ƒÉ¦JU „ÔVc–ý_Ãdah•N]™š~{_0_Ãri©Wôn`oê¦èž¨b—KU“ˆ z[„.Zæ’HYZœ®W×›{[²ŽV£”dTÁi3UŸ€?•npU¸¥ÜTå€ÛR£sM^ê¨%iZœØ€J£|^"©„k©lºŽ6V°Z‰Ki|^ 5W™VÌË¢Ó¤Ep£e;W¥Î€ß]œPbMqÄigRͨãZçiJš¯TNemŽÝbQmw\†O¾›£é–VËdÏZú–‹öŽ¨Ò™Ëd0¦©‡É•±t„—1š@xU[‹\Ò¥‹]¬‚0“å`Á£Ë¤uYE‘l›6zsƒ3eb^cš| Š|¥‹­ŸŠ„}P~b¥ zÚe±`2e WbpP"zL°“Õ,fNë¥LXùOINÞ}ï¥u‚>~i,kèdþ–¶y›ub–КÔ`«§Ë“’rÓ© ì^V5¤åR7“6ˆ åx¬dÜŽõ¢ãa`vb}ƒEˆ‚\¡^ôŽ„u·T¾‚܇áÒ\–eb” `â©f]s®T»¨½¡· YUvVS3web>‡§šÎ¨œ8|ã’ ¡çn'”¤ƒL)V“e‡XFI>[ÛdàdÛKÞd«ƒJwLJTHªR‰"—VdšSjSªJ^‰Ùž¥4¢LMšo”WBš^¨5‘‚KYr”qRŸƒÚbÖQ÷„¢T.]j›€–c ª#vVuœžbÑW±QÌYè^üƒz¢>{¬T¼[ØŠ^XVª”@OI¨–ic{rz^\¤eód܉YåxeQ~Å¥d½Œ‹jŒÚ’DŠ®{”ƒ1˜ó©=V€šÐž;Ÿä ô¡p‹§d™dªAdùbÉ•=]Á©éxÚ™ªQ q—i½QƒMÙK/Sê“A’ñ¡ª \~b|–W Qô™0cŒŒ^¢œî•§&lÔMNǪ'Y £É{§œPr)ž:žWu€è§¨~€ÙfæWL 5žnRÑQiWѪ³Q?^NîªósâªÝQ¡™” qukS=SŒ¤ñatGNV§}ÎL/£°~å{¨ËQib‘ûžeò©È“~~VÉhÜQ“QËQ~,rG€›‚GVw¢žeªŠl"¢E^öO…L#x¨Š2¥ÌSUPÔªX—ŒLµcÞ€tWI¨þ_{KW&XŒ\.ZŒbåZÀ_Ð÷ª&fçŸNžý ¯€š¤Tù¡d3[p–«nð–AŒ `{ëP3¢v9qtVHMN C’x€–TŠLh«vŽo‰[Ë•˜e–O„«Ö‡È‹¬™ó£rƒ¯wœS3ƒt†qÊqÝ•Á©bM~.‰ËŽ7i"†4‰¨ˆmQn‡‡’K]$„‡£nt‡¢–tTOvé~¸Çj¦ouuzs wºxìnþƒpt™T-–LJ.Tõ‰aJ~— ËaWFN8qlnûXK`‹({=LÌK}Õ«òKezþ€vW2T$…ÅU%WG©É|ßœŒ„$eX†n¤!Qzzj“l•Δ°YÝ«¢R½RgWzR’4[²£Ãw”«‘«ûWímF©ÎrÅž0`8\£X¨]YT/jó‹hvúœ®£*[¢ø„3’¥h'¢Û_ÓSR¦ú©~t¬Hú«Þv"{OZƒ–Wé’¼h…aÂV—œù˜–oÜ«yq‚‡ ah¡]`|_Y¨—éR{%š0_‘Ÿ¦_’¬¸xM`Ö‰ƒw_XZœôDXÏLù}`á«Çç‚h¬|6~¨O`ä«´Q¨„Wî« c‡j½™­]o™\œža›H_Ìq¸¨È«çÊ«•NÜ«¿aM{€›×«ž‚VÖ«ÌKØ«‚\S¿aÌK[ÁM¬n¸g)é‚þh¼M†h£K[ÌR¡a$¿a£K'‡”¢!c•^ s“U{¬6R±g~¬ ¢1s¬.u¬!c…y¬‰¬ûQMŒ¬ð]¶˜¬:邯¦Ñ«~¬˜o(==ðT$‡zzΫxŸ÷XzzøKTZ‚ãgè„K ¬—ZBÁ ׫Šx‰ŠL0zz£K{$y¨LëKÁ¬’€zzg¬„…½¾¬Ñ«Må!içWe¦TÊ|8?+c­ˆUIòK$a¬³¬c¬Î¬ð‰3Ѭq}Ñ„å¢qf×K¬¬è¬E’q}Ó¬ÉKլߨmBk¬q¬ŠL´¬v“Up¬±¬›¸g†n {¶Ké«Ú]÷rlM¤œWK|Îi`{«‹`ªùd°¡Wr™‘‹y…yWü¬ZlyXstÌ}°ƒ’_Ü_ÝV•dR|Uˆè¢#‹}P†`æSðŒWOý¬ìU¶Ÿ^UTúšlM{†ƒb™a®&‹¶a¢ÓPÙ˜/vf¬ V2FzO¿a”³{u^ÇŸ¡“[ˆÜtâŠm®_œik§˜–¢s“˜]‘¢|wRã‰ø¥‹²š³e¬5v¿pÅ­»T®‡|4}-I‡‚'xpLvua[×ye®‚rž®N|ÎYŸM†Éz'_¤®ÈTls§®žÿO&‚Ÿ®ÕU.N®®‘o°®¥LuW‘Kv¬*WWtÀqþt¨ŒíZ¬uÀ†¥'¢`‘_“§s…ÝVå«)UÜNél¼˜^[ä sj|«o¶®\[¥¢EX°”¨^qP­QJ˜«–Ë{„­osåªZ•{[åuB—±g1P¨€s™¬³•8S[­¹x7‹Ì†[­©tõptXKbeK­°e­«Rê®=¥ó–l­€qdŸ®p­ëKr­Å˜°  LÙ÷ŽÜÈ¢ýOúŽÌZ¥‰Ö[²~™X<{ÁSbp¹V¯SZªe›AÏO»cøY_ŸlL¢¢TÀ«ý¤®ZvôƒWP­ð]ÉšJœîzñhႃyi–Ь½op’ù«/jlŒ¬Yx®r¨lLKv˜"ŸrQ3\žšqm¬„Œ¬r¡†ì}ï”a· é—L¬#®Và«/|â«E­=LÒLI­ëˆvˆÌ«Rô|“]üWŒrÁ’lM'QjŒ*£“G«†»Qe¯Ó`ešÑ€ïw_®'¬½gˆ`ÅŽ4‘e¯9~ wÀ‚wƒr-|®·ÛS¶Ÿ¼KH@aN£’¢Z¬“ûOåR@®‚[XP«™5S¯Œ˜uÊ’=ª²}ï;¬¹#¡ l0_z¿¢ÁzNz¨a¼|}¯*®€ˆòŠ™a `J¦5‡œS%­7ÚnmXi}ç[Õ˜°r•TWj™]8X'xB{„s£P¹r¦® Mï©t S‘6¤Tb¤…‘…¬ÅžDaº¯%x+¨n¢ŒíUÊ®qOtT»›l zT¢TM¢uxúy‰¦‹‡]R‚™qœû£r§w«Ÿ’®_^queÊ®»hÓ˜;[p•(j•sÒmé¤,Qί——íc?k“ƒ¶”4X¢ÃzÙUã{š‰ú_Že膟“Æi¢“ƒõ[©³ˆ¿f¦f2]]|„Ý}¾e4Ì|r0¤‰ÀgEX"g˜Š©Sׇcœ`‘â†Íi¤p§)t•ã –^”®ÝaD‘C¥|y† ZXŸO–TnŽK~xÜWWS‡yžÚW×£4W z¢s%Ž“[n”“«Ô¦*­Óž'’ëumXå\FX‚Ї}mNð`‚dhwXR¨VlMh’UPc߇†ð]¥®O"z>š§nd-˜èâo”[ ¨!œj–‰­ž#Y¿ŸOùL5M§¦Ϊ§Ñª¼Z$«Ï\š­Øª;sÏd?l/NÒQJ˜•c” Sƒ°™­ßQ ¯Ën·nlM™KÁ¡z­‘®ˆV0¢Ú¢žðx!¯‹¯XoZ[§q†½Œsv†{ÀS wqS—amLû§ŠšKÈ•âšO¢kds”Šx\ÃL>`ßU½w!vö`[Tó\@T²WJy.WxtÓ\øUŸõU„{”˜›üŸWLuÏ|˜`V wðsWxA ÿSUyäR“ˆ)›êŽûŠ£tf°¨~_5“Ï¢þˆËI¡Ä©ÝV!“»t€W·©Á£sˆàšÍX/jDFvnpPdxˆ~Žú\Ó\’§¹e^[òdV½Ž·ZϘá™&¢žšWyÈ[ù°c}xtÊK‘Y‘üU+aУyZu™©w[€æ[S™s„^«ôš:¢ù¦¸cN¯s«¬}®PUè’ˆjŽ^‰žU‡©¾ŒŽî–õuöªu£ÌW°ªèY¬¯ñ¯Ô“†O‹Ç—†WšœŠL&ž¯da*žð’µQ^U ¯ÐˆXfDc¯zTÉpÜWL^J’ž¯Ú^]DT×nÆÏOµ­G¨x¢KT6”€zl¯Ývè`¦†(8±‘aêxºV‡bYXNW@a>˜òŸÖQ²Nf9­¸r<­ÇhH­æS\¥ubSU^ë™)vFœH”‡¡ ch°è[E§`\þ’~Ÿ“LGq£|Øš“Œ¼`±’<˜ Š/¥I‹Ç¨hi’ÐpÇܚ‚\«‰oS“ÜSNË›2®á”U¦çM/–c“uŠfˆ ºY¾¸­‚j*zã–VpãX‹¥5¥Ó‹Þy}T©t@§’K®öS®5^;–doŽ~rC¢^’G¯ßp„wPAvV§•N`-e´n1¥gR1p+¨¶§H± wë­™Ux¶‹Íw–OœRx™¦Ká°êO~›Ym«=¯¬ž‡cp&¤‚m¾«®âK­R­™y›WñÕ‘ Œ¿ŽŒx»–~£ªOÁ[àY×›üœÞ£˜Ž•?Nȱñ]˜¤[Qq:b¨U¦vcù–ĉ¡ÛVåXŽqOzcãSÔ –W¤F¯Y¬”a¦s“w9¡c½—œj†¢Ê±C}~ª–:jj–ßo„ÀLˆ|°_’°ºQR­‡¥` ¨b¦ ¨¤WCˆvŸŽm±™T°»oÌ©­Z©j},¥{4ˆ[—U ¡±Ÿ_šKH“6ˆÓ\P[¡k™c`ß~ëTl%‘[ûn£R›`Ük"‹0‹yr`Æ£)]_L:‡kYü’ù^ã… vˆÜWþ}xŒ¦R‰ê“þ —¶a®_zéa_U[‘¤>q×O`˜»T{‰IX|O?‡ÛŸäuCv^†­_À«’R3¬/jð¢ß}‡“ž{¥oˆy;²õ˜ì®é±½«UWs* äu ¦þh„•õV| ÷t €bë«LÉ«û¢€KÐN׫@MDOlfNO¸®.}b }Œôg»²‰KN ŒlžÀ²S±_¬V3YcºPfNzzWK•ýk˜$hí\9®ï±¬ù}ѓퟺ|zªN¾±´’ðT%€Ñœ+vƒ—º”dyAL•Ž”—H|…UPæím¦Š¡¹Œ9Ÿ «Ñƒ†¡Z±buéZ”——K~¼ƒÕ˜C Žˆž Y wGf¸¡Kݰ„œpñwÌ’L•_r&Oô_ƒ_Dœ6ªÅ[ZZX»–†~Ètƒ¡VšžT3a׌ÍY¼Z³?b—I„ÄN\ªýieQ–{­\)›4¯}G‘“|¤a’L½L°rxOá•È”%~Üv±g€0o·²'•l’µ² ³õO\‡X± ÌnÃz˜_³³¨O³¶¦L™C¼¨„/„Ïowy-–6³ˆK'O‡ ˆ/‰´—3‰X‡¨ˆZ‰¸ˆ— ‘ªÇW}‰„‡m:®«G³øSÉ_ˆlLL²[Í”ÌX ˜AMy±¬UW¶f쑞¦Ÿ{bŒ¿ZKv'™3a”jV¢s‘Ÿp{¤•*L޲þ}MMÃX‘|ÿ~¼Ÿæn‡VMÄi›U¬Ü²´Té”à˜¬[m¤xz+~lMiTë¤o©(x(E‡§°ÄN”³*s,¯ì‰ÅªeÅ?¹³íö•ï £“­€°œ©Òª;²ÞQ¢²›­;sûв‰°²²Z¬ðf˜ˆëKåcjõRðϳ_¬Õ«Ì¬ez½LÁQl–T –d¯ÇëK"#g ÜV$ѳúV}_h‹»²’ÁR¶WA¬üWÌKã³×Lq賘ˆë³í³ªˆnj•Û³¨œkc¯•¤e¯õ³Ï³ÌK$˜ˆÿ³|KÔDvcTÀ¬{DMÒ³¡a!¤¬ÒLe¬ŠLez®mð_wß³´á³Kj•ÌNÓ[@•äp‡$´ ´Æ²á­Æ²çÔž>…´‡Œªˆ{X†ÕaL>:î³Û³ ⟯ó³™Vp•'´˜ˆ(†k‡]‡;•K~ ´Ò³F´9†yTI´ý³ ´%þÞ³1„A´`V"î´];´S´Æ²ú§W´õ[Y´7W3´‡R6î_´~‡}R´~‡n#‡VL¾Kf²(ZPÓ²ÇTQ] MYŒæ±²Ÿ¤ò…x¢¯~uÅ­í…ˆ¡¬s y0_±±´d_ŒÎ•z}Q¹N´™Ò³|“݆üSÀ«  ‰¨¢°‘’p®ÛzP[ï“V4¥´’Ý­ŠfÔŒ( y!¬dt4`Õ!rán²gL\¯Šfd®*Lä³TðfGoì³PвꌶK#÷³N½´¿´¯²G)@oŽ´½´_M8´^ÿdÅTw´ùTWثв٠²¦%´YnƲ±KW½´”‡sc=´Ê !Q~ß´õYscÓ´ƒ¬²¦ç]´ Uµ´/bC­|dï´wé‚m´À´égçWq´™Ëxr,«+‚”f°Å\ö¯É®L¯Šž‹ŒMÙ¯W¢q›üS wϳo‹ïw¨c¼vÓ´Q°Ï³œfÍ´£§¥bQÕoÑ¢%žc'œP5RRîX;sNÿ‰¬KôQ"µïn$µWL‰qP¸Š=S ®M!Ñ‘øx¿Z­w6¾LjßL4QÍM|QzQáOýN R;P^MÚXjŒXïQÖ³\/N iÀ _h¶pÜq‚WÊP>µ>NÍN%R—LÎPCµFµ"RBµDµXµ?RGµ­MIµ~oV`SŠ·p?\½›ïNVµÂQR]µÂO\µ@Rpµ_µÓPCRtµµPÕMM–´‡*Œo t=µ—LWµxµaµ„N>Quµ‰µEµMˆµrµXMOfeµ–š {h–Oâv~ZÓij—K³ŠMÀ˜BghŽ:µ‹ Nô>µ–Obµ†µŠµìLCOAµ^MµkMïQÇvqP¦^¹³Œeµã|.adµF>µ«µ§µcMµ½µ†µAµ¿µ…µSNHµ®µ²G)·]9lÖUCt‚µ£ˆnµsµzQõµèµÀµvµoµÿµÄµ)MÓµôL‹N®µ4ÊWÖU‹Ÿ›{a®hƒL²ºµñNnµäQhO¶‰µ QPêµuµÖN¶ìL×Qeµ­q¢SóQ­më'÷µ¾b¹µ»µ¶¶±P.¶¶¶ÏN¶¶NûµÇµFsPj¾l¢¥ñX¨£¼V¬¥±dâµêµZM5¶¶Yµ`µÄµkP’³òq€b@o¤ÎaèPY-¥KŽî›÷žqWò¤¶’L©­RصҵE¶1¶úOeµ£Owþ¤_¥3œƒ¤#}>µ_P2¶¾µ/¶p¶wµ÷P†µ¶ŒX=p+h£r di¶l‚¤Zs¤›KWa>µ#´þµ\µ`¶=Oõ‰¶ OˆPM¶Òbé‚€¶ÀžÖQäPƒdt8¶>µyQ¶G¶ìµ6¶‡‡¶­µx¶ WUd·höMÕM>µn¶Mœ¶¶Œ¶¶H¶^µr¶eµzióƒõaJA[ALˆeµ\+h8µÅZ²±5ŠD¶s¶#Rž¶¯¶ˆ¶^N@Qeµþ‰‡nùL¶Kþk”¶LpXm¶M¶Áµ4¶²¶Õµ®¶»QN޶M ¶_LRj;×K@«@^ `†­˜¶Mš¶çµÙ¶éµÄ¶Ü¶pµ$Nw¶mMMÞ¡|iJýK Xõ6)¶§¶L¤µî¶ZQJ¶°¶ò¶c¶u¶Æ¶sµ¡¶M:¶5Xe’g•NÐ]Gcò¤‚VöƶqO5Q·åµ(MõL¶’Pc¦·TYj£ÂWÖWxW„¶ôLÖ¶úP ·¬¶Å¶©NÚPôŒX½˜!·alâ¡£P-Uüµ„µÚ¶ÏM,·¶`¶>Qʶ9¶à¶±“P[0µ£Smg®%[+{hMc¨ÉN…¶c¶Û¶!R ·I¶+·¶¶ÆµïµMÁç}qPɤI·|WMWYÇ}²†HuÔ¶óMrµ,·R·§µ×µÉ¶OR˶B·À[·%|±£S’yI·½ŠÍ”MD†¦ƒ H–,¶BRëµð¶ï¶V·×¶ÿQ8¶ŒXP[Ú«qPMt·,Ÿ¬ L·kénYHu·±¶·§L<·È¶·«¶·Å¶ÚP˶t·¹\¥JXhŽUµ—L­_’L‡¶„·©µÔµ ··Ç¶¶!¶ÇµfÌO`·w çW¿¶/o¬KÜOáuQ­·¡Q=·›¶±·…·uµOj˶1N[±“qP¹·$T)¶Ny£ MYDU ~.ž·Ä·ž·m··¡Q@·¶Ð·4 ¹NÓ·m£c{£wx0Q¨¶ôLì¶¶\µ[µ­¶·¶n·ÿMô¶QÌ·u ž«ƒ¹·´)¶:§2§O·.QO{ò¤Á·(·U·ñ·T·t¶ð·a°®µ; ·õ´òµ§K¸¢eµi¾¶hŽ]­9VcO\¶7Ró·®·?Oœ·4MÉNJµ¸Ù ‡ÍK'¸9³®µ¥U"§‚WœPlh·£Lî·M ¸·Ç·Š¶²¶ ·4ž¹·¡˜s` ¸«·]Rò·Ý·tµ5¶l·¶RMRe¶¸ÍœSaaâQ·5¸Æ·?R#¸·G¸··<¸LP¹·7¸e=0f7deµh«¸ŠMU·¶‹¶ ¸ ¸¶J¸¶%oe¶8M[ñm žU·{b·ØK„Pi¸£LPõ·Ã·W¸=Q„¸:··ŠNÞ¶GP`·'ø¶y_Œ¸’ pLÝ_r·¼·?ƒDíŠO·—L#´)·3¶ÆOY¸²·Y·¯µÄª­Wj¿…¥¸mo˪½S ­v\úQ÷Khf*Ûª}i·µ(°ùo­¸û™ žôµDueµ8™Â„Sgì·ˆMxQ^MõW[¸†¸öPŸ¸ÒPR0·s·¢¦·½¸.P÷¬3¸¥L·\¸„¸q¸S·¢L¸ŒXö¶|·¶8`ÒŽW®®µŒ˜|J[[T¸í·Ø¸n¸ñ¶·Ù¸·Mô¶â¶0e¢ÿåœ/oê¶÷LV¸Ÿ¶Äµï¸H¸9¸!¸Mrg˶޸/Bc[…òh¡­¸9·b¶$MƸ‡·Ã·È¸wµ5M˸ó¸¦õ¸…pXù¸¦Lû¸ý¸=R8¸¹ÔN¹øLîµÌ¸,ŸÇq"Z…q7· ¹Ðµ ·F¶#¹¸¹;¸ô|ݸ}ÙsQUOv…‘؆˜ŠíQ8·.¹¹W·Zµ ¹Z¸ƒ¸Q~¹r· ¶*[—?n3¸o¶o¸í¸k¸#¹0¹A¹F¸à·ëOǵ޸[/WJDga[‰°)™iúe ° ¹VµLš·D¹Ú¶¹1¹…·^f¹Õ“ÏOéÍTR?¹ãµB¹BOi¹‚·¶²¶|Q<¸ö¶h6Xép‰íÔ„ÇL­ƒþO*…}P.S5§áµ—L‰ME¸P¹\µ ˜o¹ƒ›o7ãœ7Rüµ¢Lœ¸úNYQ’¹V¹¸l¹Ý¶Úµ¹ßÎ|)¸¹¶/bf,¤n—H–¸œ¹R¹·|¹ì¸:¸!¹êµÜ¸M-R;¶M2—H–µ-¹v¹U¹¤Lk¹Ã¹2¹üP ¹âf˶–ˆßzHš'·j¸Æ¹z¹¹ï·Þ·Ä¶¹¹Úª•ˆ/Š/Nú¶‰Kíeµb‚‡‰#S™¸’L›¸´¹PNÔ¹²·äµÔ¹¥LN¸Y¹ Wo„-sZ ÍT¸Û·z¹†¸L¸Ò¹·¹ü¸Û¸5¹&¹(­¸–æ­ô¹Ñ¸JQ÷¬<µ¸:R‘¹Ç¹1¹éQc¶¡¸¹þ O¤\žKã¶újeµNcßÔ¸—LÖ¸Ù¶m¸Å¸¹¶;¸p·Y¹r·{¶9‰àkLmg XQ®®µ4©ËL'‚ÖWÁKüµeOĵ7¸è¹F¹ÿ¸v¶%¹I¹#¶Ç¸É¤h­’eµb¹…‘òh幫Ri·ü¹³·Õ¹É¹=PŹƶï¹6¹§^‘ªM‚€• !T º>µ ººNº…²¤¹Mß·dM£¹PºŒµ#¹ ·)ºÀ jº/|!T鸜L3Qþ¸l¸²¹QºÇ¸\µò¸Þ¸´ç˜/|ú+¡ü»O·rºy¹ÄQcº R&º6¹y·gHqPx·E·»¸®µÆ…,e3¸¢L¹{¹!¸ºŸ·h¹¸¹¥ºÀ ¶À…·jgÿ°†·†4º˜·Lº º º¹’ºŠPÔ¹¢·'º¯¡O¤·*¯qP!d`·Í ’¸2Œ !T[¶·¬·Æº ¸aºQÞº`Qeð¹`·ò1Ž··ÕºÛƒ@‰´ˆë··ê¸³¹Ã¹ºk·µ¹&~ŸM¦ºŒ·Y¯ 1aUMîºæ¹Õ¶ô·/¹ôºƒ·*··ËºŒXË·Áî1n‘ŽŽ·vüµD¸ ºù¹þ¹ë¸"ºeºý¸^Nµ·»¸Ä ¹N•¯RKº_º ¹;ºQ¹´º»„º¹º»D- »ìŒïfB¸>µ»dºi¹‚¸¹Nº·ÒNgº¸·Ì·Œ ŽS~ºÛºRNuºE¹6»K¸»Èºë±L&¸¹·iù𹏆¶Çº$»H»q¸óº»¨V¹õgÌ·J• ÁyPP@»Åº¶C»ë¹‚ºT»Ñµñ¸¹º;»±…*œn2ã­3Ta»»ð¶º»4»‘º¹j»[»/nÄyA3‹]º—L!»¡¹ú¹€ºf»¶ºiO)»¸o n»’DT¹¢L º$ºàº»Ú¸‚º±NORZ»I¹*»Ú‡Œ»øŒmW-üºüµç¹G¸d»"»E»a¶ý¹É¹”¹Çµ{»ì¬jLÏ·Ì· Õºw¿Z°¹`PèQ†»¦µ›·S¹»É·ãº²»ˆ  Œ_q¹3Q¶[¸£º-·j·¦»ñ¸>ºu¸±…ÏÍ”Jü·Ì·yVfth°ºÂ¸t»:º§»Ë»»»¡º-M¹À»Un̯JådŒ¸Ra)¶i„حٺ—Lí\¦Pº»>R»á»òºM¸Q÷ºnnZ={”Ís<c‚Br©·’LÓUA»·&»`Mu»#»Ø¸=R:»Ï»•_»zÍ}­W–À¹f¹Rµºƒ»ðºH»°·G¹Çµ‹·nn ޏ-fŒ¸À©T΂òhÊQ¸±º3»„¸ ¸¼»¹ ¶j» ¼ ’Š¢ZÏ‚Ž!’Dfu¹ò»©P¥»7»c¶Þ›J»s·¸{ºÖ¥²MšU<±<¼V¹Ÿ¹á»‡¸ûNÉ»h»N;¼ä»•_>˜Î‚غüµ^¶O¹³ºÉ¹/¼g»G»»Waù»V¼F¼£Àzî»]¶nµ²ºMC»`¼€ºQ¼ôL ¼¤·iºö¬‚†íº6º¼PÞ»ñºØ¶2¼¥¹2@ºz¸ú/ö¬1§N›¥N¢»Û»sº&»W» ¼ ¶„go¹Œ¸ˆº˜ÅKº¹n¼2¶¼~¼sºSºN¼Eµß…“¼v¸y¥’ªb‚\–úص$N?¼_¼ì¸Y¸$N»º¹¶³¤¸ò““­÷•³¸'X.µuˆòN±¸Jy¸ d%¼æšˆÀ¸üº–»¹»“»e»ð¸“»ó¶`N¹Þ¸¿qPözÊ*‚®µ9tk¼É¼à»C¹½»v»‡»Ü·¼pµâºe¼–£Sé\Œ¸üxeµ\ì†<¹ºOȼ»á¼»à¼Î¼D»;¸Î»»º±?MµÆªõ6NzC ‰™So¼¼­¸ˆ=J;sO×{ô¬K½#µ¶¸D`L¹¸𼏲y>y¶rNrM­Š¼Q»Œ¼q¼Ö¹Ê»“»«»M ½ •Ž–´·»»|Q¬¼î¸Ž¼Ý»;¸’¼¸N¶熪ƒ¬ƒàa­¸TQ§»¯¼|¼ô»,¼Ä~C¼9I¹¹œEV«‰U·{üQ‹¼ëQȻ߼ã¼'»0¼¡Qgº%½®¬•´Ôu¸¥Lš¼¼1¼¼b¼•»!¸¹¹Fss'½›e½-¶Ñ¹_½ÁµŸ¼Ê¼ž¸ ·±¼’µ†®/N€—µ]eµs{u{‚Å»iMö»vº>½¨»ƒºÉO¹º%½zD¦m·sðMX¹ø¹·ºNº¬¼½ò¶m½íµ¥¹3½w ¸^¹/m{·ˆ‡|nekh½}N½^¼¡½¶¢¼Çµ•½ýíh¸¶Ÿ›Ìp¼¶íŽeQyÆV´y¸R»ö¼D¹`¼I¸»/·®µ%½›n½¹›ºdN|„·„ȼ#´\½²·,½O½¢¹´·‰·Mšz+h¦¹ñ1 žú¶PÉwà¹T œÚ[˜¼Œ¼â¼ºÌ¼b¼É»¡¸ÑbϽ:¶c'|ßr˜„K½¸™¼x»¶¹÷¼Þ½J¶£½ÿQ#}{µß[AÐQ¦r˜„Ê~M­³½º„»©» ¼µ½ì½ˆ·ÚµÌ¹ ÷½o¢)0»¶RçQõ¼<º‚½ï½ðT¾×Nø»·qŒóUq¨sÁ½ÃKÁ½ü}yUˆPÚº]½P½a½"¾¼½VQ ·d½Þb¾iVÓsKº£»?½½¾¼@½k½¾¦Lgº*¾ÖqPG„È`ºìqòp¼ƒµg¹6¾V»ô¼#¾ÍN?·ÿP®µ–8'!QÐyÒy°T¬¥¼ð¼R‘»É½±·¸½3¾ÿQd¼Ã˜·;\G·`¾™•0º vÚ»ñ»^µs¼Ýº1¾%¾º¶>º=l[™,\¹R·‰Õº³r6yú½ÉrtL޹Á¸¼¾ó»×¸@¼¾#½~o`·Õ£ªbŒ)ut­Rt¹Á¹¾Oº-½\¾¼»ÿ½”ºL¾M_¸d¸Ïޏ·äº®µxVÓs¾Œ½8º“¾I¾¾¼É¹n¹®µš¾cL‚÷Œ¦“×uÛ¼2»–¾»Ï¼®¼H¾)·×Q˸®¾%ép£SÔ»/nH Õº€{ÓsZ½Û½4¾k¾¾T¹6¾Í¼øL1½ŒXD·/n&u£Sè»<»‘¸Šsúյĸ¨¾§¾"¹¾Û¶ŽP±¼LOã·à¸"¼ù·qŸeµO ¾øm¶Ì»Æ¹[¾ß¾ß»‚¾“¹¾¼D"A^õ–ˆf¶M/r~ºÿºò¾…»¾·ó¶„½¸½LÏOöx,T¬xÅTü½€¾$¾¶½€½ó¾¼Y»»½¸þ ¿õ–ðkÇLµOÇL1Xú¹s»ŒMϾ¾Pp½Ì½Ó¾¼²r¯/Nc¸±…øKż:}çÌ\K¼ö¾ ½Ü½f»5» ·á·Í½¤·iÀ¼P¸]†®µS}Ú½h¾o¸Þ¾&¾/½¾„¾ÍMÚX¹Î½ ¶ù¾XL ¦ˆ}œU¾¥µb»©¾ñ¾Î¾;¿Ä¶:»šz–O‹¸d¸zqVJözé»eµ2¸È¼O¹ÂµY¾#º]¿á»xºô½žÀjëSrÎ_“ ”q/K–6ˆ $j‹¿Ž¬PLKO¬axe-6.1.2.orig/Widgets/ 40755 243 144 0 5600546251 13302 5ustar joostusersaxe-6.1.2.orig/Widgets/X11/ 40755 243 144 0 5600546254 13656 5ustar joostusersaxe-6.1.2.orig/Widgets/X11/Xaw/ 40755 243 144 0 5600546254 14415 5ustar joostusersaxe-6.1.2.orig/Widgets/X11/Xaw/Porthole.h100644 243 144 4364 5550557130 16465 0ustar joostusers/* * $XConsortium: Porthole.h,v 1.1 90/02/28 18:07:31 jim Exp $ * * Copyright 1990 Massachusetts Institute of Technology * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that * the above copyright notice appear in all copies and that both that * copyright notice and this permission notice appear in supporting * documentation, and that the name of M.I.T. not be used in advertising or * publicity pertaining to distribution of the software without specific, * written prior permission. M.I.T. makes no representations about the * suitability of this software for any purpose. It is provided "as is" * without express or implied warranty. * * M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL M.I.T. * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * * Author: Jim Fulton, MIT X Consortium */ #ifndef _XawPorthole_h #define _XawPorthole_h #include /***************************************************************************** * * Porthole Widget (subclass of Composite) * * This widget is similar to a viewport without scrollbars. Child movement * is done by external panners or scrollbars. * * Parameters: * * Name Class Type Default * ---- ----- ---- ------- * * background Background Pixel XtDefaultBackground * border BorderColor Pixel XtDefaultForeground * borderWidth BorderWidth Dimension 1 * height Height Dimension 0 * reportCallback ReportCallback Pointer NULL * width Width Dimension 0 * x Position Position 0 * y Position Position 0 * *****************************************************************************/ /* external declarations */ extern WidgetClass portholeWidgetClass; typedef struct _PortholeClassRec *PortholeWidgetClass; typedef struct _PortholeRec *PortholeWidget; #endif /* _XawPorthole_h */ axe-6.1.2.orig/Widgets/X11/Xaw/PortholeP.h100644 243 144 4005 5550557130 16575 0ustar joostusers/* * $XConsortium: PortholeP.h,v 1.1 90/02/28 18:07:32 jim Exp $ * * Copyright 1990 Massachusetts Institute of Technology * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that * the above copyright notice appear in all copies and that both that * copyright notice and this permission notice appear in supporting * documentation, and that the name of M.I.T. not be used in advertising or * publicity pertaining to distribution of the software without specific, * written prior permission. M.I.T. makes no representations about the * suitability of this software for any purpose. It is provided "as is" * without express or implied warranty. * * M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL M.I.T. * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * * Author: Jim Fulton, MIT X Consortium */ #ifndef _XawPortholeP_h #define _XawPortholeP_h #include #include typedef struct { /* new fields in widget class */ int dummy; } PortholeClassPart; typedef struct _PortholeClassRec { /* Porthole widget class */ CoreClassPart core_class; CompositeClassPart composite_class; PortholeClassPart porthole_class; } PortholeClassRec; typedef struct { /* new fields in widget */ /* resources... */ XtCallbackList report_callbacks; /* callback/Callback */ /* private data... */ } PortholePart; typedef struct _PortholeRec { CorePart core; CompositePart composite; PortholePart porthole; } PortholeRec; /* * external declarations */ extern PortholeClassRec portholeClassRec; #endif /* _XawPortholeP_h */ axe-6.1.2.orig/Widgets/X11/Xaw/Reports.h100644 243 144 4244 5550557131 16325 0ustar joostusers/* * $XConsortium: Reports.h,v 1.3 90/02/28 18:46:46 jim Exp $ * * Copyright 1990 Massachusetts Institute of Technology * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that * the above copyright notice appear in all copies and that both that * copyright notice and this permission notice appear in supporting * documentation, and that the name of M.I.T. not be used in advertising or * publicity pertaining to distribution of the software without specific, * written prior permission. M.I.T. makes no representations about the * suitability of this software for any purpose. It is provided "as is" * without express or implied warranty. * * M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL M.I.T. * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #ifndef _Xaw_Reports_h #define _Xaw_Reports_h /* * XawPannerReport - this structure is used by the reportCallback of the * Panner, Porthole, Viewport, and Scrollbar widgets to report its position. * All fields must be filled in, although the changed field may be used as * a hint as to which fields have been altered since the last report. */ typedef struct { unsigned int changed; /* mask, see below */ Position slider_x, slider_y; /* location of slider within outer */ Dimension slider_width, slider_height; /* size of slider */ Dimension canvas_width, canvas_height; /* size of canvas */ } XawPannerReport; #define XawPRSliderX (1 << 0) #define XawPRSliderY (1 << 1) #define XawPRSliderWidth (1 << 2) #define XawPRSliderHeight (1 << 3) #define XawPRCanvasWidth (1 << 4) #define XawPRCanvasHeight (1 << 5) #define XawPRAll (63) /* union of above */ #define XtNreportCallback "reportCallback" #define XtCReportCallback "reportCallback" #endif /* _Xaw_Reports_h */ axe-6.1.2.orig/Widgets/X11/Xp/ 40755 243 144 0 5600546256 14247 5ustar joostusersaxe-6.1.2.orig/Widgets/X11/Xp/COPY100644 243 144 1744 5550557130 15044 0ustar joostusers/* * SCCS_data: @(#) COPY 1.1 92/03/18 11:17:02 ****************************************************************************** Copyright 1990, 1991, 1992 David E. Smyth All Rights Reserved Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation, and that the name of David E. Smyth not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. This software is provided as-is and without any warranty of any kind. The Table widget was initially implemented by David Harrison in 1989 while he was at the University of California, Berkeley. The Table widget was re-implemented in 1992 by David Smyth. ****************************************************************************** */ axe-6.1.2.orig/Widgets/X11/Xp/Table.h100644 243 144 12303 5550557127 15566 0ustar joostusers#ifndef _XpTable_h #define _XpTable_h #include #ifdef __cplusplus /* for C++ V2.0 */ extern "C" { #endif /* * SCCS_data: %Z% %M% %I% %E% %U% * * XpTable - Forms-based composite widget/geometry manager * * Original Author: * David Harrison * University of California, Berkeley * 1989 * * Re-Implementation: * David E. Smyth David.Smyth@SniAp.MchP.SNI.De * 1992 * * This file contains the XpTable public declarations. */ /* * XpTable Widget Parameters * * Name Class RepType Default Value * * layout Layout XmpTableLoc NULL * defaultOptions DefaultOptions XmpTableOpts NULL * sameWidth SameSize XrmNameListLists NULL * sameHeight SameSize XrmNameListLists NULL * sameBorder SameSize XrmNameListLists NULL * forceShrink ForceShrink Boolean True * shrinkSimple ShrinkSimple Boolean True * columnSpacing Spacing int 0 * rowSpacing Spacing int 0 * marginWidth Margins int 0 * marginHeight Margins int 0 * * Inheritace Heirarchy (therefore see man pages for these widget types * for additional resources): * Core, Composite, XpTable. */ #define XtNlayout "layout" #define XtNdefaultOptions "defaultOptions" #define XtNsameWidth "sameWidth" #define XtNsameHeight "sameHeight" #define XtNsameBorder "sameBorder" #define XtNshrinkSimple "shrinkSimple" #define XtNforceShrink "forceShrink" #define XtNmarginWidth "marginWidth" #define XtNmarginHeight "marginHeight" #ifndef XtNcolumnSpacing #define XtNcolumnSpacing "columnSpacing" #define XtNrowSpacing "rowSpacing" #endif #define XtCLayout "Layout" #define XtCDefaultOptions "DefaultOptions" #define XtCSameSize "SameSize" #define XtCForceShrink "ForceShrink" #define XtCShrinkSimple "ShrinkSimple" #define XtCMargins "Margins" #ifndef XtCSpacing #define XtCSpacing "Spacing" #endif #define XtRXpTableLoc "XpTableLoc" #define XtRXpTableOpts "XpTableOpts" #define XtRXrmNameListLists "XrmNameListLists" /* * Option masks */ #define TBL_LEFT (1<<0) #define TBL_RIGHT (1<<1) #define TBL_TOP (1<<2) #define TBL_BOTTOM (1<<3) #define TBL_SM_WIDTH (1<<4) #define TBL_SM_HEIGHT (1<<5) #define TBL_LK_WIDTH (1<<6) #define TBL_LK_HEIGHT (1<<7) #define TBL_DEF_OPT -1 /* resource types */ typedef int XpTableOpts; typedef XrmName** XrmNameListLists; /* * Opaque resource type, class, and instance records */ typedef struct _XpTableLoc *XpTableLoc; typedef struct _XpTableClassRec *XpTableWidgetClass; typedef struct _XpTableRec *XpTableWidget; extern WidgetClass xpTableWidgetClass; #define XpIsTable(w) XtIsSubclass(w,xpTableWidgetClass) /****************************************************************************** ** Macros for ANSI and K&R Function Decls ******************************************************************************/ #ifndef NeedFunctionPrototypes #if defined(FUNCPROTO) || defined(__STDC__) || defined(__cplusplus) || defined(c_plusplus) #define NeedFunctionPrototypes 1 #else #define NeedFunctionPrototypes 0 #endif /* __STDC__ */ #endif /* NeedFunctionPrototypes */ #ifndef _ /* Macro for ANSI or K&R external declarations. Declare them like this: ** ** int foo _(( int, MapAg )); ** ** DO NOT forget whitespace before the '_' !! */ #if NeedFunctionPrototypes #define _(a) a /* ANSI results in: int foo ( int, MapAg ); */ #else #define _(a) () /* K&R results in: int foo (); */ #endif #endif /****************************************************************************** ** XpTable Public Functions ******************************************************************************/ /* Support for new XpTable data types */ extern XpTableLoc XpTableLocParse _(( char* /*layout*/ )); extern void XpTableLocFree _(( XpTableLoc /*to_free*/ )); extern XpTableOpts XpTableOptsParse _(( char* /*opt_string*/ )); extern XrmName** XrmNameListListsParse _(( char* )); extern void XrmNameListListsFree _(( XrmName** )); extern void XpCvtStrToXpTableOpts _(( XrmValue*, Cardinal*, XrmValue*, XrmValue* )); extern void XpCvtStrToXpTableLoc _(( XrmValue*, Cardinal*, XrmValue*, XrmValue* )); extern void XpCvtStrToXrmNameListLists _(( XrmValue*, Cardinal*, XrmValue*, XrmValue* )); /* Support for configuring children of an XpTable */ extern void XpTableChildPosition _(( Widget /*child*/, int /*col*/, int /*row*/ )); extern void XpTableChildResize _(( Widget /*child*/, int /*col_span*/, int /*row_span*/ )); extern void XpTableChildOptions _(( Widget /*child*/, XpTableOpts /*opts*/ )); extern void XpTableChildConfig _(( Widget /*child*/, int /*col*/, int /*row*/, int /*col_span*/, int /*row_span*/, XpTableOpts /*opts*/ )); /* Constructors */ extern Widget XpCreateTable _(( Widget /*parent*/, char* /*name*/, ArgList /*args*/, Cardinal /*numArgs*/ )); extern Widget XpCreateTableDialog _(( Widget /*parent*/, char* /*name*/, ArgList /*args*/, Cardinal /*numArgs*/ )); extern Widget XpCreateTableTransient _(( Widget /*parent*/, char* /*name*/, ArgList /*args*/, Cardinal /*numArgs*/ )); #ifdef __cplusplus /* for C++ V2.0 */ } #endif #endif /* _XpTable_h */ axe-6.1.2.orig/Widgets/X11/Xp/TableP.h100644 243 144 22766 5550557130 15716 0ustar joostusers#ifndef _XpTableP_h #define _XpTableP_h #include /* * SCCS_data: %Z% %M% %I% %E% %U% * * XpTable - Forms-based composite widget/geometry manager. * Class heirarchy: * Core * Composite * XpTable * * Originally implemented by: * David Harrison * University of California, Berkeley * 1989 * * Many bug fixes and enhancements provided by * marbru@auto-trol.com Martin Brunecky * nazgul@alphalpha.com Kee Hinckley * pastor@PRC.Unisys.COM Jon A. Pastor * * Completely re-implemented by: * David.Smyth@SniAP.MchP.SNI.De */ #include #include #ifdef __cplusplus /* for C++ V2.0 */ extern "C" { #endif /* Method definitions **====================** No new methods. I can't imagine how anyone is going to sub-class THIS Widget, as the coupling between the behavior and the instance members is rather intense! */ /* Table Class Part: Information kept in class record **====================================================** */ typedef struct _XpTableClassPart { caddr_t extension; } XpTableClassPart; /* Class hierarchy **=================** */ typedef struct _XpTableClassRec { CoreClassPart core_class; CompositeClassPart composite_class; XpTableClassPart table_class; } XpTableClassRec; extern XpTableClassRec xpTableClassRec; /* Private data types **====================** All of these structures are often used as elements of null terminated arrays. */ /* Table Location structs. **========================** These are used to describe each widget location, in both the default_layout and the real_layout. In the default_layout, the location structs contain a quark, in the real_layout they contain the actual widget and the orig* fields are set. */ typedef struct _XpTableLoc { XrmQuark w_quark; /* Widget name quark */ Widget w; /* actual widget */ int col, row; /* Position in table */ int col_span, row_span; /* Positions spanned */ int orig_width, orig_height;/* Childs orig size ... */ int orig_border_width; /* ... and border width */ int same_width, same_height;/* Childs pref size if */ int same_border; /* in a SameSize list */ XpTableOpts options; /* Child layout options */ } XpTableLocRec; /* *XpTableLoc */ /* TableLoc Methods **==================** */ #define TABLE XpTableWidget extern XpTableLoc XpTableLocNew _(( int /*count*/ )); extern XpTableLoc XpTableLocParse _(( char* /*layout*/ )); extern XpTableLoc XpTableLocGrow _(( XpTableLoc )); extern XpTableLoc XpTableLocCopy _(( XpTableLoc )); extern XpTableLoc XpTableLocFind _(( XpTableLoc, Widget )); extern XpTableLoc XpTableLocFindDefault _(( XpTableLoc, Widget )); extern XpTableLoc XpTableLocFindAtPosition _(( XpTableLoc, int, int )); extern int XpTableLocLen _(( XpTableLoc )); extern int XpTableLocPreferredWidth _(( XpTableLoc, TABLE )); extern int XpTableLocPreferredHeight _(( XpTableLoc, TABLE )); extern int XpTableLocNumCols _(( XpTableLoc )); extern int XpTableLocNumRows _(( XpTableLoc )); extern int XpTableLocCompareColSpan _(( XpTableLoc, XpTableLoc )); extern int XpTableLocCompareRowSpan _(( XpTableLoc, XpTableLoc )); extern void XpTableLocFree _(( XpTableLoc )); /* Table Vector Structs **======================** A table has two of these vectors: one for columns, and one for rows. */ typedef int XpTableVectorOpts; #define TBL_VEC_MINIMIZE 0x01 #define TBL_VEC_LOCK 0x02 #define TBL_VEC_NOGROW (TBL_VEC_MINIMIZE | TBL_VEC_LOCK) typedef struct _XpTableVector { XpTableVectorOpts options; /* Apply to entire col or row */ int value; /* width of col, hieght of row */ int pref_value; /* minimum or preferred value */ int offset; /* of upper left corner of cell */ } XpTableVectorRec, *XpTableVector; /* TableVector Methods **=====================** */ #define DO_COL (int)1 #define DO_ROW (int)0 extern XpTableVector XpTableVectorNew _(( int, TABLE, int )); extern void XpTableVectorFree _(( XpTableVector )); extern void XpTableVectorMinimize _(( XpTableVector, int, TABLE, int)); extern int XpTableVectorTotalSize _(( XpTableVector, int, TABLE, int)); extern int XpTableVectorPreferredSize _(( XpTableVector, int, TABLE, int)); extern void XpTableVectorAdjust _(( XpTableVector, int, int )); extern void XpTableVectorComputeOffsets _(( XpTableVector, int, int, int )); #undef TABLE typedef enum _ResizeStatus { RSinit, RSdone, RSdueToRequest } ResizeStatus; /* Table Part: Information kept in instance record **=================================================** */ typedef struct _XpTablePart { /* controlling members, set by SetValues or from resource database */ Boolean force_shrink; /* Shrink smaller than pref'd */ Boolean shrink_simple; /* obsolete: will be removed */ int margin_width; /* to left and right of kids */ int margin_height; /* above and below table kids */ int col_spacing; /* Space between columns */ int row_spacing; /* Space between rows */ XpTableOpts default_options;/* Default child layout options */ XpTableLoc default_layout; /* Layout spec (orig from xrdb) */ /* Lists of lists of XrmNames of child widgets whose preferred dimensions * should be considered to be the maximum of any individual named on the * lists. These lists can be changed via SetValues or the xrdb. * same_width[0] is a list of names of kids, each of which gets a * preferred width which is equal to the width of the widest kid on * the list. * Note: many child widgets may have the same name - that's OK) */ XrmName** same_width; /* kids with same width */ XrmName** same_height; /* kids with same height */ XrmName** same_border; /* kids with same border */ /* internally computed members */ XpTableLoc real_layout; /* Computed current layout */ int num_cols; /* Number of columns */ XpTableVector cols; /* Widths and opts of each col */ int num_rows; /* Number of rows */ XpTableVector rows; /* Heights and opts of each row */ /* State indications */ ResizeStatus resize_status; /* if Resize was invoked*/ /* Makes geometry management more efficient */ Boolean requesting_resize; Dimension requesting_width, requesting_height; /* Geometry data to support child resize request: * resize_* These fields are the values the child is asking for. * approved_* These fields are computed by table and returned to * the child. * current_* These fields are placeholders to save the current * vectors when computing the proposed vectors. * query_* These fields are for the table, obtained by a query * to the table's parent. */ Widget resize_child; XtGeometryMask resize_mode; Dimension resize_width, resize_height, resize_border_width; Widget approved_child; XtGeometryMask approved_mode; Dimension approved_width, approved_height, approved_border_width; XpTableVector approved_cols, approved_rows; XpTableVector current_cols, current_rows; XtGeometryMask query_mode; Dimension query_width, query_height; Boolean resize_table_to_size_pre_approved_by_parent; } XpTablePart; /* Instance hierarchy **====================** */ typedef struct _XpTableRec { CorePart core; CompositePart composite; XpTablePart table; } XpTableRec; /* Geometry Management Support Methods **=====================================** */ extern void XpTableNewLayout _(( XpTableWidget )); extern void XpTableRecomputeLayout _(( XpTableWidget )); extern void XpTableNewProposedLayout _(( XpTableWidget )); extern void XpTableUseProposedLayout _(( XpTableWidget )); extern void XpTableResizeLayout _(( XpTableWidget )); extern void XpTableSaveProposedLayout _(( XpTableWidget )); extern void XpTableGetProposedLayout _(( XpTableWidget )); extern void XpTableForgetProposedLayout _(( XpTableWidget )); extern void XpTableForgetResizeChild _(( XpTableWidget )); extern void XpTableNewRealLayout _(( XpTableWidget )); extern void XpTableAppendToDefaultLayout _(( XpTableWidget, XpTableLoc )); extern void XpTableConsiderSameSize _(( XpTableWidget )); extern void XpTableNewColsAndRows _(( XpTableWidget )); extern void XpTableProposedColsAndRows _(( XpTableWidget )); extern void XpTableMakeColsFitWidth _(( XpTableWidget )); extern void XpTableMakeColsFitQueryWidth _(( XpTableWidget )); extern void XpTableMakeRowsFitHeight _(( XpTableWidget )); extern void XpTableMakeRowsFitQueryHeight _(( XpTableWidget )); extern void XpTableFitThis _(( XpTableWidget, int, int )); extern int XpTablePreferredWidth _(( XpTableWidget )); extern int XpTablePreferredHeight _(( XpTableWidget )); extern void XpTableRequestResize _(( XpTableWidget )); extern void XpTableQueryParentForResize _(( XpTableWidget )); extern void XpTableGetProposedChildSize _(( XpTableWidget )); extern void XpTableApproveGeometryChanges _(( XpTableWidget, Widget, int, int, int )); extern void XpTableSetGeometryOfChildren _(( XpTableWidget )); extern void XpTableComputeChildSize _(( XpTableWidget, XpTableLoc, int*, int*, int*, int*, int* )); #ifdef __cplusplus /* for C++ V2.0 */ } #endif #endif /* _XpTableP_h */ axe-6.1.2.orig/Widgets/AxeCommand.c100644 243 144 13214 5550557111 15601 0ustar joostusers/* * Copyright 1992 The University of Newcastle upon Tyne * * Permission to use, copy, modify and distribute this software and its * documentation for any purpose other than its commercial exploitation * is hereby granted without fee, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of The University of Newcastle upon Tyne not be used in * advertising or publicity pertaining to distribution of the software * without specific, written prior permission. The University of * Newcastle upon Tyne makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * THE UNIVERSITY OF NEWCASTLE UPON TYNE DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF * NEWCASTLE UPON TYNE BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. * * Author: Jim Wight (j.k.wight@newcastle.ac.uk) * Department of Computing Science * University of Newcastle upon Tyne, UK */ #include #include #include #include #include static void UpdateInfo(); static XtActionsRec actions[] = { "update-info", UpdateInfo, }; static char translations[] = ": highlight() update-info()"; #define CLASS(field) axeCommandClassRec.axe_command_class.field #define Offset(field) XtOffsetOf(AxeCommandRec, axeCommand.field) static XtResource resources[] = { {XtNhelp, XtCHelp, XtRString, sizeof(String), Offset(help), XtRString, NULL}, }; #undef Offset static void ClassInitialize(), Initialize(); AxeCommandClassRec axeCommandClassRec = { { /* superclass */ (WidgetClass) &commandClassRec, /* class_name */ "AxeCommand", /* size */ sizeof(AxeCommandRec), /* class_initialize */ ClassInitialize, /* class_part_initialize */ NULL, /* class_inited */ FALSE, /* initialize */ Initialize, /* initialize_hook */ NULL, /* realize */ XtInheritRealize, /* actions */ actions, /* num_actions */ XtNumber(actions), /* resources */ resources, /* resource_count */ XtNumber(resources), /* xrm_class */ NULLQUARK, /* compress_motion */ FALSE, /* compress_exposure */ TRUE, /* compress_enterleave */ TRUE, /* visible_interest */ FALSE, /* destroy */ NULL, /* resize */ XtInheritResize, /* expose */ XtInheritExpose, /* set_values */ NULL, /* set_values_hook */ NULL, /* set_values_almost */ XtInheritSetValuesAlmost, /* get_values_hook */ NULL, /* accept_focus */ NULL, /* version */ XtVersion, /* callback_private */ NULL, /* tm_table */ XtInheritTranslations, /* query_geometry */ XtInheritQueryGeometry, /* display_accelerator */ XtInheritDisplayAccelerator, /* extension */ NULL }, /* CoreClass fields initialization */ { /* change_sensitive */ XtInheritChangeSensitive }, /* SimpleClass fields initialization */ #ifdef XAW3D { /* shadowdraw */ XtInheritXaw3dShadowDraw, }, /* ThreeD class fields initialization */ #endif { /* foo */ 0, }, /* LabelClass fields initialization */ { /* makes_compiler_happy */ 0, }, /* CommandClass fields initialization */ { /* extension */ NULL, }, /* AxeCommandClass fields initialization */ }; WidgetClass axeCommandWidgetClass = (WidgetClass) &axeCommandClassRec; static void ClassInitialize() { CLASS(translations) = XtParseTranslationTable(translations); } /* ARGSUSED */ static void Initialize(req, new, args, num_args) Widget req, new; ArgList args; Cardinal *num_args; { XtOverrideTranslations(new, CLASS(translations)); } /************************************************************* * * update-info * *************************************************************/ /* ARGSUSED */ static void UpdateInfo(widget, event, params, num_params) Widget widget; XEvent *event; String *params; Cardinal *num_params; { String help; XtVaGetValues(widget, XtNhelp, &help, NULL); AxeEditorUpdateInfoBar(AxeEditorParentOf(widget), help); } #undef CLASS axe-6.1.2.orig/Widgets/AxeCommand.h100644 243 144 3370 5550557117 15576 0ustar joostusers/* * Copyright 1992 The University of Newcastle upon Tyne * * Permission to use, copy, modify and distribute this software and its * documentation for any purpose other than its commercial exploitation * is hereby granted without fee, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of The University of Newcastle upon Tyne not be used in * advertising or publicity pertaining to distribution of the software * without specific, written prior permission. The University of * Newcastle upon Tyne makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * THE UNIVERSITY OF NEWCASTLE UPON TYNE DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF * NEWCASTLE UPON TYNE BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. * * Author: Jim Wight (j.k.wight@newcastle.ac.uk) * Department of Computing Science * University of Newcastle upon Tyne, UK */ #ifndef _AxeCommand_h #define _AxeCommand_h #include extern WidgetClass axeCommandWidgetClass; typedef struct _AxeCommandClassRec *AxeCommandWidgetClass; typedef struct _AxeCommandRec *AxeCommandWidget; #define XtNhelp "help" #define XtCHelp "Help" #endif /* _AxeCommand_h */ axe-6.1.2.orig/Widgets/AxeCommandP.h100644 243 144 4547 5550557117 15725 0ustar joostusers/* * Copyright 1992 The University of Newcastle upon Tyne * * Permission to use, copy, modify and distribute this software and its * documentation for any purpose other than its commercial exploitation * is hereby granted without fee, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of The University of Newcastle upon Tyne not be used in * advertising or publicity pertaining to distribution of the software * without specific, written prior permission. The University of * Newcastle upon Tyne makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * THE UNIVERSITY OF NEWCASTLE UPON TYNE DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF * NEWCASTLE UPON TYNE BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. * * Author: Jim Wight (j.k.wight@newcastle.ac.uk) * Department of Computing Science * University of Newcastle upon Tyne, UK */ #ifndef _AxeCommandP_h #define _AxeCommandP_h #include #include typedef struct _AxeCommandClass { XtPointer extension; XtTranslations translations; } AxeCommandClassPart; typedef struct _AxeCommandClassRec { CoreClassPart core_class; SimpleClassPart simple_class; #ifdef XAW3D ThreeDClassPart threeD_class; #endif LabelClassPart label_class; CommandClassPart command_class; AxeCommandClassPart axe_command_class; } AxeCommandClassRec; extern AxeCommandClassRec axeCommandClassRec; typedef struct { String help; } AxeCommandPart; typedef struct _AxeCommandRec { CorePart core; SimplePart simple; #ifdef XAW3D ThreeDPart threeD; #endif LabelPart label; CommandPart command; AxeCommandPart axeCommand; } AxeCommandRec; #endif /* _AxeCommandP_h */ axe-6.1.2.orig/Widgets/AxeEditor.c100644 243 144 304035 5600342450 15467 0ustar joostusers/* * Copyright 1992, 1993 The University of Newcastle upon Tyne * * Permission to use, copy, modify and distribute this software and its * documentation for any purpose other than its commercial exploitation * is hereby granted without fee, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of The University of Newcastle upon Tyne not be used in * advertising or publicity pertaining to distribution of the software * without specific, written prior permission. The University of * Newcastle upon Tyne makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * THE UNIVERSITY OF NEWCASTLE UPON TYNE DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF * NEWCASTLE UPON TYNE BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. * * Author: Jim Wight (j.k.wight@newcastle.ac.uk) * Department of Computing Science * University of Newcastle upon Tyne, UK */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include extern int errno; #ifndef __BSD_4_4__ extern char *sys_errlist[]; #endif #include #ifdef EXTENSION #include "Language.h" #endif #include "AxeEditorP.h" extern char *getenv(); #include "regexp.h" #include "util.h" #include "version.h" #include "axeLogo.xbm" #include "fwdArrow.xbm" #include "bwdArrow.xbm" #include "vtCentre.xbm" #include "hzCentre.xbm" #include "tickMark.xbm" #include "modMark.xbm" static Boolean validAction; /* * The names in the first column must be the same * as those in the defaultMenuList that follows */ static MenuRecord chosenMenus[] = { "move", False, "search", False, "insert", False, "delete", False, "help", False, "misc", False, "font", False, "window", False, "buffer", False, "show", False, "file", False, "quit", False, 0, False, }; #define defaultMenuList "move search insert delete help misc font window \ buffer show file quit logo" #define defaultFontList "Small:6x13 Medium:8x13 Large:9x15 Huge:10x20" #define defaultMiniMenu "print:lpr spell nroff mail | \ exec:mini-commit abort:mini-abort | \ print:lpr\n spell:spell\n nroff:nroff\n" #define Offset(field) XtOffsetOf(AxeEditorRec, axeEditor.field) static XtResource resources[] = { {XtNfile, XtCFile, XtRString, sizeof(String), Offset(file), XtRString, NULL}, {XtNmenuList, XtCMenuList, XtRString, sizeof(String), Offset(menu_list), XtRString, defaultMenuList}, {XtNbuttons, XtCButtons, XtRBoolean, sizeof(Boolean), Offset(buttons), XtRImmediate, (XtPointer) False}, {XtNbuttonList, XtCButtonList, XtRString, sizeof(String), Offset(button_list), XtRString, NULL}, {XtNinfoTimeout, XtCInfoTimeout, XtRInt, sizeof(int), Offset(info_timeout), XtRImmediate, (XtPointer) 0}, {XtNfocusToText, XtCFocusToText, XtRBoolean, sizeof(Boolean), Offset(focus_to_text), XtRImmediate, (XtPointer) False}, {XtNsuppressFilename, XtCSuppressPane, XtRBoolean, sizeof(Boolean), Offset(suppressFilename), XtRImmediate, (XtPointer) False}, {XtNsuppressInfobar, XtCSuppressPane, XtRBoolean, sizeof(Boolean), Offset(suppressInfobar), XtRImmediate, (XtPointer) False}, {XtNsuppressMinibuffer, XtCSuppressPane, XtRBoolean, sizeof(Boolean), Offset(suppressMinibuffer), XtRImmediate, (XtPointer) False}, {XtNfontList, XtCFontList, XtRString, sizeof(String), Offset(font_list), XtRString, defaultFontList}, {XtNinternalBorderWidth, XtCBorderWidth, XtRDimension, sizeof(Dimension), Offset(internal_border_width), XtRImmediate, (XtPointer) 1}, {XtNfullPathnames, XtCFullPathnames, XtRBoolean, sizeof(Boolean), Offset(full_pathnames), XtRImmediate, (XtPointer) False}, {XtNchangeCallback, XtCCallback, XtRCallback, sizeof(XtPointer), Offset(change_callbacks), XtRCallback, (XtPointer) NULL}, }; #undef Offset #define INCREMENT 5 #define MAXSTRLEN 16 #define CHUNK 10 #define EDITORS axeEditorClassRec.axeEditor_class.editors #define NUMBEROFEDITORS axeEditorClassRec.axeEditor_class.numberOfEditors #define MAXEDITORS axeEditorClassRec.axeEditor_class.maxEditors #define CLASS(field) axeEditorClassRec.axeEditor_class.field #define PRIVATE(w,field) (((AxeEditorWidget) w)->axeEditor.field) static void ClassInitialize(), PseudoClassInitialize(), Initialize(); static void CalculateSize(), Resize(), Realize(); static void Destroy(); static XtGeometryResult GeometryManager(); static void InsertChild(), DeleteChild(); static XpTableLoc MakeButtonsLayout(); static void NewEditor(), DeckChange(), SetKeyboardFocus(); static Widget MakeMenu(); static void MakeOneMenu(); static void MakeFontMenu(), MakeShowMenu(), MakeLogoMenu(), MakeMiniMenu(); static void MakeButtons(); static void RePopulateShowMenu(), FreeFontList(); static FontListStruct *ParseFontList(); static void UpdateFileName(), UpdateTitles(); static Widget AxeEditorOf(), ShellOf(); static String HomeFile(); String AxeEditorExpandName(); static void Help(); static void NewWindow(), CloseWindow(), CloseAll(), IconifyAll(), Restack(); static void NewBuffer(), CloseBuffer(); static void SaveAndClose(), SaveAll(); static void miniSearch(), miniInsert(), miniSaveAs(), miniLoad(), miniPipe(); static void miniClear(), miniSelect(), miniAbort(), MiniLeave(), MiniCommit(); static void miniShell(), miniStuff(); #ifdef EXTENSION static int MiniInterp(); #endif static void MiniUninstallAccelerators(); static void startMacro(), endMacro(), execMacro(), repeatMacro(); static void UpdateInfo(), UpdateInfoBar(); static char commandButtonsLayout[] = "\ mbeg 0 1 wW; sbtext 1 1 wW; ifile 2 1 wW; \ mend 0 2 wW; sftext 1 2 wW; isel 2 2 wW; \ mup 0 3 wW; sline 1 3 wW; ipaste 2 3 wW; \ mdown 0 4 wW; scaret 1 4 wW; ictrl 2 4 wW; \ mtop 0 5 wW; sbsel 1 5 wW; \ mbot 0 6 wW; sfsel 1 6 wW; \ \ dword 3 1 wW; hgnrl 4 1 wW; mundo 5 1 wW; \ dline 3 2 wW; hbind 4 2 wW; mwhere 5 2 wW; \ dsel 3 3 wW; hcust 4 3 wW; mform 5 3 wW; \ dcut 3 4 wW; hpop 4 4 wW; mcentre 5 4 wW; \ hextn 4 5 wW; mhcentr 5 5 wW; \ hchng 4 6 wW; mpref 5 6 wW; \ \ wnew 7 1 wW; bempty 8 1 wW; fsvex 10 1 wW; \ wfull 7 2 wW; bfull 8 2 wW; fsvall 10 2 wW; \ wclose 7 3 wW; bclear 8 3 wW; fsave 10 3 wW; \ wclall 7 4 wW; bclose 8 4 wW; fsvas 10 4 wW; \ wicon 7 5 wW; fload 10 5 wW; \ wdeicon 7 6 wW; frvrt 10 6 wW; \ \ qquit 11 1 wW; \ qsvex 11 2 wW; \ qsvclw 11 3 wW; \ qsvclb 11 4 wW;"; static ButtonRecord buttonActions[] = { "mMove", NULL, "mbeg", "beginning-of-line", "mend", "end-of-line", "mup", "previous-page", "mdown", "next-page", "mtop", "beginning-of-file", "mbot", "end-of-file", "mSearch", NULL, "sbtext", "search(backward)", "sftext", "search(forward)", "sline", "goto-line", "scaret", "search-caret", "sbsel", "backward-search-selection", "sfsel", "forward-search-selection", "mInsert", NULL, "ifile", "include-file", "isel", "include-selection", "ipaste", "paste", "ictrl", "insert-control", "mDelete", NULL, "dword", "delete-word", "dline", "delete-line", "dsel", "delete-selection", "dcut", "kill-selection", "mHelp", NULL, "hgnrl", "help(Introduction)", "hbind", "help(Bindings)", "hcust", "help(Customise)", "hpop", "help(Popups)", #ifdef EXTENSION "hextn", "help(Language)", #endif "hchng", "help(Changes)", "mMisc", NULL, "mundo", "undo", "mwhere", "where", "mform", "form-paragraph", "mcentre", "redraw-display", "mhcentr", "centre-line", "mpref", "set-preferences", "mWindow", NULL, "wnew", "new-window", "wfull", "new-window(load)", "wclose", "close-window", "wclall", "close-all", "wicon", "iconify-all(I)", "wdeicon", "iconify-all(D)", "mBuffer", NULL, "bempty", "new-buffer", "bfull", "new-buffer(load)", "bclear", "clear-buffer", "bclose", "close-buffer", "mFile", NULL, "fsvex", "save-and-close", "fsvall", "save-all", "fsave", "save-file", "fsvas", "save-as", "fload", "load-file", "frvrt", "reload-file", "mQuit", NULL, "qquit", "close-all", "qsvex", "save-and-close", "qsvclw", "save-and-close(window)", "qsvclb", "save-and-close(buffer)", }; static char miniTranslationsTable[] = "\ : display-caret(on) update-info(\"search /)fwd ?)bwd; [0-9][0-9]*)goto; r)ead; w)rite; e)dit; |)pipe; !)shell\")\n\ : mini-leave() update-info(\" \")\n\ CtrlG: mini-abort() \n\ Escape: mini-abort() \n\ Return: mini-commit()"; static char miniAcceleratorsTable[] = "#override \n\ CtrlA: beginning-of-line() \n\ CtrlB: backward-character() \n\ CtrlD: delete-next-character() \n\ CtrlE: end-of-line() \n\ CtrlF: forward-character() \n\ CtrlG: mini-abort() \n\ CtrlK: kill-to-end-of-line() \n\ Delete: delete-previous-character() \n\ Escape: mini-abort() \n\ Return: mini-commit() \n\ : insert-char()"; static XtActionsRec actions[] = { "help", Help, "new-window", NewWindow, "close-window", CloseWindow, "close-all", CloseAll, "iconify-all", IconifyAll, "deiconify-all", IconifyAll, "restack", Restack, "new-buffer", NewBuffer, "close-buffer", CloseBuffer, "save-and-exit ", SaveAndClose, /* backwards compatability */ "save-and-close", SaveAndClose, "save-all", SaveAll, "mini-search", miniSearch, "mini-insert", miniInsert, "mini-saveas", miniSaveAs, "mini-load", miniLoad, "mini-pipe", miniPipe, "mini-clear", miniClear, "mini-select", miniSelect, "mini-abort", miniAbort, "mini-leave", MiniLeave, "mini-commit", MiniCommit, "mini-shell", miniShell, "mini-stuff", miniStuff, "start-macro", startMacro, "end-macro", endMacro, "exec-macro", execMacro, "repeat-macro", repeatMacro, "update-info", UpdateInfo, }; AxeEditorClassRec axeEditorClassRec = { /* Core class part */ { /* superclass */ (WidgetClass) &compositeClassRec, /* class_name */ "AxeEditor", /* widget_size */ sizeof(AxeEditorRec), /* class_initialize */ ClassInitialize, /* class_part_initialize */ NULL, /* class_inited */ FALSE, /* initialize */ Initialize, /* initialize_hook */ NULL, /* realize */ Realize, /* actions */ actions, /* num_actions */ XtNumber(actions), /* resources */ resources, /* num_resources */ XtNumber(resources), /* xrm_class */ NULLQUARK, /* compress_motion */ TRUE, /* compress_exposure */ XtExposeCompressMultiple, /* compress_enterleave */ TRUE, /* visible_interest */ FALSE, /* destroy */ Destroy, /* resize */ Resize, /* expose */ XtInheritExpose, /* set_values */ NULL, /* set_values_hook */ NULL, /* set_values_almost */ XtInheritSetValuesAlmost, /* get_values_hook */ NULL, /* accept_focus */ NULL, /* version */ XtVersion, /* callback offsets */ NULL, /* tm_table */ NULL, /* query_geometry */ XtInheritQueryGeometry, /* display_accelerator */ NULL, /* extension */ NULL, }, { /* composite class fields */ /* geometry_manager */ GeometryManager, /* change_managed */ XtInheritChangeManaged, /* insert_child */ InsertChild, /* delete_child */ DeleteChild, /* extension */ NULL }, /* AxeEditor class part */ { /* extension */ NULL } }; WidgetClass axeEditorWidgetClass = (WidgetClass) &axeEditorClassRec; static void ClassInitialize() { char *dir; #if defined(SYSV) || defined(SVR4) extern char *getcwd(); #define getwd(buf) getcwd(buf,MAXPATHLEN) #else extern char *getwd(); #endif extern char *getenv(); EDITORS = NULL; NUMBEROFEDITORS = 0; MAXEDITORS = 0; CLASS(show_menu) = (Widget) 0; CLASS(mini_translations) = XtParseTranslationTable(miniTranslationsTable); CLASS(mini_accelerators) = XtParseAcceleratorTable(miniAcceleratorsTable); if ( (dir = getenv("HOME")) ) { CLASS(home_dir) = XtNewString(dir); } else { CLASS(home_dir) = NULL; } CLASS(home_dir_len) = strlen(CLASS(home_dir)); CLASS(current_dir) = XtMalloc(MAXPATHLEN); if (!getwd(CLASS(current_dir))) { if (CLASS(home_dir)) { strcpy(CLASS(current_dir), CLASS(home_dir)); } else { CLASS(current_dir)[0] = '\0'; } } strcat(CLASS(current_dir), "/"); CLASS(current_dir_len) = strlen(CLASS(current_dir)); CLASS(show_menu_callbacks) = 0; CLASS(show_menu_callback_list) = 0; CLASS(default_mini_menu) = 0; CLASS(mini_menu) = 0; CLASS(macro_id) = (XtActionHookId) 0; CLASS(macro_size) = 0; CLASS(max_macro_size) = 0; CLASS(in_macro_string) = False; CLASS(macro_commands) = (MacroList) 0; CLASS(show_work_proc) = False; } static void PseudoClassInitialize(w) Widget w; { Display *display; Window rootWindow; Widget app; if (!CLASS(axeLogo)) { display = XtDisplay(w); rootWindow = XDefaultRootWindow(display); CLASS(axeLogo) = XCreateBitmapFromData(display, rootWindow, (char *) axeLogo_bits, axeLogo_width, axeLogo_height); CLASS(fwdArrow) = XCreateBitmapFromData(display, rootWindow, (char *) fwdArrow_bits, fwdArrow_width, fwdArrow_height); CLASS(bwdArrow) = XCreateBitmapFromData(display, rootWindow, (char *) bwdArrow_bits, bwdArrow_width, bwdArrow_height); CLASS(vtCentre) = XCreateBitmapFromData(display, rootWindow, (char *) vtCentre_bits, vtCentre_width, vtCentre_height); CLASS(hzCentre) = XCreateBitmapFromData(display, rootWindow, (char *) hzCentre_bits, hzCentre_width, hzCentre_height); CLASS(tickMark) = XCreateBitmapFromData(display, rootWindow, (char *) tickMark_bits, tickMark_width, tickMark_height); CLASS(modMark) = XCreateBitmapFromData(display, rootWindow, (char *) modMark_bits, modMark_width, modMark_height); while ((app = XtParent(w))) { w = app; } CLASS(menu_parent) = w; } } /* ARGSUSED */ static void Initialize(req, new, args, num_args) Widget req, new; ArgList args; Cardinal *num_args; { AxeEditorWidget aew = (AxeEditorWidget) new; FontListStruct *buttonList = NULL; XpTableLoc tableLoc; int menu; char menuName[32]; Widget fileName, infoBar, buttons, miniBuffer; Widget menuButton, logoButton, miniMenu; PseudoClassInitialize(aew); NewEditor(aew); fileName = PRIVATE(new,file_name) = XtVaCreateWidget("fileName", labelWidgetClass, new, NULL); if (!PRIVATE(new,suppressFilename)) { XtManageChild(fileName); } infoBar = PRIVATE(new,info_bar) = XtVaCreateWidget("infoBar", labelWidgetClass, new, XtNlabel, QVERSION, NULL); PRIVATE(new,info_timer) = (XtIntervalId) 0; if (!PRIVATE(new,suppressInfobar)) { XtManageChild(infoBar); } tableLoc = MakeButtonsLayout(new, &buttonList); buttons = PRIVATE(new,menu_bar) = XtVaCreateManagedWidget("buttons", xpTableWidgetClass, new, XtNlayout, tableLoc, NULL); XpTableLocFree(tableLoc); for (menu = 0; chosenMenus[menu].name; ++menu) { if (chosenMenus[menu].chosen) { sprintf(menuName, "%sMenu", chosenMenus[menu].name); menuButton = XtVaCreateManagedWidget(menuName, axeMenuButtonWidgetClass, buttons, NULL); if (strcmp(menuName, "showMenu") == 0 && !CLASS(show_menu)) { CLASS(show_menu) = MakeMenu(menuButton, CLASS(menu_parent), MakeShowMenu, False); } else if (strcmp(menuName, "fontMenu") == 0) { (void) MakeMenu(menuButton, new, MakeFontMenu, False); } else { (void) MakeMenu(menuButton, CLASS(menu_parent), MakeOneMenu, False); } } } PRIVATE(new,font_table) = (FontListStruct *) 0; logoButton = XtVaCreateManagedWidget("axeLogo", axeMenuButtonWidgetClass, buttons, XtNbitmap, CLASS(axeLogo), XtNhelp, QVERSION, NULL); (void) MakeMenu(logoButton, CLASS(menu_parent), MakeLogoMenu, False); if (PRIVATE(new,buttons) || PRIVATE(new,button_list)) { MakeButtons(buttons, buttonList); if (buttonList) { FreeFontList(XtDisplay(new), buttonList); } } PRIVATE(new,ed_deck) = XtVaCreateManagedWidget("edDeck", axeTextDeckWidgetClass, new, XtNfile, PRIVATE(new,file), NULL); XtAddCallback(PRIVATE(new,ed_deck), XtNchangeCallback, DeckChange, (XtPointer) new); XtVaGetValues(AxeTextDeckTop(PRIVATE(new,ed_deck)), XtNtranslations, &(PRIVATE(new,defaultTextTranslations)), NULL); miniBuffer = PRIVATE(new,mini_buffer) = XtVaCreateWidget("miniBuffer", asciiTextWidgetClass, new, XtNaccelerators, CLASS(mini_accelerators), NULL); XtOverrideTranslations(PRIVATE(new,mini_buffer), CLASS(mini_translations)); miniMenu = PRIVATE(new,mini_button) = XtVaCreateWidget("miniMenu", axeMenuButtonWidgetClass, new, NULL); (void) MakeMenu(miniMenu, CLASS(menu_parent), MakeMiniMenu, False); if (!PRIVATE(new,suppressMinibuffer)) { XtManageChild(miniBuffer); XtManageChild(miniMenu); } PRIVATE(new,accelerateMini) = False; PRIVATE(new,confirmer) = XtVaCreatePopupShell("confirmer", confirmerWidgetClass, new, NULL); SetKeyboardFocus(new, AxeTextDeckTop(PRIVATE(new,ed_deck))); /* The best we can do to keep Realize happy */ CalculateSize(aew, &aew->core.width, &aew->core.height); } static void CalculateSize(aew, width, height) AxeEditorWidget aew; Dimension *width, *height; { Cardinal child; Dimension wide, maxWidth, high, totalHeight = 0; for (child = 0; child < aew->composite.num_children; ++child) { if (XtIsManaged(aew->composite.children[child])) { XtVaGetValues(aew->composite.children[child], XtNwidth, &wide, XtNheight, &high, NULL); if (XtIsSubclass(aew->composite.children[child], axeTextDeckWidgetClass)) { maxWidth = wide; } if (XtIsSubclass(aew->composite.children[child], axeMenuButtonWidgetClass)) { continue; } totalHeight += high + PRIVATE(aew,internal_border_width); } } *width = maxWidth; *height = totalHeight - PRIVATE(aew,internal_border_width);; } static void Configure(aew, deltaHeight, initiator) AxeEditorWidget aew; Dimension deltaHeight; Widget initiator; { /* * This routine needs looking at; the addition of the * minibuffer MenuButton was done in a bit of a hurry. */ Cardinal child; Widget kid; Dimension width, height, border; Position x = -PRIVATE(aew,internal_border_width); Position y = -PRIVATE(aew,internal_border_width); Position atx, aty; for (child = 0; child < aew->composite.num_children; ++child) { kid = aew->composite.children[child]; if (XtIsManaged(kid)) { XtVaGetValues(kid, XtNheight, &height, NULL); if (XtIsSubclass(kid, axeTextDeckWidgetClass)) { height += deltaHeight; } if (kid == initiator) { kid->core.y = y; } else { aty = y; border = PRIVATE(aew,internal_border_width); if (XtIsSubclass(kid, asciiTextWidgetClass)) /* minibuffer */ { atx = PRIVATE(aew,mini_button)->core.width; width = aew->core.width - atx + 1; } else { atx = x; if (XtIsSubclass(kid, axeMenuButtonWidgetClass)) { width = kid->core.width; aty = y + PRIVATE(aew,internal_border_width); height = PRIVATE(aew,mini_buffer)->core.height; border = 0; } else { width = aew->core.width; } } XtConfigureWidget(kid, atx, aty, width, height, border); } if (!XtIsSubclass(kid, asciiTextWidgetClass)) /* order assumed */ { y += height + PRIVATE(aew,internal_border_width); } } } } static void Resize(aew) AxeEditorWidget aew; { Dimension oldWidth, oldHeight; CalculateSize(aew, &oldWidth, &oldHeight); Configure(aew, aew->core.height - oldHeight, (Widget) 0); } /* * This routine shouldn't be necessary, but it is because the size could * not be calculated in Initialize since the Table widget does not set its * core width and height fields in its Initialize procedure as it should. */ static void Realize(w, valueMask, attributes) Widget w; Mask *valueMask; XSetWindowAttributes *attributes; { AxeEditorWidget aew = (AxeEditorWidget) w; Cardinal child; Dimension width, height; (*((CompositeWidgetClass) (axeEditorWidgetClass->core_class.superclass))->core_class.realize) (w, valueMask, attributes); for (child = 0; child < aew->composite.num_children; ++child) { if (XtIsManaged(aew->composite.children[child])) { XtRealizeWidget(aew->composite.children[child]); } } CalculateSize(aew, &width, &height); XtVaSetValues(w, XtNwidth, width, XtNheight, height, NULL); /* * This is done here and not in Initialize for the benefit of AxeWindow. * UpdateTitles calls the change_callbacks list but AxeWindow can't * add to the list until after it has created its AxeEditor component, * hence if fileTitle were operative then the title bar would not be * correct until a change causing an update occurred. */ UpdateTitles(aew); } static void Destroy(w) Widget w; { int editor; for (editor = 0; editor < NUMBEROFEDITORS; ++editor) { if (w == EDITORS[editor]) { EDITORS[editor] = NULL; } } if (PRIVATE(w,info_timer)) { XtRemoveTimeOut(PRIVATE(w,info_timer)); } if (PRIVATE(w,font_table)) { FreeFontList(XtDisplay(w), PRIVATE(w,font_table)); } } static void NewEditor(aew) Widget aew; { int editor; Boolean spareSlot = False; WidgetList oldList; for (editor = 0; editor < NUMBEROFEDITORS; ++editor) { if (!EDITORS[editor]) { spareSlot = True; break; } } if (!spareSlot) { ++NUMBEROFEDITORS; if (NUMBEROFEDITORS > MAXEDITORS) { MAXEDITORS += INCREMENT; oldList = EDITORS; EDITORS = (WidgetList) XtRealloc((char *) oldList, MAXEDITORS * sizeof(Widget)); } editor = NUMBEROFEDITORS - 1; } EDITORS[editor] = aew; } /* ARGSUSED */ static XtGeometryResult GeometryManager(w, desired, allowed) Widget w; XtWidgetGeometry *desired, *allowed; { AxeEditorWidget aew = (AxeEditorWidget) XtParent(w); Dimension saveWidth, saveHeight, newWidth, newHeight; XtWidgetGeometry request; XtGeometryResult result; #define REQUESTS(flag) (desired->request_mode & flag) if (!XtIsSubclass(w, axeTextDeckWidgetClass)) { return XtGeometryNo; } if (REQUESTS(CWWidth)) { saveWidth = w->core.width; w->core.width = desired->width; } if (REQUESTS(CWHeight)) { saveHeight = w->core.height; w->core.height = desired->height; } CalculateSize(aew, &newWidth, &newHeight); request.request_mode = desired->request_mode; request.width = newWidth; request.height = newHeight; result = XtMakeGeometryRequest((Widget) aew, &request, (XtWidgetGeometry *) 0); if (REQUESTS(XtCWQueryOnly) || result != XtGeometryYes) { if(REQUESTS(CWWidth)) { w->core.width = saveWidth; } if (REQUESTS(CWHeight)) { w->core.height = saveHeight; } return result; } if (result == XtGeometryYes) { Configure(aew, 0, w); return XtGeometryYes; } return XtGeometryNo; #undef REQUESTS } static void InsertChild(w) Widget w; { CompositeWidget parent = (CompositeWidget) XtParent(w); /* Silently disallow unknown children; the 6 we know of are fileName */ /* infoBar, buttons, ed_deck, miniMenu, miniBuffer */ if (parent->composite.num_children < 6) { (*((CompositeWidgetClass) (axeEditorWidgetClass-> core_class.superclass))->composite_class.insert_child) (w); } } static void DeleteChild(w) Widget w; { Widget parent = XtParent(w); if (w == PRIVATE(parent,ed_deck)) { XtDestroyWidget(parent); } } static void SetKeyboardFocus(axeEditor, ed) Widget axeEditor, ed; { if (PRIVATE(axeEditor,focus_to_text)) { XtSetKeyboardFocus(PRIVATE(axeEditor,file_name), ed); XtSetKeyboardFocus(PRIVATE(axeEditor,info_bar), ed); XtSetKeyboardFocus(PRIVATE(axeEditor,menu_bar), ed); } } /* ARGSUSED */ static void DeckChange(w, client_data, call_data) Widget w; XtPointer client_data, call_data; { Widget axeEditor = (Widget) client_data; Widget ed = AxeTextDeckTop(PRIVATE(axeEditor,ed_deck)); SetKeyboardFocus(axeEditor, ed); if (PRIVATE(axeEditor,accelerateMini)) { MiniUninstallAccelerators(w); } UpdateTitles(axeEditor); RePopulateShowMenu(XtWidgetToApplicationContext(axeEditor)); } static Boolean CreatePopupLater(client_data) XtPointer client_data; { Widget menu = (Widget) client_data; XtCreatePopupChildProc create; XtVaGetValues(menu, XtNcreatePopupChildProc, &create, NULL); if (create) { (*create) (menu); } XtVaSetValues(menu, XtNcreatePopupChildProc, (XtCreatePopupChildProc) 0, NULL); return True; } static Widget MenuMade(menuName, menuParent) String menuName; Widget menuParent; { int n; for (n = 0; n < menuParent->core.num_popups; n++) { if (strcmp(XtName(menuParent->core.popup_list[n]), menuName) == 0) { return menuParent->core.popup_list[n]; } } return (Widget) 0; } static Widget MakeMenu(menuButton, menuParent, childProc, always) Widget menuButton, menuParent; XtCreatePopupChildProc childProc; Boolean always; { String menuName; Widget menu; XtVaGetValues(menuButton, XtNmenuName, &menuName, NULL); if (!(menu = MenuMade(menuName, menuParent))) { menu = XtVaCreatePopupShell(menuName, axeSimpleMenuWidgetClass, menuParent, NULL); XtVaSetValues(menu, XtNcreatePopupChildProc, childProc, NULL); AxeSimpleMenuStorePopperUpper(menu, AxeEditorParentOf(menuButton)); /* * No longer applies to any menu; retained just in case */ if (always) { XtAppAddWorkProc(XtWidgetToApplicationContext(menu), CreatePopupLater, (XtPointer) menu); } return menu; } return (Widget) 0; } static void MakeEvent(widget, event) Widget widget; XEvent *event; { Window root, child; unsigned int mask; XQueryPointer(XtDisplay(widget), XtWindow(widget), &root, &child, &event->xbutton.x_root, &event->xbutton.y_root, &event->xbutton.x, &event->xbutton.y, &mask); event->xbutton.type = ButtonRelease; } static void GenericAction(widget, client_data) Widget widget; XtPointer client_data; { XEvent event; String action = (String) client_data, params[1], p, q, proc; char routine[32], param[128]; Cardinal num_params; if ( (p = index(action, '(')) ) { strncpy(routine, action, p - action); routine[p - action] = '\0'; p += 1; q = index(p, ')'); strncpy(param, p, q - p); param[q - p] = '\0'; proc = routine; params[0] = param; num_params = strlen(param) == 0 ? 0 : 1; } else { params[0] = NULL; proc = action; num_params = 0; } MakeEvent(widget, &event); XtCallActionProc(widget, proc, &event, params, num_params); } /* ARGSUSED */ static void DoAction(widget, client_data, call_data) Widget widget; XtPointer client_data, call_data; { GenericAction(AxeTextDeckTop(PRIVATE(AxeSimpleMenuFetchPopperUpper(XtParent(widget)),ed_deck)), client_data); } static void AddBitmaps(widget, pixmap) Widget widget; Pixmap pixmap; { Pixmap lbitmap, rbitmap; XtVaGetValues(widget, XtNleftBitmap, &lbitmap, XtNrightBitmap, &rbitmap, NULL); if (!lbitmap) { XtVaSetValues(widget, XtNleftBitmap, pixmap, NULL); } if (!rbitmap) { XtVaSetValues(widget, XtNrightBitmap, pixmap, NULL); } } static void AddObjectBitmaps(obj, name) Widget obj; String name; { Pixmap bitmap; if (strcmp(name, "sbtext") == 0) { XtVaGetValues(obj, XtNleftBitmap, &bitmap, NULL); if (!bitmap) { XtVaSetValues(obj, XtNleftBitmap, CLASS(bwdArrow), NULL); } } else if (strcmp(name, "sftext") == 0) { XtVaGetValues(obj, XtNrightBitmap, &bitmap, NULL); if (!bitmap) { XtVaSetValues(obj, XtNrightBitmap, CLASS(fwdArrow), NULL); } } else if (strcmp(name, "sbsel") == 0) { XtVaGetValues(obj, XtNleftBitmap, &bitmap, NULL); if (!bitmap) { XtVaSetValues(obj, XtNleftBitmap, CLASS(bwdArrow), NULL); } } else if (strcmp(name, "sfsel") == 0) { XtVaGetValues(obj, XtNrightBitmap, &bitmap, NULL); if (!bitmap) { XtVaSetValues(obj, XtNrightBitmap, CLASS(fwdArrow), NULL); } } else if (strcmp(name, "mcentre") == 0) { AddBitmaps(obj, CLASS(vtCentre)); } else if (strcmp(name, "mhcentr") == 0) { AddBitmaps(obj, CLASS(hzCentre)); } } static void MakeOneDefaultMenu(menu, menuName) Widget menu; String menuName; { Widget obj; int button; for (button = 0; button < XtNumber(buttonActions); ++button) { if (!buttonActions[button].action && strcmp(menuName, buttonActions[button].name) == 0) { break; } } for (button += 1; button < XtNumber(buttonActions); ++button) { if (!buttonActions[button].action) { break; } obj = XtVaCreateManagedWidget(buttonActions[button].name, axeSmeBSBObjectClass, menu, NULL); XtAddCallback(obj, XtNcallback, DoAction, (XtPointer) buttonActions[button].action); AddObjectBitmaps(obj, buttonActions[button].name); } } static void MakeOneMenu(menu) Widget menu; { String menuName = XtName(menu); char resourceName[32]; String menuList; XtResource resource; Cardinal numChildren; /* * We don't know which button is popping up the menu, but we know the * menu name so we will generate something from that. Thus for menu * mMove we generate moveMenu and look for a resource moveMenuList. */ sprintf(resourceName, "%sMenu", menuName); resourceName[1] = tolower(resourceName[1]); resource.resource_name = &resourceName[1]; resource.resource_class = "Menu"; resource.resource_type = XtRString; resource.resource_size = sizeof(String); resource.resource_offset = 0; resource.default_type = XtRString; resource.default_addr = 0; XtVaGetApplicationResources(AxeSimpleMenuFetchPopperUpper(menu), (XtPointer) &menuList, &resource, 1, NULL); if (!menuList) { MakeOneDefaultMenu(menu, menuName); } else { FontListStruct *m, *userMenu = ParseFontList(menuList); int item; Widget obj; for (m = userMenu + 1; m->name; ++m) { if (*m->label == '+') { MakeOneDefaultMenu(menu, menuName); continue; } if (*m->label == '|') { XtVaCreateManagedWidget("line", smeLineObjectClass, menu, NULL); continue; } for (item = 0; item < XtNumber(buttonActions); ++item) { if (strcmp(buttonActions[item].name, m->name) == 0) { obj = XtVaCreateManagedWidget(buttonActions[item].name, axeSmeBSBObjectClass, menu, NULL); XtAddCallback(obj, XtNcallback, DoAction, (XtPointer) buttonActions[item].action); AddObjectBitmaps(obj, buttonActions[item].name); break; } } } XtVaGetValues(menu, XtNnumChildren, &numChildren, NULL); if (numChildren == 0) { char warning[64]; sprintf(warning, "The value of %s is invalid", &resourceName[1]); XtAppWarning(XtWidgetToApplicationContext(menu), warning); /* * Prevents permature exit if menu popped */ XtVaCreateManagedWidget("line", smeLineObjectClass, menu, NULL); } FreeFontList(XtDisplay(menu), userMenu); } } /* ARGSUSED */ static void Help(widget, event, params, num_params) Widget widget; XEvent *event; String *params; Cardinal *num_params; { if (*num_params) { AxeEditorHelpWindow(params[0], CLASS(menu_parent)); } else { AxeEditorHelpWindow((String) 0, CLASS(menu_parent)); } } /* ARGSUSED */ static void ChooseFont(widget, client_data, call_data) Widget widget; XtPointer client_data, call_data; { Pixmap leftBitmap; WidgetList children; Cardinal numChildren, child, choice; Widget axeEditor = AxeSimpleMenuFetchPopperUpper(XtParent(widget)); Widget lastFont; XFontStruct *fontStruct; XtVaGetValues(widget, XtNleftBitmap, &leftBitmap, NULL); if (leftBitmap) { return; } XtVaGetValues(XtParent(widget), XtNchildren, &children, XtNnumChildren, &numChildren, NULL); for (child = 0; child < numChildren; ++child) { XtVaGetValues(children[child], XtNleftBitmap, &leftBitmap, NULL); if (leftBitmap) { lastFont = children[child]; } if (widget == children[child]) { choice = child; } } if (!(fontStruct = PRIVATE(axeEditor,font_table)[choice].fontStruct)) { fontStruct = PRIVATE(axeEditor,font_table)[choice].fontStruct = XLoadQueryFont(XtDisplay(axeEditor), PRIVATE(axeEditor,font_table)[choice].name); } if (fontStruct) { XtVaSetValues(lastFont, XtNleftBitmap, (Pixmap) 0, NULL); XtVaSetValues(widget, XtNleftBitmap, CLASS(tickMark), NULL); XtVaSetValues(PRIVATE(axeEditor,ed_deck), XtNfont, fontStruct, NULL); } else { UpdateInfoBar(axeEditor, "Invalid font"); } } static void FreeFontList(display, list) Display *display; FontListStruct *list; { FontListStruct *l; for (l = list; l->name; ++l) { if (l->name != l->label) { XtFree(l->name); } XtFree(l->label); /* NB We didn't cause creation of the Default entry's XFontStruct */ if (l != list && l->fontStruct) { XFreeFont(display, l->fontStruct); } } XtFree((char *) list); } static FontListStruct* ParseFontList(fontList) String fontList; { int n, numberOfFonts, listLen = strlen(fontList); String i, fontString, parsed, p; Boolean skipping, quoting; char quoteChar; FontListStruct *fontTable; for (n = 0, i = fontList, skipping = True, quoting = False; i < fontList + strlen(fontList); ++i) { if (*i == '"' || *i == '\'') { if (quoting && (*i == quoteChar)) { quoting = False; } else if (!quoting) { quoting = True; quoteChar = *i; } } else if (*i == ' ' || *i == '\t') { if (!skipping) { ++n; skipping = !skipping; } } else if (skipping) { skipping = !skipping; } } numberOfFonts = n + 3; /* Default, no trailing space, NULL terminator */ fontTable = (FontListStruct *) XtMalloc(numberOfFonts * sizeof(FontListStruct)); fontString = (String) XtMalloc(listLen + 2); strcpy(fontString, fontList); strcat(fontString, " "); fontTable[0].label = XtNewString("Default"); fontTable[0].name = fontTable[0].label; parsed = (String) XtMalloc(listLen + 1); for (i = fontString, p = parsed, skipping = False, quoting = False, n = 0; i < fontString + strlen(fontList) + 1; ++i) { if (*i == '"' || *i == '\'') { if (quoting && (*i == quoteChar)) { quoting = False; } else if (!quoting) { quoting = True; quoteChar = *i; } } else if (!quoting && (*i == ' ' || *i == '\t')) { if (skipping) { *p = '\0'; if (!fontTable[n].label) { fontTable[n].label = parsed; } fontTable[n].name = parsed; fontTable[n].fontStruct = (XFontStruct *) 0; parsed = (String) XtMalloc(listLen + 1); p = parsed; } skipping = False; } else if (!quoting && *i == ':') { *p = '\0'; fontTable[n].label = parsed; parsed = (String) XtMalloc(listLen + 1); p = parsed; } else { *p++ = *i; if (!skipping) { skipping = !skipping; ++n; fontTable[n].label = 0; } } } fontTable[++n].name = (String) 0; XtFree(fontString); XtFree(parsed); return fontTable; } static void MakeFontMenu(menu) Widget menu; { Widget axeEditor = XtParent(menu); String fontList; Widget obj; FontListStruct *parseFontList, *p; XtVaGetValues(XtParent(menu), XtNfontList, &fontList, NULL); parseFontList = PRIVATE(axeEditor,font_table) = ParseFontList(fontList); XtVaGetValues(AxeTextDeckTop(PRIVATE(XtParent(menu),ed_deck)), XtNfont, &parseFontList[0].fontStruct, NULL); for (p = parseFontList; p->name; ++p) { obj = XtVaCreateManagedWidget(p->name, axeSmeBSBObjectClass, menu, XtNlabel, p->label, XtNleftBitmap, p == parseFontList ? CLASS(tickMark) : (Pixmap) 0, NULL); XtAddCallback(obj, XtNcallback, ChooseFont, (XtPointer) 0); } } /* ARGSUSED */ static void NewWindow(widget, event, params, num_params) Widget widget; XEvent *event; String *params; Cardinal *num_params; { Widget window = AxeEditorCreateWindow(widget, CLASS(menu_parent), (String) 0); XtPopup(window, XtGrabNone); if (*num_params > 0) { XtCallActionProc(AxeEditorEdWidget(AxeWindowAxeEditor(window)), "load-file", event, (String *) 0, (Cardinal) 0); } } /* ARGSUSED */ static void ForceClose(widget, client_data, call_data) Widget widget; XtPointer client_data, call_data; { XtDestroyWidget((Widget) client_data); RePopulateShowMenu(XtWidgetToApplicationContext(widget)); } static Boolean WindowClosed(w) Widget w; { Boolean closed; if (w && XtIsSubclass(XtParent(w), axeWindowWidgetClass)) { if ( (closed = AxeTextDeckIterate(PRIVATE(w,ed_deck), AxeSafeClose)) ) { XtDestroyWidget(w); } return closed; } else { return False; } } /* ARGSUSED */ static void CloseWindow(widget, event, params, num_params) Widget widget; XEvent *event; String *params; Cardinal *num_params; { Widget axeEditor = AxeEditorParentOf(widget); if (!WindowClosed(axeEditor)) { ConfirmerRequestConfirmation(PRIVATE(axeEditor,confirmer), "There are unsaved changes", "close unsaved", ForceClose, "unused", NULL, (XtPointer) axeEditor); } { RePopulateShowMenu(XtWidgetToApplicationContext(widget)); } } static Boolean AllWindowsClosed(w) Widget w; { Boolean result = False; if (w && XtIsSubclass(XtParent(w), axeWindowWidgetClass)) { result = AxeEditorIterate(AxeSafeClose); } return result; } /* ARGSUSED */ static void ForceCloseAll(widget, client_data, call_data) Widget widget; XtPointer client_data, call_data; { AxeEditorIterate(AxeForceClose); RePopulateShowMenu(XtWidgetToApplicationContext(widget)); } /* ARGSUSED */ static void CloseAll(widget, event, params, num_params) Widget widget; XEvent *event; String *params; Cardinal *num_params; { Widget axeEditor= AxeEditorParentOf(widget); int editor; if (!AllWindowsClosed(axeEditor)) { /* NB axeEditor may have been deleted, so find another. */ /* being_destroyed field is used since only Phase 1 */ /* of XtDestroyWidget for any windows destroyed will */ /* have been executed at this juncture. */ for (editor = 0; editor < NUMBEROFEDITORS; ++editor) { axeEditor = EDITORS[editor]; if (axeEditor && !axeEditor->core.being_destroyed) { ConfirmerRequestConfirmation(PRIVATE(axeEditor,confirmer), "There are unsaved changes", "close unsaved", ForceCloseAll, "unused", NULL, (XtPointer) axeEditor); break; } } } /* * This catches the case where the confirmer is necessary but * the user selects "cancel", but it also means that the menu * is generated twice if "close unsaved" is chosen - once from * this call and once from the ForceClassAll callback. */ RePopulateShowMenu(XtWidgetToApplicationContext(widget)); } /* ARGSUSED */ static void IconifyAll(widget, event, params, num_params) Widget widget; XEvent *event; String *params; Cardinal *num_params; { Boolean iconifying = (strcmp(params[0], "I") == 0); Display *display; Widget shell; Window window; int editor; for (editor = 0; editor < NUMBEROFEDITORS; ++editor) { if (EDITORS[editor]) { shell = ShellOf(EDITORS[editor]); display = XtDisplay(shell); window = XtWindow(shell); if (iconifying) { XIconifyWindow(display, window, XDefaultScreen(display)); } else { XMapWindow(display, window); } } } } /* ARGSUSED */ static void Restack(widget, event, params, num_params) Widget widget; XEvent *event; String *params; Cardinal *num_params; { printf("Restack not implemented\n"); } /* ARGSUSED */ static void NewBuffer(widget, event, params, num_params) Widget widget; XEvent *event; String *params; Cardinal *num_params; { Widget axeEditor = AxeEditorParentOf(widget), ed; XFontStruct *font; char *assocFile, assocDir[MAXPATHLEN]; XtVaGetValues(PRIVATE(axeEditor,ed_deck), XtNfont, &font, NULL); ed = XtVaCreateManagedWidget("ed", axeTextWidgetClass, PRIVATE(axeEditor,ed_deck), XtNfont, font, NULL); if ( (assocFile = AxeTextGetAssociatedFile(widget)) ) { strcpy(assocDir, assocFile); assocDir[rindex(assocDir, '/') - assocDir] = '\0'; XtVaSetValues(ed, XtNassociatedDirectory, assocDir, NULL); } if (*num_params > 0) { XtCallActionProc(ed, "load-file", event, (String *) 0, (Cardinal) 0); } } /* ARGSUSED */ static void ForceCloseTopBuffer(widget, client_data, call_data) Widget widget; XtPointer client_data, call_data; { Widget axeEditor = (Widget) client_data; AxeTextDeckCloseTop(PRIVATE(axeEditor,ed_deck)); RePopulateShowMenu(XtWidgetToApplicationContext(axeEditor)); } /* ARGSUSED */ static void CloseBufferSaved(widget, client_data, call_data) Widget widget; XtPointer client_data, call_data; { Widget axeEditor = (Widget) client_data; if (!AxeTextSaveFile(AxeTextDeckTop(PRIVATE(axeEditor,ed_deck)))) { ConfirmerRequestConfirmation(PRIVATE(axeEditor,confirmer), "There are unsavable changes", "acknowledge", ConfirmerPopdown, "unused", NULL, (XtPointer) axeEditor); } else { ForceCloseTopBuffer((XtPointer) 0, (XtPointer) axeEditor, (XtPointer) 0); } } /* ARGSUSED */ static void CloseBuffer(widget, event, params, num_params) Widget widget; XEvent *event; String *params; Cardinal *num_params; { Widget axeEditor = AxeEditorParentOf(widget); Widget deck = PRIVATE(axeEditor,ed_deck); Widget buffer = AxeTextDeckTop(deck); Cardinal numChildren; XtVaGetValues(deck, XtNnumChildren, &numChildren, NULL); if (numChildren == 1) { CloseWindow(widget, event, params, num_params); return; } if (AxeTextIsModified(buffer)) { if (AxeTextGetAssociatedFile(buffer)) { ConfirmerRequestConfirmation(PRIVATE(axeEditor,confirmer), "There are unsaved changes", "close unsaved", ForceCloseTopBuffer, "close saved", CloseBufferSaved, (XtPointer) axeEditor); } else { ConfirmerRequestConfirmation(PRIVATE(axeEditor,confirmer), "There are unsavable changes", "close unsaved", ForceCloseTopBuffer, "unused", NULL, (XtPointer) axeEditor); } } else { ForceCloseTopBuffer((XtPointer) 0, (XtPointer) axeEditor, (XtPointer) 0); } } static Widget ShellOf(axeEditor) Widget axeEditor; { Widget w; for (w = XtParent(axeEditor) ;; w = XtParent(w)) { if (XtIsShell(w)) { break; } } return w; } /* ARGSUSED */ static void RaiseWindow(widget, client_data, call_data) Widget widget; XtPointer client_data, call_data; { Widget axeEditor = AxeEditorOf((Widget) client_data); Widget shell = ShellOf(axeEditor); AxeTextDeckRaise(PRIVATE(axeEditor,ed_deck), (Widget) client_data); XMapRaised(XtDisplay(shell), XtWindow(shell)); } static void CopyShowMenuChildren(children, numChildren) WidgetList *children; Cardinal *numChildren; { WidgetList copyChildren; Cardinal child; XtVaGetValues(CLASS(show_menu), XtNchildren, ©Children, XtNnumChildren, numChildren, NULL); *children = (WidgetList) XtMalloc(*numChildren * sizeof(Widget)); for (child = 0; child < *numChildren; ++child) { (*children)[child] = copyChildren[child]; } } /* ARGSUSED */ static Boolean PopulateShowMenu(client_data) XtPointer client_data; { WidgetList copyChildren; Cardinal numChildren; int child, editor, windows, n; AxeTextDeckList list, lst; String homeFile; Pixmap leftBitmap; Widget obj, line = 0; AxeEditorWidgetClass wc = (AxeEditorWidgetClass) axeEditorWidgetClass; if (!CLASS(show_menu)) { return True; } CopyShowMenuChildren(©Children, &numChildren); /* * I'm not sure that I understand this, but if I deleted the old menu * objects here first, then app crashed with X_ConfigureWindow error, * although it was fine when this routine was a callback routine that * was invoked via the triggering of the MenuButton's notify action. */ for (windows = 0, editor = 0; editor < NUMBEROFEDITORS; ++editor) { if (EDITORS[editor]) { list = AxeTextDeckListOf(PRIVATE(EDITORS[editor],ed_deck)); for (lst = list; (*lst).file; ++lst) { leftBitmap = AxeTextIsModified((*lst).widget) ? CLASS(modMark) : (Pixmap) 0; homeFile = HomeFile((*lst).file); obj = XtVaCreateManagedWidget(homeFile, axeSmeBSBObjectClass, CLASS(show_menu), XtNleftBitmap, leftBitmap, NULL); XtAddCallback(obj, XtNcallback, RaiseWindow, (XtPointer) (*lst).widget); if (homeFile != (*lst).file) { XtFree(homeFile); } XtFree((char *) (*lst).file); } XtFree((char *) list); line = XtVaCreateManagedWidget("line", smeLineObjectClass, CLASS(show_menu), NULL); ++windows; } } if (line) { /* If the menu is non-empty then the last line was one too many */ XtDestroyWidget(line); } else { /* Can't have an empty menu so give it a dummy entry */ XtVaCreateManagedWidget("line", smeLineObjectClass, CLASS(show_menu), NULL); } /* See comment above */ for (child = 0; child < numChildren; ++child) { XtDestroyWidget(copyChildren[child]); } XtFree((char *) copyChildren); CLASS(show_work_proc) = False; for (n = 0; n < CLASS(show_menu_callbacks); ++n) { (*CLASS(show_menu_callback_list)[n].cbr.callback) (CLASS(show_menu_callback_list)[n].widget, CLASS(show_menu_callback_list)[n].cbr.closure, (XtPointer) windows); } return True; } static void RePopulateShowMenu(app) XtAppContext app; { if (!CLASS(show_work_proc)) { (void) XtAppAddWorkProc(app, PopulateShowMenu, (XtPointer) 0); CLASS(show_work_proc) = True; } } /* ARGSUSED */ static void OnShowPopup(widget, client_data, call_data) Widget widget; XtPointer client_data, call_data; { Widget axeEditor = AxeSimpleMenuFetchPopperUpper(widget); Widget ed; WidgetList children; Cardinal numChildren, child; XtCallbackList callback; if (axeEditor) { ed = AxeEditorEdWidget(axeEditor); } XtVaGetValues(CLASS(show_menu), XtNchildren, &children, XtNnumChildren, &numChildren, NULL); for (child = 0; child < numChildren; ++child) { if (!XtIsSubclass(children[child], axeSmeBSBObjectClass)) { continue; } XtVaGetValues(children[child], XtNcallback, &callback, NULL); XtVaSetValues(children[child], XtNrightBitmap, axeEditor ? (((Widget) callback[0].closure == ed) ? CLASS(tickMark) : (Pixmap) 0) : (Pixmap) 0, NULL); } } static void MakeShowMenu(menu) Widget menu; { Cardinal numChildren; XtAddCallback(menu, XtNpopupCallback, OnShowPopup, (XtPointer) 0); XtVaGetValues(menu, XtNnumChildren, &numChildren, NULL); if (numChildren == 0) { PopulateShowMenu((XtPointer) 0); } } static Boolean BuffersSaved(w) Widget w; { return AxeTextDeckIterate(PRIVATE(w,ed_deck), AxeSave); } /* ARGSUSED */ static void SaveAndClose(widget, event, params, num_params) Widget widget; XEvent *event; String *params; Cardinal *num_params; { Widget axeEditor = AxeEditorParentOf(widget); Widget axeText; int editor; Cardinal numChildren; XtVaGetValues(PRIVATE(axeEditor,ed_deck), XtNnumChildren, &numChildren, NULL); if (*num_params == 1) { if (strcmp(params[0], "window") == 0 || (strcmp(params[0], "buffer") == 0 && numChildren == 1)) { (void) BuffersSaved(axeEditor); if (!WindowClosed(axeEditor)) { ConfirmerRequestConfirmation(PRIVATE(axeEditor,confirmer), "There are unsavable buffers", "acknowledge", ConfirmerPopdown, "unused", NULL, (XtPointer) axeEditor); } } else if (strcmp(params[0], "buffer") == 0) { axeText = AxeEditorEdWidget(axeEditor); if (AxeTextSaveFile(axeText)) { XtDestroyWidget(axeText); } else { ConfirmerRequestConfirmation(PRIVATE(axeEditor,confirmer), "There are unsavable changes", "acknowledge", ConfirmerPopdown, "unused", NULL, (XtPointer) axeEditor); } } } else if (*num_params == 0 && !AxeEditorIterate(AxeSaveAndClose)) { (void) AxeEditorIterate(AxeSafeClose); /* NB axeEditor may have been deleted, so find another. */ /* being_destroyed field is used since only Phase1 */ /* of XtDestroyWidget for any windows destroyed will */ /* have been executed at this juncture. */ for (editor = 0; editor < NUMBEROFEDITORS; ++editor) { axeEditor = EDITORS[editor]; if (!axeEditor->core.being_destroyed) { ConfirmerRequestConfirmation(PRIVATE(axeEditor,confirmer), "There are unsavable buffers", "acknowledge", ConfirmerPopdown, "unused", NULL, (XtPointer) axeEditor); break; } } } RePopulateShowMenu(XtWidgetToApplicationContext(widget)); } /* ARGSUSED */ static void SaveAll(widget, event, params, num_params) Widget widget; XEvent *event; String *params; Cardinal *num_params; { Widget axeEditor = AxeEditorParentOf(widget);; if (!AxeEditorIterate(AxeSave)) { ConfirmerRequestConfirmation(PRIVATE(axeEditor,confirmer), "There are unsavable buffers", "acknowledge", ConfirmerPopdown, "unused", NULL, (XtPointer) axeEditor); } else { UpdateInfoBar(axeEditor, "All buffers saved"); } } static void MakeLogoMenu(menu) Widget menu; { XtVaCreateManagedWidget(QVERSION, axeSmeBSBObjectClass, menu, NULL); XtVaCreateManagedWidget("by", axeSmeBSBObjectClass, menu, NULL); XtVaCreateManagedWidget("Jim Wight", axeSmeBSBObjectClass, menu, NULL); XtVaCreateManagedWidget("Department of Computing Science", axeSmeBSBObjectClass, menu, NULL); XtVaCreateManagedWidget("University of Newcastle upon Tyne", axeSmeBSBObjectClass, menu, NULL); XtVaCreateManagedWidget("", axeSmeBSBObjectClass, menu, NULL); } static void MakeMiniSubMenu(menu, menuList) Widget menu; FontListStruct *menuList; { char action[80]; Widget obj; FontListStruct *p; for (p = menuList + 1; p->name; ++p) { if (*p->label == '+') { if (!CLASS(default_mini_menu)) { CLASS(default_mini_menu) = ParseFontList(defaultMiniMenu); } MakeMiniSubMenu(menu, CLASS(default_mini_menu)); continue; } if (*p->label == '|') { XtVaCreateManagedWidget("line", smeLineObjectClass, menu, NULL); continue; } obj = XtVaCreateManagedWidget(p->label, axeSmeBSBObjectClass, menu, NULL); if (strncmp(p->name, "mini-", 5) != 0) { sprintf(action, "mini-shell(%s)", p->name); if (p->name != p->label) { XtFree(p->name); } p->name = XtNewString(action); } XtAddCallback(obj, XtNcallback, DoAction, (XtPointer) p->name); } } static void MakeMiniMenu(menu) Widget menu; { String miniMenuList; FontListStruct *miniMenu; static XtResource resource = {XtNminiMenu, XtCMiniMenu, XtRString, sizeof(String), (Cardinal) 0, XtRString, defaultMiniMenu}; /* * The miniMenu resource is an application resource, not an AxeEditor * resource. We do it this way because we can't get a handle onto the * invoking AxeEditor widget. */ XtVaGetApplicationResources(menu, (XtPointer) &miniMenuList, &resource, 1, NULL); CLASS(mini_menu) = ParseFontList(miniMenuList); MakeMiniSubMenu(menu, CLASS(mini_menu)); } /* ARGSUSED */ static void ButtonAction(widget, client_data, call_data) Widget widget; XtPointer client_data, call_data; { GenericAction(AxeEditorEdWidget(AxeEditorParentOf(widget)), client_data); } static void MakeButtons(parent, buttonList) Widget parent; FontListStruct *buttonList; { FontListStruct *p; Widget butt; int len, button; if (PRIVATE(XtParent(parent),button_list)) { for (p = buttonList + 1; p->name; ++p) { if (*(p->name) == '-' || *(p->name) == ';') { continue; } else if (p->name[(len = strlen(p->name)) - 1] == ';') { len -= 1; } for (button = 0; button < XtNumber(buttonActions); ++button) { if (strncmp(buttonActions[button].name, p->name, len) == 0) { butt = XtVaCreateManagedWidget(buttonActions[button].name, axeCommandWidgetClass, parent, NULL); XtAddCallback(butt, XtNcallback, ButtonAction, (XtPointer) buttonActions[button].action); break; } } if (button >= XtNumber(buttonActions)) { printf("Invalid button name %s in buttonList\n", p->name); } } } else { for (button = 0; button < XtNumber(buttonActions); ++button) { if (buttonActions[button].action) { butt = XtVaCreateManagedWidget(buttonActions[button].name, axeCommandWidgetClass, parent, NULL); XtAddCallback(butt, XtNcallback, ButtonAction, (XtPointer) buttonActions[button].action); } } } } static String ButtonListLayout(widget, menuButtonsLayout, list) Widget widget; char *menuButtonsLayout; FontListStruct **list; { String buttonLayout = (String) XtMalloc(strlen(menuButtonsLayout) + strlen(commandButtonsLayout) + 1); FontListStruct *buttonList = ParseFontList(PRIVATE(widget,button_list)), *p; int col = 0, row = 1, len; Boolean newRow = False; char buf[16]; strcpy(buttonLayout, menuButtonsLayout); for (p = buttonList + 1; p->name; ++p) { if (*(p->name) == '-' ) { ++col; continue; } else if (*(p->name) == ';') { ++row; col = 0; continue; } else if (p->name[(len = strlen(p->name)) - 1] == ';') { strncat(buttonLayout, p->name, len - 1); newRow = True; } else { strcat(buttonLayout, p->name); } sprintf(buf, " %d %d wW;", col, row); strcat(buttonLayout, buf); if (newRow) { ++row; col = 0; newRow = False; } else { ++col; } } *list = buttonList; return buttonLayout; } static XpTableLoc MakeButtonsLayout(widget, buttonList) Widget widget; FontListStruct **buttonList; { String layoutString; XpTableLoc tableLoc; Boolean toFree = True; FontListStruct *menuList = ParseFontList(PRIVATE(widget,menu_list)), *p; char menuButtonsLayout[1024]; char *mbl; int n, m; Boolean axeLogoSeen = False, matched; menuButtonsLayout[0] = '\0'; mbl = menuButtonsLayout; for (n = 0, p = menuList + 1; p->name; ++p, ++n) { matched = False; for (m = 0; chosenMenus[m].name; ++m) { if (strcmp(p->name, chosenMenus[m].name) == 0) { chosenMenus[m].chosen = True; matched = True; sprintf(mbl, "%sMenu %d 0 wW; ", p->name, n); mbl += strlen(mbl); break; } } if (!matched && strcmp(p->name, "logo") == 0) { axeLogoSeen = True; sprintf(mbl, "axeLogo %d 0 1 8; ", n); mbl += strlen(mbl); } } if (!axeLogoSeen) { sprintf(mbl, "axeLogo %d 0 1 8; ", n); } if (PRIVATE(widget,button_list)) { layoutString = ButtonListLayout(widget, menuButtonsLayout, buttonList); } else if (PRIVATE(widget,buttons)) { layoutString = (String) XtMalloc(strlen(menuButtonsLayout) + strlen(commandButtonsLayout) + 1); strcpy(layoutString, menuButtonsLayout); strcat(layoutString, commandButtonsLayout); } else { layoutString = menuButtonsLayout; toFree = False; } tableLoc = XpTableLocParse(layoutString); if (toFree) { XtFree(layoutString); } FreeFontList(XtDisplay(widget), menuList); return tableLoc; } /************************************************************* * * utilities * *************************************************************/ static Widget AxeEditorOf(widget) Widget widget; { Widget w; for (w = widget; w; w = XtParent(w)) { if (XtIsSubclass(w, axeEditorWidgetClass)) { return w; } } return (Widget) 0; } static void UpdateFileName(aew, file) Widget aew; String file; { if (PRIVATE(aew,suppressFilename)) { return; } XtVaSetValues(PRIVATE(aew,file_name), XtNlabel, file, NULL); } static void UpdateTitles(aew) Widget aew; { Widget top = AxeTextDeckTop(PRIVATE(aew,ed_deck)); String file, fileName, homeFile; Boolean freeFile = False; if (!(file = AxeTextGetAssociatedFile(top))) { file = XtNewString(noname); freeFile = True; } homeFile = HomeFile(file); fileName = XtMalloc(strlen(homeFile) + 2 + 1); *fileName = '\0'; if (AxeTextIsModified(top)) { strcat(fileName, "* "); } strcat(fileName, homeFile); UpdateFileName(aew, fileName); XtCallCallbackList(aew, PRIVATE(aew,change_callbacks), (XtPointer) fileName); XtFree(fileName); if (homeFile != file) { XtFree(homeFile); } if (freeFile) { XtFree(file); } } /*ARGSUSED*/ static void InfoBarTimeout(client_data, id) XtPointer client_data; XtIntervalId *id; { Widget axeEditor = (Widget) client_data; PRIVATE(axeEditor,info_timer) = (XtIntervalId) 0; XtVaSetValues(PRIVATE(axeEditor,info_bar), XtNlabel, QVERSION, NULL); } /* ARGSUSED */ static void UpdateInfo(w, event, params, num_params) Widget w; XEvent *event; String *params; Cardinal *num_params; { UpdateInfoBar(AxeEditorOf(w), params[0]); } static void UpdateInfoBar(w, info) Widget w; String info; { if (PRIVATE(w,suppressInfobar)) { return; } if (PRIVATE(w,info_timer)) { XtRemoveTimeOut(PRIVATE(w,info_timer)); } XtVaSetValues(PRIVATE(w,info_bar), XtNlabel, info ? info : QVERSION, NULL); if (PRIVATE(w,info_timeout)) { PRIVATE(w,info_timer) = XtAppAddTimeOut(XtWidgetToApplicationContext(w), (unsigned long) PRIVATE(w,info_timeout) * 1000, InfoBarTimeout, (XtPointer) w); } } static Atom AxeisUserAtom(display) Display *display; { char propName[1024], *user; strcpy(propName, "AXE_AXINFO"); if ( (user = getenv("USER")) ) { strcat(propName, "_"); strcat(propName, user); } return XInternAtom(display, propName, False); } /************************************************************* * * Minibuffer * *************************************************************/ /* Caller must free return value */ static String CurrentDir(w) Widget w; { Widget axeEditor = AxeEditorOf(w); String assocFile, dir, filePart; if (assocFile = AxeTextGetAssociatedFile(AxeTextDeckTop(PRIVATE(axeEditor,ed_deck)))) { dir = XtNewString(assocFile); filePart = rindex(dir, '/'); if (filePart) { *(filePart + 1) = '\0'; } return dir; } else { return XtNewString(CLASS(current_dir)); } } /* NB Caller must free return value if different from input */ static String HomeFile(file) String file; { String new; if (strlen(file) > CLASS(home_dir_len) && strncmp(file, CLASS(home_dir), CLASS(home_dir_len)) == 0) { new = XtMalloc(strlen(file) + 3); strcpy(new, "~"); strcat(new, &file[CLASS(home_dir_len)]); return new; } return file; } static void MiniDisplayCaret(w, On) Widget w; Boolean On; { XtVaSetValues(PRIVATE(AxeEditorOf(w),mini_buffer), XtNdisplayCaret, On, NULL); } static void MiniEnable(w, prompt) Widget w; String prompt; { Widget axeEditor = AxeEditorOf(w); if (!PRIVATE(axeEditor,suppressMinibuffer)) { Widget input = PRIVATE(axeEditor,mini_buffer); XtVaSetValues(input, XtNdisplayCaret, True, XtNstring, prompt, NULL); XawTextSetInsertionPoint(input, strlen(prompt)); } } static XawTextPosition MiniAppend(w, text) Widget w; String text; { XawTextBlock textBlock; XawTextPosition textPos, textRtn; Widget input = PRIVATE(AxeEditorOf(w),mini_buffer); textPos = XawTextGetInsertionPoint(input); textBlock.firstPos = 0; textBlock.length = strlen(text); textBlock.ptr = text; textBlock.format = FMT8BIT; if ((textRtn = XawTextReplace(input, textPos, textPos, &textBlock)) == XawEditDone) { XawTextSetInsertionPoint(input, textPos + textBlock.length); } return textRtn; } static void MiniInstallAccelerators(w) Widget w; { Widget axeEditor = AxeEditorOf(w); if (!PRIVATE(axeEditor,suppressMinibuffer)) { XtVaSetValues(w, XtNdisplayCaret, False, NULL); XtInstallAccelerators(w, PRIVATE(axeEditor,mini_buffer)); PRIVATE(axeEditor,accelerateMini) = True; } } static void MiniUninstallAccelerators(w) Widget w; { Widget axeEditor = AxeEditorOf(w); if (!PRIVATE(axeEditor,suppressMinibuffer)) { XtVaSetValues(AxeTextDeckTop(PRIVATE(axeEditor,ed_deck)), XtNtranslations, PRIVATE(axeEditor,defaultTextTranslations), XtNdisplayCaret, True, NULL); XtVaSetValues(PRIVATE(axeEditor,mini_buffer), XtNdisplayCaret, False, NULL); PRIVATE(axeEditor,accelerateMini) = False; } } static void MiniInitInput(w) Widget w; { String dir = CurrentDir(w); String home = HomeFile(dir); (void) MiniAppend(w, home); if (home != dir) { XtFree(home); } XtFree(dir); } static String MiniInput(w, skip) Widget w; Boolean skip; { String input, p; XtVaGetValues(PRIVATE(AxeEditorOf(w),mini_buffer), XtNstring, &input, NULL); for (p = input + strlen(input) - 1; p >= input; --p) { if (*p != ' ' && *p != '\t') { break; } else { *p = 0; } } if (skip) { for (p = &input[1]; *p == ' '; ++p) {} return p; } else { return input; } } /*ARGSUSED*/ static void miniSelect(w, event, params, num_params) Widget w; XEvent *event; String *params; Cardinal *num_params; { if (!PRIVATE(AxeEditorOf(w),suppressMinibuffer)) { MiniDisplayCaret(w, True); MiniInstallAccelerators(w); } } /*ARGSUSED*/ static void miniClear(w, event, params, num_params) Widget w; XEvent *event; String *params; Cardinal *num_params; { if (!PRIVATE(AxeEditorOf(w),suppressMinibuffer)) { MiniEnable(w, ""); MiniInstallAccelerators(w); } } /*ARGSUSED*/ static void miniSearch(w, event, params, num_params) Widget w; XEvent *event; String *params; Cardinal *num_params; { if (!PRIVATE(AxeEditorOf(w),suppressMinibuffer)) { if (*num_params > 0 && (strcmp(params[0], "backward") == 0)) { MiniEnable(w, "?"); } else { MiniEnable(w, "/"); } MiniInstallAccelerators(w); } } static void MiniSearch(w, searchDirection) Widget w; XawTextScanDirection searchDirection; { Widget text = AxeTextDeckTop(PRIVATE(AxeEditorOf(w),ed_deck)); regexp *compexp; String nomatch, regexpr = MiniInput(w, False); XawTextPosition nobegin, noend; Boolean found; compexp = 0; if (compexp = regcomp(®expr[1])) { nomatch = 0; found = AxeiiTextReSearch(text, (searchDirection == XawsdRight), ®expr[1], compexp, &nomatch, &nobegin, &noend); if (!RegError && !found) { UpdateInfoBar(AxeEditorOf(w), "Search string not found"); } XtFree(nomatch); } if (RegError) { UpdateInfoBar(AxeEditorOf(w), RegError); XBell(XtDisplay(w), 100); RegError = 0; } XtFree((char *) compexp); } static void MiniGoto(w) Widget w; { AxeTextGotoLine(AxeTextDeckTop(PRIVATE(AxeEditorOf(w),ed_deck)), atoi(MiniInput(w, False))); } /*ARGSUSED*/ static void miniInsert(w, event, params, num_params) Widget w; XEvent *event; String *params; Cardinal *num_params; { if (!PRIVATE(AxeEditorOf(w),suppressMinibuffer)) { MiniEnable(w, "r "); MiniInitInput(w); MiniInstallAccelerators(w); } } static void MiniInsert(w) Widget w; { Widget axeEditor = AxeEditorOf(w); Widget axe = AxeTextDeckTop(PRIVATE(axeEditor,ed_deck)); String insertFile = AxeEditorExpandName(MiniInput(w, True)); Boolean undo; void (*proc)(); XtVaGetValues(axe, XtNundo, &undo, NULL); if ( (proc = AxeiiTextUndoPreInsert(axe)) ) { (*proc)(axe); } if (!InsertFileNamed(axe, insertFile)) { UpdateInfoBar(axeEditor, "Error inserting file"); XBell(XtDisplay(w), 100); } XtFree(insertFile); } /*ARGSUSED*/ static void miniSaveAs(w, event, params, num_params) Widget w; XEvent *event; String *params; Cardinal *num_params; { if (!PRIVATE(AxeEditorOf(w),suppressMinibuffer)) { MiniEnable(w, "w "); MiniInitInput(w); MiniInstallAccelerators(w); } } static void MiniSaveAs(w) Widget w; { Widget axeEditor = AxeEditorOf(w); String saveAs = AxeEditorExpandName(MiniInput(w, True)); FileNominatorStruct fnomStruct; AxeTextFileToNominatorStruct(saveAs, &fnomStruct); if (!fnomStruct.directoryPart) { UpdateInfoBar(axeEditor, "Invalid pathname"); XBell(XtDisplay(w), 100); } else if (!fnomStruct.filenamePart) { UpdateInfoBar(axeEditor, "Pathname is a directory"); XBell(XtDisplay(w), 100); } else { (void) AxeTextSaveAsFile(AxeEditorEdWidget(axeEditor), &fnomStruct); } XtFree(saveAs); AxeTextFreeNominatorStruct(&fnomStruct); } /*ARGSUSED*/ static void miniLoad(w, event, params, num_params) Widget w; XEvent *event; String *params; Cardinal *num_params; { if (!PRIVATE(AxeEditorOf(w),suppressMinibuffer)) { MiniEnable(w, "e "); MiniInitInput(w); MiniInstallAccelerators(w); } } /* ARGSUSED */ static void MiniForceLoad(widget, client_data, call_data) Widget widget; XtPointer client_data, call_data; { Widget mini = (Widget) client_data; Widget axeEditor = AxeEditorOf(mini); String loadFile; FileNominatorStruct fnomStruct; loadFile = AxeEditorExpandName(MiniInput(mini, True)); AxeTextFileToNominatorStruct(loadFile, &fnomStruct); if (!fnomStruct.directoryPart) { UpdateInfoBar(axeEditor, "Invalid pathname"); XBell(XtDisplay(mini), 100); } else if (!fnomStruct.filenamePart) { UpdateInfoBar(axeEditor, "Pathname is a directory"); XBell(XtDisplay(mini), 100); } else { AxeTextLoadFile(AxeEditorEdWidget(axeEditor), &fnomStruct); } XtFree(loadFile); AxeTextFreeNominatorStruct(&fnomStruct); } static void MiniLoad(w) Widget w; { Widget axeEditor = AxeEditorOf(w); if (AxeTextIsModified(AxeTextDeckTop(PRIVATE(axeEditor,ed_deck)))) { ConfirmerRequestConfirmation(PRIVATE(axeEditor,confirmer), "There are unsaved changes", "Discard changes", MiniForceLoad, "unused", NULL, (XtPointer) w); } else { MiniForceLoad((XtPointer) 0, (XtPointer) w, (XtPointer) 0); } } static void MiniPipeOrShell(w, cmd, params, num_params) Widget w; String cmd, *params; Cardinal *num_params; { int i, len; char param[80]; Boolean commit = False; if (!PRIVATE(AxeEditorOf(w),suppressMinibuffer)) { MiniEnable(w, cmd); for (i = 0; i < *num_params; ++i) { if (i == (*num_params) - 1 && (len = strlen(params[i])) >= 1 && params[i][len - 1] == '\n') { strcpy(param, params[i]); param[len - 1] = '\0'; MiniAppend(w, param); commit = True; } else { MiniAppend(w, params[i]); MiniAppend(w, " "); } } MiniInstallAccelerators(w); if (commit) { MiniCommit(w, (XEvent *) 0, (String *) 0, (Cardinal *) 0); } } } /*ARGSUSED*/ static void miniPipe(w, event, params, num_params) Widget w; XEvent *event; String *params; Cardinal *num_params; { MiniPipeOrShell(w, "| ", params, num_params); } static void ClosePipes(output, input, errput) int *output, *input, *errput; { if (output[0] != -1) close(output[0]); if (output[1] != -1) close(output[1]); if (input[0] != -1) close(input[0]); if (input[1] != -1) close(input[1]); if (errput[0] != -1) close(errput[0]); if (errput[1] != -1) close(errput[1]); } static Boolean ExecSubProcess(widget, command, output, input, errput) Widget widget; String command; int *output, *input, *errput; { output[0] = output[1] = input[0] = input[1] = errput[0] = errput[1] = -1; if (pipe(output) == -1 || pipe(input) == -1 || pipe(errput) == -1) { ClosePipes(output, input, errput); return False; } switch(fork()) { case -1: ClosePipes(output, input, errput); return False; case 0: /* Child */ (void) close(XConnectionNumber(XtDisplay(widget))); if (close(0) == 0 && dup(output[0]) == 0 && close(output[0]) == 0 && close(output[1]) == 0 && close(1) == 0 && dup(input[1]) == 1 && close(input[0]) == 0 && close(input[1]) == 0 && close(2) == 0 && dup(errput[1]) == 2 && close(errput[0]) == 0 && close(errput[1]) == 0) { char *assocFile, assocDir[MAXPATHLEN]; if ( (assocFile = AxeTextGetAssociatedFile(widget)) ) { strcpy(assocDir, assocFile); assocDir[rindex(assocDir, '/') - assocDir] = '\0'; (void) chdir(assocDir); } (void) execl("/bin/sh", "sh", "-c", command, (char *) 0); } ClosePipes(output, input, errput); exit(0); default: /* Parent */ if (close(output[0]) == -1 || close(input[1]) == -1 || close(errput[1]) == -1) { ClosePipes(output, input, errput); return False; } } return True; } static void ChildInput(client_data, source, id) XtPointer client_data; int *source; XtInputId *id; { struct childInfo *ci = (struct childInfo*) client_data; char buffer[1024]; int nread; XawTextBlock block; XawTextPosition pos; void (*proc)(); nread = read(*source, buffer, sizeof(buffer)); if (nread == -1) { UpdateInfoBar(AxeEditorOf(ci->ed), "Output from command is possibly incomplete"); XBell(XtDisplay(ci->ed), 100); } if (nread == 0 || nread == -1) { if (!ci->first && !ci->replace) { XtVaSetValues(ci->ed, XtNinsertPosition, 0, NULL); XtPopup(ci->window, XtGrabNone); } else if (ci->replace && (ci->selStart != ci->selEnd)) { XawTextSetSelection(ci->ed, ci->selStart, XawTextGetInsertionPoint(ci->ed)); } XtRemoveInput(*id); close(*source); XtFree((char *) ci); wait((int *) 0); } else { block.firstPos = 0; block.length = nread; block.ptr = buffer; block.format = FMT8BIT; if (ci->first) { char first[2]; String f = first, *ff = &f; ci->first = False; if (ci->replace) { XawTextBlock notext; notext.firstPos = 0; notext.length = 0; notext.ptr = 0; notext.format = FMT8BIT; XawTextSetInsertionPoint(ci->ed, ci->selStart); if (ci->selStart != ci->selEnd) { if ( (proc = AxeiiTextUndoPreReplace(ci->ed)) ) { (*proc)(ci->ed); } } else { if ( (proc = AxeiiTextUndoPreInsert(ci->ed)) ) { (*proc)(ci->ed); } } (void) XawTextReplace(ci->ed, ci->selStart, ci->selEnd, ¬ext); /* * This shouldn't be necessary, but for some reason the * insertion point is incorrect following the replace. */ XawTextSetInsertionPoint(ci->ed, ci->selStart); } else { ci->window = AxeEditorCreateWindow(ci->ed, CLASS(menu_parent), (String) 0); ci->ed = AxeEditorEdWidget(AxeWindowAxeEditor(ci->window)); XtRealizeWidget(ci->window); /* * Silly kludge to get round problem of caret behaving oddly * if text is inserted into empty widget using XawTextReplace */ first[0] = buffer[0]; first[1] = '\0'; XtCallActionProc(ci->ed, "insert-string", (XEvent *) 0, ff, (Cardinal) 1); block.firstPos = 1; block.length = nread - 1; } } pos = XawTextGetInsertionPoint(ci->ed); if (XawTextReplace(ci->ed, pos, pos, &block) != XawEditDone) { UpdateInfoBar(AxeEditorOf(ci->ed), "Text insertion failure"); } else { XawTextSetInsertionPoint(ci->ed, pos + block.length); } } } static void MiniPopen(w, replace) Widget w; Boolean replace; { Widget axeEditor = AxeEditorOf(w); Widget text = AxeTextDeckTop(PRIVATE(axeEditor,ed_deck)); Widget asciiSrc; XawTextPosition selStart, selEnd, from; XawTextBlock textBlock; Cursor busyCursor = 0, menuCursor, textCursor, miniCursor; int length, toread, piece; int tochild[2], fromchild[2], errchild[2]; struct childInfo *ci, *ce; /* * The selection or the entire buffer is fed to the command in the * minibuffer. The output from the command replaces the selection or * is inserted into the buffer if replace is True (| - mini-pipe), * otherwise it is inserted into a new window (! - mini-shell). Nothing * happens if there is no standard output from the command. Error output * is popped up in a separate standard aXe window. */ if (!ExecSubProcess(text, MiniInput(w, True), tochild, fromchild, errchild)) { UpdateInfoBar(axeEditor, "Unable to execute command"); XBell(XtDisplay(w), 100); return; } asciiSrc = XawTextGetSource(text); XtVaGetValues(asciiSrc, XtNpieceSize, &piece, NULL); XawTextGetSelectionPos(text, &selStart, &selEnd); if ((length = selEnd - selStart) == 0) { if (replace) { selStart = XawTextGetInsertionPoint(text); selEnd = selStart; } else { selStart = selEnd = 0; length = piece; } } XtVaGetValues(PRIVATE(axeEditor,menu_bar), XtNcursor, &menuCursor, NULL); XtVaGetValues(text, XtNcursor, &textCursor, NULL); XtVaGetValues(PRIVATE(axeEditor,mini_buffer), XtNcursor, &miniCursor, NULL); busyCursor = XCreateFontCursor(XtDisplay(axeEditor), XC_watch); XtVaSetValues(PRIVATE(axeEditor,menu_bar), XtNcursor, busyCursor, NULL); XtVaSetValues(text, XtNcursor, busyCursor, NULL); XtVaSetValues(PRIVATE(axeEditor,mini_buffer), XtNcursor, busyCursor, NULL); XFlush(XtDisplay(axeEditor)); ci = XtNew(struct childInfo); ci->first = True; ci->replace = replace; ci->ed = text; ci->window = 0; ci->selStart = selStart; ci->selEnd = selEnd; (void) XtAppAddInput(XtWidgetToApplicationContext(w), fromchild[0], (XtPointer) XtInputReadMask, ChildInput, (XtPointer) ci); ce = XtNew(struct childInfo); ce->first = True; ce->replace = False; ce->ed = text; ce->window = 0; ce->selStart = 0; /* Not used */ ce->selEnd = 0; /* Not used */ (void) XtAppAddInput(XtWidgetToApplicationContext(w), errchild[0], (XtPointer) XtInputReadMask, ChildInput, (XtPointer) ce); signal(SIGPIPE, SIG_IGN); textBlock.format = FMT8BIT; for(toread = length, from = selStart; toread > 0; toread = (selEnd != selStart ? toread - textBlock.length : piece), from = from + textBlock.length) { (void) XawTextSourceRead(asciiSrc, from, &textBlock, toread); if (textBlock.length == 0) { break; } if (write(tochild[1], textBlock.ptr, textBlock.length) == -1) { UpdateInfoBar(axeEditor, "Pipe output error"); XBell(XtDisplay(w), 100); break; } } close(tochild[1]); signal(SIGPIPE, SIG_DFL); if (busyCursor) { XtVaSetValues(PRIVATE(axeEditor,menu_bar), XtNcursor, menuCursor,NULL); XtVaSetValues(text, XtNcursor, textCursor, NULL); XtVaSetValues(PRIVATE(axeEditor,mini_buffer), XtNcursor, miniCursor, NULL); } } #ifdef EXTENSION /*ARGSUSED*/ static int MiniInterp(w) Widget w; { #if TCL_MAJOR_VERSION < 7 return Tcl_Eval(interpreter.interp, MiniInput(w, False), 0, NULL); #else return Tcl_Eval(interpreter.interp, MiniInput(w, False)); #endif } #endif /*ARGSUSED*/ static void miniShell(w, event, params, num_params) Widget w; XEvent *event; String *params; Cardinal *num_params; { MiniPipeOrShell(w, "! ", params, num_params); } /*ARGSUSED*/ static void miniStuff(w, event, params, num_params) Widget w; XEvent *event; String *params; Cardinal *num_params; { MiniPipeOrShell(w, "", params, num_params); } /*ARGSUSED*/ static void miniAbort(w, event, params, num_params) Widget w; XEvent *event; String *params; Cardinal *num_params; { Widget axeEditor = AxeEditorOf(w); if (!PRIVATE(axeEditor,suppressMinibuffer)) { UpdateInfoBar(axeEditor, "Minibuffer abort"); XBell(XtDisplay(w), 100); if (PRIVATE(axeEditor,accelerateMini)) { MiniUninstallAccelerators(w); } } } /*ARGSUSED*/ static void TrapWarningMsgss(name, type, class, defaultp, params, num_params) String name, type, class, defaultp, *params; Cardinal *num_params; { validAction = False; } /*ARGSUSED*/ static void TrapWarnings(message) String message; { validAction = False; } /*ARGSUSED*/ static void MiniCommit(w, event, params, num_params) Widget w; XEvent *event; String *params; Cardinal *num_params; { Widget axeEditor = AxeEditorOf(w); String input; char command; Boolean done; XtVaGetValues(PRIVATE(axeEditor,mini_buffer), XtNstring, &input, NULL); command = input[0]; switch (command) { case '/': MiniSearch(w, XawsdRight); break; case '?': MiniSearch(w, XawsdLeft); break; case '|': MiniPopen(w, True); break; case '!': MiniPopen(w, False); break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': MiniGoto(w); break; case 'r': case 'R': case 'w': case 'W': case 'e': case 'E': done = False; if (input[1] == ' ') { switch (input[0]) { case 'r': case 'R': MiniInsert(w); done = True; break; case 'w': case 'W': MiniSaveAs(w); done = True; break; case 'e': case 'E': MiniLoad(w); done = True; break; default: break; } } if (done) { break; } else { /* Drop-though; not r|w|e; try action or Tcl command */ } default: { XtAppContext app = XtWidgetToApplicationContext(w); XtErrorMsgHandler oldWarningMsgHandler = XtAppSetWarningMsgHandler(app, TrapWarningMsgss); XtErrorHandler oldWarningHandler = XtAppSetWarningHandler(app, TrapWarnings); validAction = True; GenericAction(AxeEditorEdWidget(axeEditor), (XtPointer) MiniInput(w, False)); XtAppSetWarningMsgHandler(app, oldWarningMsgHandler); XtAppSetWarningHandler(app, oldWarningHandler); if (validAction) { break; } } #ifdef EXTENSION if (MiniInterp(w) == TCL_OK) { break; } else { ConfirmerRequestConfirmation(PRIVATE(axeEditor,confirmer), interpreter.interp->result, "acknowledge", ConfirmerPopdown, "unused", NULL, (XtPointer) axeEditor); #else if (True) { ConfirmerRequestConfirmation(PRIVATE(axeEditor,confirmer), "Invalid command", "acknowledge", ConfirmerPopdown, "unused", NULL, (XtPointer) axeEditor); #endif command = '$'; break; } } switch (command) { case '/': case '?': case '$': break; default: if (PRIVATE(axeEditor,accelerateMini)) { MiniUninstallAccelerators(w); } } } /*ARGSUSED*/ static void MiniLeave(w, event, params, num_params) Widget w; XEvent *event; String *params; Cardinal *num_params; { if (!PRIVATE(AxeEditorOf(w),accelerateMini)) { MiniDisplayCaret(w, False); } } /************************************************************* * * Keyboard Macro * *************************************************************/ static void AddToMacro(w, client_data, action_name, event, params, num_params) Widget w; XtPointer client_data; String action_name; XEvent *event; String *params; Cardinal *num_params; { char buffer[MAXSTRLEN + 1]; int bytes; if (w != (Widget) client_data) { return; } if (strcmp(action_name, "insert-char") == 0) { bytes = XLookupString((XKeyEvent *) event, buffer, MAXSTRLEN, (KeySym *) 0, (XComposeStatus *) 0); if (bytes != 0) { buffer[bytes] = '\0'; if (!CLASS(in_macro_string)) { CLASS(macro_commands)[CLASS(macro_size)].name = XrmStringToQuark("insert-string"); CLASS(macro_commands)[CLASS(macro_size)].numArgs = 1; CLASS(macro_commands)[CLASS(macro_size)].arg = (String) XtMalloc(bytes + 1); strncpy(CLASS(macro_commands)[CLASS(macro_size)].arg, buffer, bytes + 1); CLASS(in_macro_string) = True; } else { CLASS(macro_commands)[CLASS(macro_size)].arg = (String) XtRealloc(CLASS(macro_commands)[CLASS(macro_size)].arg, strlen(CLASS(macro_commands)[CLASS(macro_size)].arg) + bytes + 1); strncat(CLASS(macro_commands)[CLASS(macro_size)].arg, buffer, bytes); } } } else { if (CLASS(in_macro_string)) { ++CLASS(macro_size); CLASS(in_macro_string) = False; } CLASS(macro_commands)[CLASS(macro_size)].name = XrmStringToQuark(action_name); CLASS(macro_commands)[CLASS(macro_size)].numArgs = (*num_params) ? 1 : 0; if (*num_params != 0) { CLASS(macro_commands)[CLASS(macro_size)].arg = XtNewString(params[0]); } else { CLASS(macro_commands)[CLASS(macro_size)].arg = NULL; } ++CLASS(macro_size); } if (CLASS(macro_size) == CLASS(max_macro_size)) { CLASS(max_macro_size) += CHUNK; CLASS(macro_commands) = (MacroList) XtRealloc((char *) CLASS(macro_commands), CLASS(max_macro_size) * sizeof(MacroCommand)); } } /*ARGSUSED*/ static void startMacro(w, event, params, num_params) Widget w; XEvent *event; String *params; Cardinal *num_params; { Widget axeEditor = AxeEditorOf(w); int m; if (!CLASS(macro_id)) { CLASS(macro_id) = XtAppAddActionHook(XtWidgetToApplicationContext(w), AddToMacro, (XtPointer) w); UpdateInfoBar(axeEditor, "Defining keyboard macro"); if (CLASS(macro_size) == 0) { CLASS(macro_commands) = (MacroList) XtMalloc(CHUNK * sizeof(MacroCommand)); CLASS(max_macro_size) = CHUNK; } else { for (m = 0; m < CLASS(macro_size); ++m) { if (CLASS(macro_commands)[m].numArgs != 0) { XtFree(CLASS(macro_commands)[m].arg); } } CLASS(macro_size) = 0; } CLASS(in_macro_string) = False; } else { UpdateInfoBar(axeEditor, "Already defining keyboard macro"); XBell(XtDisplay(w), 100); } } /*ARGSUSED*/ static void endMacro(w, event, params, num_params) Widget w; XEvent *event; String *params; Cardinal *num_params; { Widget axeEditor = AxeEditorOf(w); if (CLASS(macro_id)) { --CLASS(macro_size); /* removes end-macro itself */ XtRemoveActionHook(CLASS(macro_id)); CLASS(macro_id) = (XtActionHookId) 0; UpdateInfoBar(axeEditor, "Keyboard macro defined"); } else { UpdateInfoBar(axeEditor, "Not defining keyboard macro"); XBell(XtDisplay(w), 100); } } static void ExecMacro(w, event) Widget w; XEvent *event; { int c; for (c = 0; c < CLASS(macro_size); ++c) { XtCallActionProc(w, XrmQuarkToString(CLASS(macro_commands)[c].name), event, &CLASS(macro_commands)[c].arg, CLASS(macro_commands)[c].numArgs); } } /*ARGSUSED*/ static void execMacro(w, event, params, num_params) Widget w; XEvent *event; String *params; Cardinal *num_params; { if (CLASS(macro_size) == 0) { UpdateInfoBar(AxeEditorOf(w), "No macro defined"); XBell(XtDisplay(w), 100); return; } ExecMacro(w, event); } /*ARGSUSED*/ static void repeatMacro(w, event, params, num_params) Widget w; XEvent *event; String *params; Cardinal *num_params; { Widget axeEditor = AxeEditorOf(w); int repeat, repeats, times; if (CLASS(macro_size) == 0) { UpdateInfoBar(axeEditor, "No macro defined"); XBell(XtDisplay(w), 100); return; } if (*num_params > 0) { repeats = atoi(params[0]); } else { if (!PRIVATE(axeEditor,suppressMinibuffer)) { repeats = ((times = atoi(MiniInput(w, False))) == 0) ? 1 : times; } else { repeats = 1; } } for (repeat = 1; repeat <= repeats; ++repeat) { ExecMacro(w, event); } } /************************************************************* * * Semi-public functions * *************************************************************/ /* * This routine is made public for the benefit of AxeTextDeck, but it is * not advertised as such in AxeEditor.h. If there are multiple files it * is easier to do the expansions after splitting in AxeTextDeck. * * NB caller must free returned string */ String AxeEditorExpandName(name) String name; { String expandedName; if (name[0] == '~') { expandedName = XtMalloc(CLASS(home_dir_len) + strlen(name) + 1); strcpy(expandedName, CLASS(home_dir)); strcat(expandedName, "/"); strcat(expandedName, &name[2]); } #ifdef __apollo else if (strncmp (name, "`node_data", 10) == 0) { expandedName = XtNewString(name); } #endif else if (name[0] == '/') { expandedName = XtNewString(name); } else { expandedName = XtMalloc(CLASS(current_dir_len) + strlen(name) + 1); strcpy(expandedName, CLASS(current_dir)); strcat(expandedName, name); } return expandedName; } /************************************************************* * * Public functions * *************************************************************/ int AxeEditorNextEditor() { int editor; /* AxeWindows are named according to the slot number of the child AxeEditor. But the AxeWindow has to be created, and hence named, before the AxeEditor is created. This makes sure a correct slot number is returned in the first case */ XtInitializeWidgetClass(axeEditorWidgetClass); for (editor = 0; editor < NUMBEROFEDITORS; ++editor) { if (!EDITORS[editor]) { break; } } return editor; } Widget AxeEditorParentOf(widget) Widget widget; { Widget axeEditor; for (axeEditor = XtParent(widget); axeEditor; axeEditor = XtParent(axeEditor)) { if (XtIsSubclass(axeEditor, axeEditorWidgetClass)) { break; } } return axeEditor; } Widget AxeEditorFileNameWidget(w) Widget w; { return (XtIsSubclass(w, axeEditorWidgetClass)) ? PRIVATE(w,file_name) : (Widget) 0; } Widget AxeEditorInfoBarWidget(w) Widget w; { return (XtIsSubclass(w, axeEditorWidgetClass)) ? PRIVATE(w,info_bar) : (Widget) 0; } Widget AxeEditorMenuBarWidget(w) Widget w; { return (XtIsSubclass(w, axeEditorWidgetClass)) ? PRIVATE(w,menu_bar) : (Widget) 0; } Widget AxeEditorEdWidget(w) Widget w; { return (XtIsSubclass(w, axeEditorWidgetClass)) ? AxeTextDeckTop(PRIVATE(w,ed_deck)) : (Widget) 0; } Widget AxeEditorMiniBufferWidget(w) Widget w; { return (XtIsSubclass(w, axeEditorWidgetClass)) ? PRIVATE(w,mini_buffer) : (Widget) 0; } void AxeEditorUpdateInfoBar(w, info) Widget w; String info; { if (w && XtIsSubclass(w, axeEditorWidgetClass)) { UpdateInfoBar(w, info); } } Boolean AxeEditorIterate(iterator) AxeIterationType iterator; { Widget axeEditor; int editor; Boolean result = True; XtInitializeWidgetClass(axeEditorWidgetClass); for (editor = 0; editor < NUMBEROFEDITORS; ++editor) { axeEditor = EDITORS[editor]; if (!axeEditor) { continue; } switch (iterator) { case AxeSafeClose: result &= WindowClosed(axeEditor); break; case AxeForceClose: XtDestroyWidget(axeEditor); break; case AxeSave: result &= BuffersSaved(axeEditor); break; case AxeSaveAndClose: (void) BuffersSaved(axeEditor); result &= WindowClosed(axeEditor); break; default: ; } } return result; } Widget AxeEditorCreateWindow(widget, parent, file) Widget widget; Widget parent; String file; { Widget window, deck; char name[3], assocDir[MAXPATHLEN], *assocFile; RePopulateShowMenu(XtWidgetToApplicationContext(parent)); sprintf(name, "%02d", AxeEditorNextEditor()); window = XtVaCreatePopupShell(name, axeWindowWidgetClass, parent, XtNfile, file, NULL); if (XtIsSubclass(widget, axeTextWidgetClass)) { if ( (assocFile = AxeTextGetAssociatedFile(widget)) ) { strcpy(assocDir, assocFile); assocDir[rindex(assocDir, '/') - assocDir] = '\0'; } deck = PRIVATE(AxeWindowAxeEditor(window),ed_deck); AxeTextDeckSetAssociatedDirectory (deck, assocFile ? assocDir : assocFile); } return window; } static XtResource appResource[] = { { "display", "Display", XtRString, sizeof(String), (Cardinal) 0, XtRImmediate, (XtPointer) 0 } }; void AxeEditorHelpWindow(helpName, parent) String helpName; Widget parent; { Atom reqAtom = XA_WINDOW, gotAtom; int gotFormat; unsigned long gotItems, moreBytes; unsigned char *propValue; Display *display = XtDisplay(parent); Window propWindow; char command[1024], property; Boolean startAxinfo = True; String dpy; /* * Check if axinfo is already running. First look to * see if expected root window property is present. */ if (XGetWindowProperty(display, XDefaultRootWindow(display), AxeisUserAtom(display), 0, 1, False, reqAtom, &gotAtom, &gotFormat, &gotItems, &moreBytes, &propValue) == Success) { /* * The property does exist. The window that is the value of the * property should have the AXE_AXINFO_user property attached. */ if (gotAtom == reqAtom) { propWindow = *((Window *) propValue); XFree((char *) propValue); TrapErrors(display); if (XGetWindowProperty(display, propWindow, AxeisUserAtom(display), 0, 0, False, XA_STRING, &gotAtom, &gotFormat, &gotItems, &moreBytes, &propValue) == Success) { if (gotAtom == None) { xerror = BadAtom; } XFree((char *) propValue); } DontTrapErrors(display); /* * The window id from the root window property seems to be OK. * So go ahead and notify it by changing its AXE_AXINFO property * with the tag of the node that is to be displayed. If that * succeeds then the work is done. */ if (xerror == Success) { TrapErrors(display); XChangeProperty(display, propWindow, XInternAtom(display, "AXE_AXINFO", False), XA_STRING, 8, PropModeReplace, (unsigned char *) helpName, strlen(helpName)); if (xerror == Success) { startAxinfo = False; } DontTrapErrors(display); } } } if (startAxinfo) { XtVaGetApplicationResources(parent, (XtPointer) &dpy, appResource, (Cardinal) 1, NULL); if (dpy) { sprintf(command, "axinfo -node %s -display %s &", (helpName ? helpName : "Top"), dpy); } else { sprintf(command, "axinfo -node %s &",(helpName ? helpName : "Top")); } system(command); } } void AxeEditorAddShowMenuCallback(widget, proc, client_data) Widget widget; XtCallbackProc proc; XtPointer client_data; { AxeEditorWidgetClass wc; int n; XtInitializeWidgetClass(axeEditorWidgetClass); wc = (AxeEditorWidgetClass) axeEditorWidgetClass; n = ++CLASS(show_menu_callbacks); CLASS(show_menu_callback_list) = (ShowMenuList) XtRealloc((char *) CLASS(show_menu_callback_list), (Cardinal) (n * sizeof(ShowMenuRec))); CLASS(show_menu_callback_list)[n - 1].widget = widget; CLASS(show_menu_callback_list)[n - 1].cbr.callback = proc; CLASS(show_menu_callback_list)[n - 1].cbr.closure = client_data; } #undef PRIVATE #undef CLASS #undef MAXEDITORS #undef NUMBEROFEDITORS #undef EDITORS axe-6.1.2.orig/Widgets/AxeEditor.h100644 243 144 6164 5550557117 15452 0ustar joostusers/* * Copyright 1992 The University of Newcastle upon Tyne * * Permission to use, copy, modify and distribute this software and its * documentation for any purpose other than its commercial exploitation * is hereby granted without fee, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of The University of Newcastle upon Tyne not be used in * advertising or publicity pertaining to distribution of the software * without specific, written prior permission. The University of * Newcastle upon Tyne makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * THE UNIVERSITY OF NEWCASTLE UPON TYNE DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF * NEWCASTLE UPON TYNE BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. * * Author: Jim Wight (j.k.wight@newcastle.ac.uk) * Department of Computing Science * University of Newcastle upon Tyne, UK */ #ifndef AxeEditor_h #define AxeEditor_h #include typedef struct _AxeEditorClassRec *AxeEditorWidgetClass; typedef struct _AxeEditorRec *AxeEditorWidget; extern WidgetClass axeEditorWidgetClass; extern int AxeEditorNextEditor(); extern Widget AxeEditorParentOf(); extern Widget AxeEditorFileNameWidget(); extern Widget AxeEditorInfoBarWidget(); extern Widget AxeEditorMenuBarWidget(); extern Widget AxeEditorEdWidget(); extern Widget AxeEditorMiniBufferWidget(); extern void AxeEditorUpdateInfoBar(); extern Boolean AxeEditorIterate(); extern Widget AxeEditorCreateWindow(); extern void AxeEditorHelpWindow(); extern void AxeEditorAddShowMenuCallback(); #define XtNbuttons "buttons" #define XtCButtons "Buttons" #define XtNmenuList "menuList" #define XtCMenuList "MenuList" #define XtNbuttonList "buttonList" #define XtCButtonList "ButtonList" #define XtNinfoTimeout "infoTimeout" #define XtCInfoTimeout "InfoTimeout" #define XtNfocusToText "focusToText" #define XtCFocusToText "FocusToText" #define XtCSuppressPane "SuppressPane" #define XtNsuppressFilename "suppressFilename" #define XtNsuppressInfobar "suppressInfobar" #define XtNsuppressMinibuffer "suppressMinibuffer" #define XtNfontList "fontList" #define XtCFontList "FontList" #define XtNinternalBorderWidth "internalBorderWidth" #define XtNchangeCallback "changeCallback" #define XtNminiMenu "miniMenu" #define XtCMiniMenu "MiniMenu" #define XtNfullPathnames "fullPathnames" #define XtCFullPathnames "FullPathnames" #endif /* AxeEditor_h */ axe-6.1.2.orig/Widgets/AxeEditorP.h100644 243 144 10465 5550557117 15611 0ustar joostusers/* * Copyright 1992 The University of Newcastle upon Tyne * * Permission to use, copy, modify and distribute this software and its * documentation for any purpose other than its commercial exploitation * is hereby granted without fee, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of The University of Newcastle upon Tyne not be used in * advertising or publicity pertaining to distribution of the software * without specific, written prior permission. The University of * Newcastle upon Tyne makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * THE UNIVERSITY OF NEWCASTLE UPON TYNE DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF * NEWCASTLE UPON TYNE BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. * * Author: Jim Wight (j.k.wight@newcastle.ac.uk) * Department of Computing Science * University of Newcastle upon Tyne, UK */ #ifndef AxeEditorP_h #define AxeEditorP_h #include #include #include "regexp.h" struct childInfo { Boolean first; Boolean replace; Widget ed; Widget window; XawTextPosition selStart; XawTextPosition selEnd; }; typedef struct { String name; Boolean chosen; } MenuRecord; typedef struct { String name; String action; } ButtonRecord; typedef struct { Widget widget; XtCallbackRec cbr; } ShowMenuRec, *ShowMenuList; typedef struct { String label; String name; XFontStruct *fontStruct; } FontListStruct; typedef struct { XrmQuark name; int numArgs; String arg; } MacroCommand, *MacroList; typedef struct { /* Class variables */ XtPointer extension; Pixmap axeLogo; Pixmap fwdArrow; Pixmap bwdArrow; Pixmap vtCentre; Pixmap hzCentre; Pixmap tickMark; Pixmap modMark; Widget *editors; int numberOfEditors; int maxEditors; Widget menu_parent; Widget show_menu; int show_menu_callbacks; ShowMenuList show_menu_callback_list; XtTranslations mini_translations; XtAccelerators mini_accelerators; FontListStruct *mini_menu; FontListStruct *default_mini_menu; char *home_dir; int home_dir_len; char *current_dir; int current_dir_len; XtActionHookId macro_id; int macro_size; int max_macro_size; Boolean in_macro_string; MacroList macro_commands; Boolean show_work_proc; } AxeEditorClassPart; typedef struct _AxeEditorClassRec { CoreClassPart core_class; CompositeClassPart composite_class; AxeEditorClassPart axeEditor_class; } AxeEditorClassRec; extern AxeEditorClassRec axeEditorClassRec; typedef struct { /* Resources */ String file; String menu_list; Boolean buttons; String button_list; int info_timeout; Boolean focus_to_text; Boolean suppressFilename; Boolean suppressInfobar; Boolean suppressMinibuffer; String font_list; Dimension internal_border_width; XtCallbackList change_callbacks; String full_pathnames; /* Private data */ Widget file_name; Widget info_bar; XtIntervalId info_timer; Widget menu_bar; Widget ed_deck; Widget mini_buffer; Widget mini_button; Widget confirmer; FontListStruct *font_table; XtTranslations defaultTextTranslations; Boolean accelerateMini; } AxeEditorPart; typedef struct _AxeEditorRec { CorePart core; CompositePart composite; AxeEditorPart axeEditor; } AxeEditorRec; #endif /* AxeEditorP_h */ axe-6.1.2.orig/Widgets/AxeIntrinsic.h100644 243 144 710 5550557117 16135 0ustar joostusers#ifndef _AxeIntrinsic_h_ #define _AxeIntrinsic_h_ typedef int AxeIterationType; #define AxeIsModified 1 #define AxeSafeClose 2 #define AxeForceClose 3 #define AxeSave 4 #define AxeSaveAndClose 5 #define noname "No name" #define AXE_SERVER "AXE_SERVER" #define AXE_COAXE "AXE_COAXE" #define AXE_FAXE "AXE_FAXE" #define AXE_POLEAXE "AXE_POLEAXE" #endif /* _AxeIntrinsic_h_ */ axe-6.1.2.orig/Widgets/AxeMenuBtn.c100644 243 144 22366 5550557111 15603 0ustar joostusers/* * Copyright 1992 The University of Newcastle upon Tyne * * Permission to use, copy, modify and distribute this software and its * documentation for any purpose other than its commercial exploitation * is hereby granted without fee, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of The University of Newcastle upon Tyne not be used in * advertising or publicity pertaining to distribution of the software * without specific, written prior permission. The University of * Newcastle upon Tyne makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * THE UNIVERSITY OF NEWCASTLE UPON TYNE DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF * NEWCASTLE UPON TYNE BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. * * Author: Jim Wight (j.k.wight@newcastle.ac.uk) * Department of Computing Science * University of Newcastle upon Tyne, UK */ #include #include #include #include /* for XtNcreateChildProc */ #include #include static void Initialize(); #if defined(XtSpecificationRelease) && XtSpecificationRelease < 5 static void GetValuesHook(); #endif static void SavePopper(), UpdateInfo(), MaybeMake(), MaybePop(), MaybeDrop(); static XtActionsRec actions[] = { "update-info", UpdateInfo, "maybe-make", MaybeMake, "maybe-pop", MaybePop, "maybe-drop", MaybeDrop, }; static char translations[] = "\ : highlight() update-info() maybe-pop() \n\ : set() notify() reset() maybe-make() PopupMenu()\n\ : reset() maybe-drop()"; #define offset(field) XtOffsetOf(AxeMenuButtonRec, axeMenuButton.field) static XtResource resources[] = { {XtNhelp, XtCHelp, XtRString, sizeof(String), offset(help), XtRString, NULL}, }; #undef offset AxeMenuButtonClassRec axeMenuButtonClassRec = { { /* superclass */ (WidgetClass) &menuButtonClassRec, /* class_name */ "AxeMenuButton", /* size */ sizeof(AxeMenuButtonRec), /* class_initialize */ NULL, /* class_part_initialize */ NULL, /* class_inited */ FALSE, /* initialize */ Initialize, /* initialize_hook */ NULL, /* realize */ XtInheritRealize, /* actions */ actions, /* num_actions */ XtNumber(actions), /* resources */ resources, /* resource_count */ XtNumber(resources), /* xrm_class */ NULLQUARK, /* compress_motion */ FALSE, /* compress_exposure */ TRUE, /* compress_enterleave */ TRUE, /* visible_interest */ FALSE, /* destroy */ NULL, /* resize */ XtInheritResize, /* expose */ XtInheritExpose, /* set_values */ NULL, /* set_values_hook */ NULL, /* set_values_almost */ XtInheritSetValuesAlmost, /* get_values_hook */ NULL, /* accept_focus */ NULL, /* version */ XtVersion, /* callback_private */ NULL, /* tm_table */ translations, /* query_geometry */ XtInheritQueryGeometry, /* display_accelerator */ XtInheritDisplayAccelerator, /* extension */ NULL }, /* CoreClass fields initialization */ { /* change_sensitive */ XtInheritChangeSensitive }, /* SimpleClass fields initialization */ #ifdef XAW3D { /* shadowdraw */ XtInheritXaw3dShadowDraw, }, /* ThreeD fields initialization */ #endif { /* foo */ 0, }, /* LabelClass fields initialization */ { /* makes_compiler_happy */ 0, }, /* CommandClass fields initialization */ { /* makes_compiler_happy */ 0, }, /* MenuButtonClass fields initialization */ { /* extension */ NULL, }, /* AxeMenuButtonClass fields initialization */ }; WidgetClass axeMenuButtonWidgetClass = (WidgetClass) &axeMenuButtonClassRec; /* ARGSUSED */ static void Initialize(req, new, args, num_args) Widget req, new; ArgList args; Cardinal *num_args; { XtAddCallback(new, XtNcallback, SavePopper, (XtPointer) AxeEditorParentOf(new)); } /* ARGSUSED */ static void SavePopper(widget, client_data, call_data) Widget widget; XtPointer client_data, call_data; { String menuName; Widget w, menu; XtVaGetValues(widget, XtNmenuName, &menuName, NULL); for (menu = (Widget) 0, w = widget; w; w = XtParent(w)) { if ((menu = XtNameToWidget(w, menuName))) { break; } } AxeSimpleMenuStorePopperUpper(menu, (Widget) client_data); } /************************************************************* * * update-info * *************************************************************/ /* ARGSUSED */ static void UpdateInfo(widget, event, params, num_params) Widget widget; XEvent *event; String *params; Cardinal *num_params; { String help; XtVaGetValues(widget, XtNhelp, &help, NULL); AxeEditorUpdateInfoBar(AxeEditorParentOf(widget), help); } /************************************************************* * * maybe-make * *************************************************************/ /*ARGSUSED*/ static void MaybeMake(widget, event, params, num_params) Widget widget; XEvent *event; String *params; Cardinal *num_params; { String menuName; Widget menu, temp; XtCreatePopupChildProc create; XtVaGetValues(widget, XtNmenuName, &menuName, NULL); temp = widget; while(temp != NULL) { menu = XtNameToWidget(temp, menuName); if (menu == NULL) temp = XtParent(temp); else break; } XtVaGetValues(menu, XtNcreatePopupChildProc, &create, NULL); if (create) { (*create) (menu); XtVaSetValues(menu, XtNcreatePopupChildProc, (XtCreatePopupChildProc) 0, NULL); } } /************************************************************* * * maybe-pop * *************************************************************/ /*ARGSUSED*/ static void MaybePop(widget, event, params, num_params) Widget widget; XEvent *event; String *params; Cardinal *num_params; { if (event->xcrossing.state | (Button1Mask & Button2Mask & Button3Mask & Button4Mask & Button5Mask)) { XtCallActionProc(widget, "maybe-make", event, (String *) 0, (Cardinal) 0); SavePopper(widget, (XtPointer) AxeEditorParentOf(widget), (XtPointer) 0); XtCallActionProc(widget, "PopupMenu", event, (String *) 0, (Cardinal) 0); } } /************************************************************* * * maybe-drop * *************************************************************/ /*ARGSUSED*/ static void MaybeDrop(widget, event, params, num_params) Widget widget; XEvent *event; String *params; Cardinal *num_params; { Dimension height; String menuName; Widget w, menu; if (event->xcrossing.state | (Button1Mask & Button2Mask & Button3Mask & Button4Mask & Button5Mask)) { XtVaGetValues(widget, XtNheight, &height, XtNmenuName, &menuName, NULL); if (event->xcrossing.y > 0 && event->xcrossing.y >= height) { return; } for (w = widget; w; w = XtParent(w)) { if ((menu = XtNameToWidget(w, menuName))) { XtPopdown(menu); break; } } } } axe-6.1.2.orig/Widgets/AxeMenuBtn.h100644 243 144 3420 5550557117 15564 0ustar joostusers/* * Copyright 1992 The University of Newcastle upon Tyne * * Permission to use, copy, modify and distribute this software and its * documentation for any purpose other than its commercial exploitation * is hereby granted without fee, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of The University of Newcastle upon Tyne not be used in * advertising or publicity pertaining to distribution of the software * without specific, written prior permission. The University of * Newcastle upon Tyne makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * THE UNIVERSITY OF NEWCASTLE UPON TYNE DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF * NEWCASTLE UPON TYNE BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. * * Author: Jim Wight (j.k.wight@newcastle.ac.uk) * Department of Computing Science * University of Newcastle upon Tyne, UK */ #ifndef _AxeMenuButton_h #define _AxeMenuButton_h #include extern WidgetClass axeMenuButtonWidgetClass; typedef struct _AxeMenuButtonClassRec *AxeMenuButtonWidgetClass; typedef struct _AxeMenuButtonRec *AxeMenuButtonWidget; #define XtNhelp "help" #define XtCHelp "Help" #endif /* _AxeMenuButton_h */ axe-6.1.2.orig/Widgets/AxeMenuBtnP.h100644 243 144 4674 5550557120 15712 0ustar joostusers/* * Copyright 1992 The University of Newcastle upon Tyne * * Permission to use, copy, modify and distribute this software and its * documentation for any purpose other than its commercial exploitation * is hereby granted without fee, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of The University of Newcastle upon Tyne not be used in * advertising or publicity pertaining to distribution of the software * without specific, written prior permission. The University of * Newcastle upon Tyne makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * THE UNIVERSITY OF NEWCASTLE UPON TYNE DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF * NEWCASTLE UPON TYNE BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. * * Author: Jim Wight (j.k.wight@newcastle.ac.uk) * Department of Computing Science * University of Newcastle upon Tyne, UK */ #ifndef _AxeMenuButtonP_h #define _AxeMenuButtonP_h #include #include typedef struct _AxeMenuButtonClass { XtPointer extension; } AxeMenuButtonClassPart; typedef struct _AxeMenuButtonClassRec { CoreClassPart core_class; SimpleClassPart simple_class; #ifdef XAW3D ThreeDClassPart threeD_class; #endif LabelClassPart label_class; CommandClassPart command_class; MenuButtonClassPart menuButton_class; AxeMenuButtonClassPart axeMenuButton_class; } AxeMenuButtonClassRec; extern AxeMenuButtonClassRec axeMenuButtonClassRec; typedef struct { String help; } AxeMenuButtonPart; typedef struct _AxeMenuButtonRec { CorePart core; SimplePart simple; #ifdef XAW3D ThreeDPart threeD; #endif LabelPart label; CommandPart command; MenuButtonPart menuButton; AxeMenuButtonPart axeMenuButton; } AxeMenuButtonRec; #endif /* _AxeMenuButtonP_h */ axe-6.1.2.orig/Widgets/AxeSimMenu.c100644 243 144 12553 5550557112 15606 0ustar joostusers/* * Copyright 1992 The University of Newcastle upon Tyne * * Permission to use, copy, modify and distribute this software and its * documentation for any purpose other than its commercial exploitation * is hereby granted without fee, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of The University of Newcastle upon Tyne not be used in * advertising or publicity pertaining to distribution of the software * without specific, written prior permission. The University of * Newcastle upon Tyne makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * THE UNIVERSITY OF NEWCASTLE UPON TYNE DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF * NEWCASTLE UPON TYNE BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. * * Author: Jim Wight (j.k.wight@newcastle.ac.uk) * Department of Computing Science * University of Newcastle upon Tyne, UK */ #include #include #include #include #include "AxeSimMenuP.h" #define PRIVATE(w,field) (((AxeSimpleMenuWidget) w)->axeSimpleMenu.field) static void Initialize(); static void UpdateInfo(); static XtActionsRec actions [] = { "update-info", UpdateInfo, }; AxeSimpleMenuClassRec axeSimpleMenuClassRec = { { /* superclass */ (WidgetClass) &simpleMenuClassRec, /* class_name */ "AxeSimpleMenu", /* size */ sizeof(AxeSimpleMenuRec), /* class_initialize */ NULL, /* class_part_initialize*/ NULL, /* Class init'ed */ FALSE, /* initialize */ Initialize, /* initialize_hook */ NULL, /* realize */ XtInheritRealize, /* actions */ actions, /* num_actions */ XtNumber(actions), /* resources */ NULL, /* resource_count */ 0, /* xrm_class */ NULLQUARK, /* compress_motion */ TRUE, /* compress_exposure */ TRUE, /* compress_enterleave*/ TRUE, /* visible_interest */ FALSE, /* destroy */ NULL, /* resize */ XtInheritResize, /* expose */ XtInheritExpose, /* set_values */ NULL, /* set_values_hook */ NULL, /* set_values_almost */ XtInheritSetValuesAlmost, /* get_values_hook */ NULL, /* accept_focus */ XtInheritAcceptFocus, /* intrinsics version */ XtVersion, /* callback offsets */ NULL, /* tm_table */ XtInheritTranslations, /* query_geometry */ XtInheritQueryGeometry, /* display_accelerator*/ XtInheritDisplayAccelerator, /* extension */ NULL },{ /* geometry_manager */ XtInheritGeometryManager, /* change_managed */ XtInheritChangeManaged, /* insert_child */ XtInheritInsertChild, /* delete_child */ XtInheritDeleteChild, /* extension */ NULL },{ /* Shell extension */ NULL },{ /* Override extension */ NULL },{ /* Simple Menu extension*/ NULL },{ /* Simple Axe Menu ext */ NULL } }; WidgetClass axeSimpleMenuWidgetClass = (WidgetClass) &axeSimpleMenuClassRec; /* ARGSUSED */ static void Initialize(req, new, args, num_args) Widget req, new; ArgList args; Cardinal *num_args; { ((AxeSimpleMenuWidget) new)->axeSimpleMenu.popperUpper = (Widget) 0; } /************************************************************* * * update-info * *************************************************************/ /* ARGSUSED */ static void UpdateInfo(widget, event, params, num_params) Widget widget; XEvent *event; String *params; Cardinal *num_params; { static Widget previousEntry = 0; Widget entry; String help; if (*num_params && strcmp(params[0], "Reset") == 0) { previousEntry = 0; return; } if ((entry = XawSimpleMenuGetActiveEntry(widget)) && entry != previousEntry) { previousEntry = entry; XtVaGetValues(entry, XtNhelp, &help, NULL); AxeEditorUpdateInfoBar(PRIVATE(widget,popperUpper), help); } } /************************************************************* * * Public functions * *************************************************************/ void AxeSimpleMenuStorePopperUpper(menu, popper) Widget menu, popper; { if (XtIsSubclass(menu, axeSimpleMenuWidgetClass)) { PRIVATE(menu,popperUpper) = popper; } } Widget AxeSimpleMenuFetchPopperUpper(menu) Widget menu; { Widget popperUpper; if (XtIsSubclass(menu, axeSimpleMenuWidgetClass)) { popperUpper = PRIVATE(menu,popperUpper); /* PRIVATE(menu,popperUpper) = (Widget) 0; */ } else { popperUpper = (Widget) 0; } return popperUpper; } #undef PRIVATE axe-6.1.2.orig/Widgets/AxeSimMenu.h100644 243 144 3503 5550557120 15565 0ustar joostusers/* * Copyright 1992 The University of Newcastle upon Tyne * * Permission to use, copy, modify and distribute this software and its * documentation for any purpose other than its commercial exploitation * is hereby granted without fee, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of The University of Newcastle upon Tyne not be used in * advertising or publicity pertaining to distribution of the software * without specific, written prior permission. The University of * Newcastle upon Tyne makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * THE UNIVERSITY OF NEWCASTLE UPON TYNE DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF * NEWCASTLE UPON TYNE BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. * * Author: Jim Wight (j.k.wight@newcastle.ac.uk) * Department of Computing Science * University of Newcastle upon Tyne, UK */ #ifndef _AxeSimMenu_h #define _AxeSimMenu_h #include #include typedef struct _AxeSimpleMenuClassRec* AxeSimpleMenuWidgetClass; typedef struct _AxeSimpleMenuRec* AxeSimpleMenuWidget; extern WidgetClass axeSimpleMenuWidgetClass; extern void AxeSimpleMenuStorePopperUpper(); extern Widget AxeSimpleMenuFetchPopperUpper(); #endif /* _AxeSimMenu_h */ axe-6.1.2.orig/Widgets/AxeSimMenuP.h100644 243 144 4530 5550557120 15706 0ustar joostusers/* * Copyright 1992 The University of Newcastle upon Tyne * * Permission to use, copy, modify and distribute this software and its * documentation for any purpose other than its commercial exploitation * is hereby granted without fee, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of The University of Newcastle upon Tyne not be used in * advertising or publicity pertaining to distribution of the software * without specific, written prior permission. The University of * Newcastle upon Tyne makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * THE UNIVERSITY OF NEWCASTLE UPON TYNE DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF * NEWCASTLE UPON TYNE BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. * * Author: Jim Wight (j.k.wight@newcastle.ac.uk) * Department of Computing Science * University of Newcastle upon Tyne, UK */ #ifndef _AxeSimMenP_h #define _AxeSimMenP_h #include #include #include typedef struct { XtPointer extension; } AxeSimpleMenuClassPart; typedef struct _AxeSimpleMenuClassRec { CoreClassPart core_class; CompositeClassPart composite_class; ShellClassPart shell_class; OverrideShellClassPart overrideShell_class; SimpleMenuClassPart simpleMenu_class; AxeSimpleMenuClassPart axeMenu_class; } AxeSimpleMenuClassRec; extern AxeSimpleMenuClassRec axeSimpleMenuClassRec; typedef struct _AxeSimpleMenuPart { Widget popperUpper; } AxeSimpleMenuPart; typedef struct _AxeSimpleMenuRec { CorePart core; CompositePart composite; ShellPart shell; OverrideShellPart override; SimpleMenuPart simpleMenu; AxeSimpleMenuPart axeSimpleMenu; } AxeSimpleMenuRec; #endif /* _AxeSimMenP_h */ axe-6.1.2.orig/Widgets/AxeSmeBSB.c100644 243 144 7232 5550557112 15262 0ustar joostusers/* * Copyright 1992 The University of Newcastle upon Tyne * * Permission to use, copy, modify and distribute this software and its * documentation for any purpose other than its commercial exploitation * is hereby granted without fee, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of The University of Newcastle upon Tyne not be used in * advertising or publicity pertaining to distribution of the software * without specific, written prior permission. The University of * Newcastle upon Tyne makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * THE UNIVERSITY OF NEWCASTLE UPON TYNE DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF * NEWCASTLE UPON TYNE BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. * * Author: Jim Wight (j.k.wight@newcastle.ac.uk) * Department of Computing Science * University of Newcastle upon Tyne, UK */ #include #include #include #define offset(field) XtOffsetOf(AxeSmeBSBRec, axeSmeBsb.field) static XtResource resources[] = { {XtNhelp, XtCHelp, XtRString, sizeof(String), offset(help), XtRString, NULL}, }; #undef offset AxeSmeBSBClassRec axeSmeBSBClassRec = { { /* superclass */ (WidgetClass) &smeBSBClassRec, /* class_name */ "AxeSmeBSB", /* size */ sizeof(AxeSmeBSBRec), /* class_initializer */ NULL, /* class_part_initialize*/ NULL, /* Class init'ed */ FALSE, /* initialize */ NULL, /* initialize_hook */ NULL, /* realize */ NULL, /* actions */ NULL, /* num_actions */ 0, /* resources */ resources, /* resource_count */ XtNumber(resources), /* xrm_class */ NULLQUARK, /* compress_motion */ FALSE, /* compress_exposure */ FALSE, /* compress_enterleave*/ FALSE, /* visible_interest */ FALSE, /* destroy */ NULL, /* resize */ NULL, /* expose */ XtInheritExpose, /* set_values */ NULL, /* set_values_hook */ NULL, /* set_values_almost */ XtInheritSetValuesAlmost, /* get_values_hook */ NULL, /* accept_focus */ NULL, /* intrinsics version */ XtVersion, /* callback offsets */ NULL, /* tm_table */ NULL, /* query_geometry */ XtInheritQueryGeometry, /* display_accelerator*/ NULL, /* extension */ NULL },{ /* Menu Entry Fields */ /* highlight */ XtInheritHighlight, /* unhighlight */ XtInheritUnhighlight, /* notify */ XtInheritNotify, /* extension */ NULL }, #ifdef XAW3D { /* ThreeD Fields */ /* shadowdraw */ XtInheritXawSme3dShadowDraw }, #endif { /* BSB Menu entry Fields */ /* extension */ NULL }, { /* AxeBSB Menu entry Fields */ /* extension */ NULL } }; WidgetClass axeSmeBSBObjectClass = (WidgetClass) &axeSmeBSBClassRec; axe-6.1.2.orig/Widgets/AxeSmeBSB.h100644 243 144 3354 5550557120 15267 0ustar joostusers/* * Copyright 1992 The University of Newcastle upon Tyne * * Permission to use, copy, modify and distribute this software and its * documentation for any purpose other than its commercial exploitation * is hereby granted without fee, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of The University of Newcastle upon Tyne not be used in * advertising or publicity pertaining to distribution of the software * without specific, written prior permission. The University of * Newcastle upon Tyne makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * THE UNIVERSITY OF NEWCASTLE UPON TYNE DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF * NEWCASTLE UPON TYNE BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. * * Author: Jim Wight (j.k.wight@newcastle.ac.uk) * Department of Computing Science * University of Newcastle upon Tyne, UK */ #ifndef _AxeSmeBSB_h #define _AxeSmeBSB_h #include typedef struct _AxeSmeBSBClassRec *AxeSmeBSBObjectClass; typedef struct _AxeSmeBSBRec *AxeSmeBSBObject; extern WidgetClass axeSmeBSBObjectClass; #define XtNhelp "help" #define XtCHelp "Help" #endif /* _AxeSmeBSB_h */ axe-6.1.2.orig/Widgets/AxeSmeBSBP.h100644 243 144 4450 5550557120 15405 0ustar joostusers/* * Copyright 1992 The University of Newcastle upon Tyne * * Permission to use, copy, modify and distribute this software and its * documentation for any purpose other than its commercial exploitation * is hereby granted without fee, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of The University of Newcastle upon Tyne not be used in * advertising or publicity pertaining to distribution of the software * without specific, written prior permission. The University of * Newcastle upon Tyne makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * THE UNIVERSITY OF NEWCASTLE UPON TYNE DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF * NEWCASTLE UPON TYNE BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. * * Author: Jim Wight (j.k.wight@newcastle.ac.uk) * Department of Computing Science * University of Newcastle upon Tyne, UK */ #ifndef _AxeSmeBSBP_h #define _AxeSmeBSBP_h #include #include typedef struct _AxeSmeBSBClassPart { XtPointer extension; } AxeSmeBSBClassPart; typedef struct _AxeSmeBSBClassRec { RectObjClassPart rect_class; SmeClassPart sme_class; #ifdef XAW3D SmeThreeDClassPart sme_threeD_class; #endif SmeBSBClassPart smeBsb_class; AxeSmeBSBClassPart axeSmeBsb_class; } AxeSmeBSBClassRec; extern AxeSmeBSBClassRec axeSmeBSBClassRec; typedef struct { /* resources */ String help; } AxeSmeBSBPart; typedef struct _AxeSmeBSBRec { ObjectPart object; RectObjPart rectangle; SmePart sme; #ifdef XAW3D SmeThreeDPart sme_threeD; #endif SmeBSBPart smeBsb; AxeSmeBSBPart axeSmeBsb; } AxeSmeBSBRec; #endif /* _AxeSmeBSBP_h */ axe-6.1.2.orig/Widgets/AxeText.c100644 243 144 115721 5550557112 15176 0ustar joostusers/* * Copyright 1992, 1993 The University of Newcastle upon Tyne * * Permission to use, copy, modify and distribute this software and its * documentation for any purpose other than its commercial exploitation * is hereby granted without fee, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of The University of Newcastle upon Tyne not be used in * advertising or publicity pertaining to distribution of the software * without specific, written prior permission. The University of * Newcastle upon Tyne makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * THE UNIVERSITY OF NEWCASTLE UPON TYNE DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF * NEWCASTLE UPON TYNE BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. * * Author: Jim Wight (j.k.wight@newcastle.ac.uk) * Department of Computing Science * University of Newcastle upon Tyne, UK */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include extern int errno; #include #include "util.h" #include "AxeTextP.h" #define PRIVATE(w,field) (((AxeTextWidget) w)->axe.field) #define AXEII(w,field) (((AxeTextWidget) w)->axeii.field) #define Offset(field) XtOffsetOf(AxeTextRec, axe.field) #define nullfile "/dev/null" static XtResource resources[] = { {XtNassociatedDirectory, XtCAssociatedDirectory, XtRString, sizeof(String), Offset(associated_directory), XtRString, (XtPointer) NULL}, {XtNgrabOnPopup, XtCGrabOnPopup, XtRBoolean, sizeof(Boolean), Offset(grab_on_popup), XtRImmediate, (XtPointer) False}, {XtNchangeCallback, XtCCallback, XtRCallback, sizeof(XtPointer), Offset(change_callbacks), XtRCallback, (XtPointer) NULL}, {XtNmessageCallback, XtCCallback, XtRCallback, sizeof(XtPointer), Offset(message_callbacks), XtRCallback, (XtPointer) NULL}, {XtNenableBackups, XtCEnableBackups, XtRBoolean, sizeof(Boolean), Offset(enable_backups), XtRImmediate, (XtPointer) False}, {XtNbackupNamePrefix, XtCBackupNamePrefix, XtRString, sizeof(String), Offset(backup_name_prefix), XtRString, (XtPointer) ""}, {XtNbackupNameSuffix, XtCBackupNameSuffix, XtRString, sizeof(String), Offset(backup_name_suffix), XtRString, (XtPointer) ".BAK"} }; #undef Offset typedef enum {NONE, READ, EDIT} AccessMode; static Widget MakePopup(); static void MakeConfirmPopup(); static Widget MakeFileNominator(), MakeNumericPad(), MakeControlSelector(); static Widget MakePreferencePopup(); static int CheckPermission(); static void GotoLine(), IncludeFile(); static void ClearBuffer(); static void SaveFile(), SaveAs(), SaveFileSelect(), SaveOver(), SaveAgain(); static void ReloadFile(), LoadFile(), NoUndo(); static void RecordAndNotifyChange(), SourceChange(); static void SetPreferences(), AcceptPreferences(); static void InsertControl(), MessageNotify(); static void Initialize(), Destroy(); static Boolean SetValues(); AxeTextClassRec axeTextClassRec = { /* Core class part */ { /* superclass */ (WidgetClass) &axeiiTextClassRec, /* class_name */ "AxeText", /* widget_size */ sizeof(AxeTextRec), /* class_initialize */ NULL, /* class_part_initialize */ NULL, /* class_inited */ FALSE, /* initialize */ Initialize, /* initialize_hook */ NULL, /* realize */ XtInheritRealize, /* actions */ NULL, /* num_actions */ 0, /* resources */ resources, /* num_resources */ XtNumber(resources), /* xrm_class */ NULLQUARK, /* compress_motion */ TRUE, #if defined(XtSpecificationRelease) && XtSpecificationRelease > 4 /* compress_exposure */ XtExposeGraphicsExpose | XtExposeNoExpose, #else /* compress_exposure */ XtExposeGraphicsExpose, #endif /* compress_enterleave */ TRUE, /* visible_interest */ FALSE, /* destroy */ Destroy, /* resize */ XtInheritResize, /* expose */ XtInheritExpose, /* set_values */ SetValues, /* set_values_hook */ NULL, /* set_values_almost */ XtInheritSetValuesAlmost, /* get_values_hook */ NULL, /* accept_focus */ XtInheritAcceptFocus, /* version */ XtVersion, /* callback offsets */ NULL, /* tm_table */ XtInheritTranslations, /* query_geometry */ XtInheritQueryGeometry, /* display_accelerator */ NULL, /* extension */ NULL, }, { /* simple fields */ /* change_sensitive */ XtInheritChangeSensitive }, { /* text fields */ /* empty */ 0 }, { /* ascii fields */ /* empty */ 0 }, { /* axeii fields */ /* extension */ NULL }, { /* axe fields */ /* exension */ NULL } }; WidgetClass axeTextWidgetClass = (WidgetClass) &axeTextClassRec; /* ARGSUSED */ static void Initialize(req, new, args, num_args) Widget req, new; ArgList args; Cardinal *num_args; { AxeTextWidget atw = (AxeTextWidget) new; String fileName; int check; Boolean exists; AccessMode mode; PRIVATE(new,initial_directory) = (String) 0; PRIVATE(new,file_nominator) = (Widget) 0; PRIVATE(new,numeric_pad) = (Widget) 0; PRIVATE(new,control_selector) = (Widget) 0; PRIVATE(new,preference_popup) = (Widget) 0; PRIVATE(new,confirm_popup) = MakePopup("confirm", new, MakeConfirmPopup); PRIVATE(new,backed_up) = False; XtVaGetValues(new, XtNstring, &fileName, NULL); if (strlen(fileName) > 0) { check = CheckPermission(fileName, &exists, &mode); } if (strlen(fileName) > 0 && (check == 0) && exists) { XtVaSetValues(new, XtNtype, XawAsciiFile, XtNeditType, mode == READ ? XawtextRead : XawtextEdit, NULL); atw->axe.associated_file = NULL; atw->axe.null_file = False; } else { if (strlen(fileName) == 0) { atw->axe.associated_file = NULL; } else { atw->axe.associated_file = XtNewString(fileName); } XtVaSetValues(new, XtNtype, XawAsciiFile, XtNstring, nullfile, XtNeditType, XawtextEdit, NULL); atw->axe.null_file = True; } atw->axe.is_modified = False; XtAddCallback(new, XtNgotoLineCallback, GotoLine, (XtPointer) 0); XtAddCallback(new, XtNincludeFileCallback, IncludeFile, (XtPointer) 0); XtAddCallback(new, XtNinsertControlCallback, InsertControl, (XtPointer) 0); XtAddCallback(new, XtNpreferencesCallback, SetPreferences, (XtPointer) 0); XtAddCallback(new, XtNmodifiedCallback, SourceChange, (XtPointer) 0); XtAddCallback(new, XtNclearBufferCallback, ClearBuffer, (XtPointer) 0); XtAddCallback(new, XtNsaveFileCallback, SaveFile, (XtPointer) 0); XtAddCallback(new, XtNsaveAsCallback, SaveAs, (XtPointer) 0); XtAddCallback(new, XtNloadFileCallback, LoadFile, (XtPointer) 0); XtAddCallback(new, XtNreloadFileCallback, ReloadFile, (XtPointer) 0); XtAddCallback(new, XtNnoUndoCallback, NoUndo, (XtPointer) 0); AxeiiTextWatchForChanges(atw); } static void Destroy(w) Widget w; { Display *display = XtDisplay(w); Atom gotAtom; int gotFormat; unsigned long gotItems, moreBytes; unsigned char *propValue; Window wid; if (PRIVATE(w,initial_directory)) { XtFree(PRIVATE(w,initial_directory)); } if (PRIVATE(w,associated_file)) { XtFree(PRIVATE(w,associated_file)); } if (XGetWindowProperty(display, XtWindow(w), XInternAtom(display, AXE_COAXE, False), 0, 1, False, XA_WINDOW, &gotAtom, &gotFormat, &gotItems, &moreBytes, &propValue) == Success) { if (gotAtom == XA_WINDOW) { wid = *((Window *) propValue); /* * Don't want to know if an error is generated * because client window has disappeared */ TrapErrors(display); XChangeProperty(display, wid, XInternAtom(display, AXE_COAXE, False), XA_STRING, 8, PropModeReplace, NULL, 0); DontTrapErrors(display); } XtFree((char *) propValue); } } /* ARGSUSED */ static Boolean SetValues(old, request, new, args, num_args) Widget old, request, new; ArgList args; Cardinal *num_args; { AxeTextWidget oldatw = (AxeTextWidget) old; AxeTextWidget newatw = (AxeTextWidget) new; /* Too late if FileNominator has already been created */ if (PRIVATE(new,file_nominator)) { return False; } #define NE(field) (oldatw->field != newatw->field) if (NE(axe.associated_directory) && newatw->axe.associated_directory && *(newatw->axe.associated_directory) == '/') { PRIVATE(new,initial_directory) = XtNewString(newatw->axe.associated_directory); } #undef NE return False; } /************************************************************* * * utilities * *************************************************************/ static int CheckPermission(file, exists, mode) String file; Boolean *exists; AccessMode *mode; { int status = 0; struct stat buf; *exists = False; *mode = NONE; if (!file) { return status; } if (access(file, F_OK) == 0) { *exists = True; status = 0; if (access(file, R_OK | W_OK) == 0) { *mode = EDIT; } else if (access(file, R_OK) == 0) { *mode = READ; } else { status = EACCES; } } else if (errno == ENOENT) { *mode = EDIT; } else { status = errno; } if (status == 0 && *exists && *mode != NONE) { if (stat(file, &buf) == 0) { if (!(buf.st_mode & S_IFREG)) { status = EACCES; } } else { status = errno; } } return status; } static void RecordAndNotifyChange(w, state) Widget w; Boolean state; { PRIVATE(w,is_modified) = state; XtCallCallbacks(w, XtNchangeCallback, (XtPointer) 0); } /*ARGSUSED*/ static void SourceChange(w, client_data, call_data) Widget w; XtPointer client_data, call_data; { RecordAndNotifyChange(w, True); } static void MessageNotify(w, code) Widget w; int code; { XtCallCallbackList(w, PRIVATE(w,message_callbacks), (XtPointer) code); } static Boolean CreatePopupLater(client_data) XtPointer client_data; { Widget popup = (Widget) client_data; XtCreatePopupChildProc create; XtVaGetValues(popup, XtNcreatePopupChildProc, &create, NULL); XtVaSetValues(popup, XtNcreatePopupChildProc, (XtCreatePopupChildProc) 0, NULL); if (create) { (*create) (popup); } return True; } static void PositionedPopup(axe, popup) Widget axe, popup; { PopupCentred(popup, PRIVATE(axe,grab_on_popup) ? XtGrabExclusive : XtGrabNone); } static Widget MakePopup(name, parent, childProc) String name; Widget parent; XtCreatePopupChildProc childProc; { Widget pop; pop = XtVaCreatePopupShell(name, transientShellWidgetClass, parent, XtNcreatePopupChildProc, childProc, NULL); if (childProc) { XtAppAddWorkProc(XtWidgetToApplicationContext(parent), CreatePopupLater, (XtPointer) pop); } return pop; } /* ARGSUSED */ static void PopDown(widget, client_data, call_data) Widget widget; XtPointer client_data, call_data; { XtPopdown((Widget) client_data); } static void NominateFile(widget, title, callback) Widget widget; String title; XtCallbackProc callback; { Widget fileNom, nominator; XtCallbackList callbacks, callb; XtCallbackStatus callbackStatus; int closure = 10101; if (!PRIVATE(widget,file_nominator)) { PRIVATE(widget,file_nominator) = MakeFileNominator(widget); } fileNom = PRIVATE(widget,file_nominator); nominator = FileNominatorWindowFileNominatorWidget(fileNom); if ((callbackStatus = XtHasCallbacks(nominator, XtNselectCallback)) == XtCallbackHasSome) { XtVaGetValues(nominator, XtNselectCallback, &callbacks, NULL); for (callb = callbacks; (*callb).callback; ++callb) { if ((*callb).closure == (XtPointer) closure && (*callb).callback != callback) { XtRemoveCallback(nominator, XtNselectCallback, (*callb).callback, (*callb).closure); XtAddCallback(nominator, XtNselectCallback, callback, (XtPointer) closure); } } } else if (callbackStatus == XtCallbackHasNone) { XtAddCallback(nominator, XtNselectCallback, callback, (XtPointer) closure); } XtVaSetValues(fileNom, XtNtitle, title, NULL); PositionedPopup(widget, fileNom); } static void ConfirmDiscard(widget, callback) Widget widget; XtCallbackProc callback; { ConfirmerRequestConfirmation(PRIVATE(widget,confirm_popup), "There are unsaved changes", "Discard changes", callback, "unused", NULL, (XtPointer) widget); } /************************************************************* * * FileNominator Popup * *************************************************************/ /* ARGSUSED */ static void OnPopup(widget, client_data, call_data) Widget widget; XtPointer client_data, call_data; { FileNominatorClearName((Widget) client_data); } static Widget MakeFileNominator(axeText) Widget axeText; { char *assocFile, assocDir[MAXPATHLEN]; Widget fileNomWin, fileNom; if ( (assocFile = AxeTextGetAssociatedFile(axeText)) ) { strcpy(assocDir, assocFile); assocDir[rindex(assocDir, '/') - assocDir] = '\0'; } fileNomWin = XtVaCreatePopupShell( "filenompop", fileNominatorWindowWidgetClass, axeText, XtNinitialDirectory, assocFile ? assocDir : PRIVATE(axeText,initial_directory), NULL); if (PRIVATE(axeText,initial_directory)) { XtFree(PRIVATE(axeText,initial_directory)); PRIVATE(axeText,initial_directory) = (String) 0; } fileNom = FileNominatorWindowFileNominatorWidget(fileNomWin); XtAddCallback(fileNomWin, XtNpopupCallback, OnPopup, (XtPointer) fileNom); XtAddCallback(fileNom, XtNcancelCallback, PopDown, (XtPointer) fileNomWin); XtRealizeWidget(fileNomWin); return fileNomWin; } /************************************************************* * * NumericPad Popup * *************************************************************/ /* ARGSUSED */ static void GotoLineEnter(widget, client_data, call_data) Widget widget; XtPointer client_data, call_data; { Widget axeText = AxeTextWidgetParentOf(widget); NumericPadReturnStruct *number = (NumericPadReturnStruct *) call_data; XtPopdown(PRIVATE(axeText,numeric_pad)); AxeTextGotoLine(axeText, number->conversion); } /* ARGSUSED */ static void ClearPadDown(widget, client_data, call_data) Widget widget; XtPointer client_data, call_data; { NumericPadClear((Widget) client_data); } static Widget MakeNumericPad(axeText) Widget axeText; { Widget popup = XtVaCreatePopupShell("gotopop", transientShellWidgetClass, axeText, NULL); Widget numPad = XtVaCreateManagedWidget("gotoBody", numericPadWidgetClass, popup, NULL); XtAddCallback(numPad, XtNenterCallback, GotoLineEnter, (XtPointer) popup); XtAddCallback(numPad, XtNcancelCallback, PopDown, (XtPointer) popup); XtAddCallback(popup, XtNpopdownCallback, ClearPadDown, (XtPointer) numPad); XtRealizeWidget(popup); return popup; } /************************************************************* * * ControlCodeSelector Popup * *************************************************************/ /* ARGSUSED */ static void ControlEnter(widget, client_data, call_data) Widget widget; XtPointer client_data, call_data; { Widget axeText = AxeTextWidgetParentOf(widget); char ch = (char) ((int) call_data); XawTextBlock textBlock; XawTextPosition insertPos; void (*proc)(); insertPos = XawTextGetInsertionPoint(axeText); textBlock.firstPos = 0; textBlock.length = 1; textBlock.ptr = &ch; textBlock.format = FMT8BIT; if ( (proc = AxeiiTextUndoPreInsert(axeText)) ) { (*proc)(axeText); } XawTextReplace(axeText, insertPos, insertPos, &textBlock); XawTextSetInsertionPoint(axeText, insertPos + 1); } /* ARGSUSED */ static void ClearCtrlDown(widget, client_data, call_data) Widget widget; XtPointer client_data, call_data; { ControlCodeSelectorClear((Widget) client_data); } static Widget MakeControlSelector(axeText) Widget axeText; { Widget popup = XtVaCreatePopupShell("control", transientShellWidgetClass, axeText, NULL); Widget ctrlSel = XtVaCreateManagedWidget("ctrlBody", controlCodeSelectorWidgetClass, popup, NULL); XtAddCallback(ctrlSel, XtNenterCallback, ControlEnter, (XtPointer) popup); XtAddCallback(ctrlSel, XtNcancelCallback, PopDown, (XtPointer) popup); XtAddCallback(popup, XtNpopdownCallback, ClearCtrlDown, (XtPointer) ctrlSel); XtRealizeWidget(popup); return popup; } /************************************************************* * * Confirmer Popup * *************************************************************/ static void MakeConfirmPopup(popup) Widget popup; { /* * ConfirmerWidget is a subclass of TransientShell, so grab the * name of the shell that MakePopup made then jettison it. */ Widget axeText = XtParent(popup), oldpop = popup; popup = XtVaCreatePopupShell(XtName(oldpop), confirmerWidgetClass, axeText, NULL); XtDestroyWidget(oldpop); PRIVATE(axeText,confirm_popup) = popup; } /************************************************************* * * Preference Popup * *************************************************************/ static Widget MakePreferencePopup(axeText) Widget axeText; { Widget popup = XtVaCreatePopupShell("preferences", transientShellWidgetClass, axeText, NULL); Widget prefPop = XtVaCreateManagedWidget("prefBody", preferenceWidgetClass, popup, NULL); XtAddCallback(prefPop, XtNenterCallback, AcceptPreferences, (XtPointer) popup); XtAddCallback(prefPop, XtNcancelCallback, PopDown, (XtPointer) popup); XtRealizeWidget(popup); return popup; } /************************************************************* * * goto-line * *************************************************************/ /*ARGSUSED*/ static void GotoLine(w, client_data, call_data) Widget w; XtPointer client_data, call_data; { if (!PRIVATE(w,numeric_pad)) { PRIVATE(w,numeric_pad) = MakeNumericPad(w); } PositionedPopup(w, PRIVATE(w,numeric_pad)); } /************************************************************* * * include-file * *************************************************************/ /* ARGSUSED */ static void IncludeFileSelect(widget, client_data, call_data) Widget widget; XtPointer client_data, call_data; { Widget axe = AxeTextWidgetParentOf(widget); FileNominatorStruct *data = (FileNominatorStruct *) call_data; String newName; void (*proc)(); extern Boolean InsertFileNamed(); if (data->directoryPart && data->filenamePart && (data->filenameStatus & FileNominatorReadable)) { newName = XtMalloc(strlen(data->directoryPart) + strlen(data->filenamePart) + 1); strcpy(newName, data->directoryPart); strcat(newName, data->filenamePart); if ( (proc = AxeiiTextUndoPreInsert(axe)) ) { (*proc)(axe); } XtPopdown(PRIVATE(axe,file_nominator)); (void) InsertFileNamed(axe, newName); XtFree(newName); } else { MessageNotify(axe, AxeTextunreadableFile); } } /* ARGSUSED */ static void IncludeFile(widget, client_data, call_data) Widget widget; XtPointer client_data, call_data; { NominateFile(widget, "insert file", IncludeFileSelect); } /************************************************************* * * insert-control * *************************************************************/ /* ARGSUSED */ static void InsertControl(w, client_data, call_data) Widget w; XtPointer client_data, call_data; { if (!PRIVATE(w,control_selector)) { PRIVATE(w,control_selector) = MakeControlSelector(w); } PositionedPopup(w, PRIVATE(w,control_selector)); } /************************************************************* * * set-preferences * *************************************************************/ /*ARGSUSED*/ static void AcceptPreferences(w, client_data, call_data) Widget w; XtPointer client_data, call_data; { Widget axeText = AxeTextWidgetParentOf(w); PreferenceReturnStruct *preferences = (PreferenceReturnStruct *) call_data; XtPopdown((Widget) client_data); XtVaSetValues(axeText, XtNscrollVertical, preferences->scrollMode, XtNwrap, preferences->wrapMode, XtNautoFill, preferences->autoFill, XtNeditType, preferences->editType, XtNtabEvery, preferences->tabEvery, NULL); } /*ARGSUSED*/ static void SetPreferences(w, client_data, call_data) Widget w; XtPointer client_data, call_data; { if (!PRIVATE(w,preference_popup)) { PRIVATE(w,preference_popup) = MakePreferencePopup(w); } PositionedPopup(w, PRIVATE(w,preference_popup)); } /************************************************************* * * clear-text * *************************************************************/ /*ARGSUSED*/ static void ReallyClearBuffer(w, client_data, call_data) Widget w; XtPointer client_data, call_data; { Widget axe = (Widget) client_data; if (w != axe) { XtPopdown(PRIVATE(axe,confirm_popup)); } if (PRIVATE(axe,associated_file)) { XtFree(PRIVATE(axe,associated_file)); } PRIVATE(axe,null_file) = True; PRIVATE(axe,associated_file) = NULL; PRIVATE(axe,backed_up) = False; XtVaSetValues(axe, XtNstring, nullfile, NULL); RecordAndNotifyChange(axe, False); AxeiiTextWatchForChanges(axe); } /*ARGSUSED*/ static void ClearBuffer(w, client_data, call_data) Widget w; XtPointer client_data, call_data; { if (PRIVATE(w,is_modified)) { ConfirmDiscard(w, ReallyClearBuffer); } else { ReallyClearBuffer(w, (XtPointer) w, (XtPointer) 0); } } /************************************************************* * * save-file * *************************************************************/ static Boolean SaveAsFile(asciiSrc, filename) Widget asciiSrc; String filename; { Widget text = XtParent(asciiSrc); XawTextPosition pos = XawTextGetInsertionPoint(text), endpos, eol; XawTextBlock textBlock; char backupName[BUFSIZ]; char *r; Boolean backedUp = False; int status; struct stat stats; endpos = XawTextSourceScan(asciiSrc, pos, XawstAll, XawsdRight, 1, True); eol = XawTextSourceScan(asciiSrc, endpos, XawstEOL, XawsdLeft, 1, False); if (eol != endpos) { textBlock.firstPos = 0; textBlock.length = 1; textBlock.ptr = "\n"; textBlock.format = FMT8BIT; XawTextReplace(text, endpos, endpos, &textBlock); } if (PRIVATE(text,enable_backups) && !PRIVATE(text,backed_up)) { r = rindex(filename, '/') + 1; strncpy(backupName, filename, r - filename); backupName[r - filename] = '\0'; strcat(backupName, PRIVATE(text,backup_name_prefix)); strcat(backupName, r); strcat(backupName, PRIVATE(text,backup_name_suffix)); if ( (status = rename(filename, backupName)) == 0 || errno == ENOENT) { status = stat(backupName, &stats); backedUp = True; } else { return False; } } if (XawAsciiSaveAsFile(asciiSrc, filename)) { if (backedUp) { if (status == 0) { (void) chmod(filename, stats.st_mode); } PRIVATE(text,backed_up) = True; } MessageNotify(text, AxeTextsaveSuccess); return True; } else { if (backedUp) { /* What if this goes wrong? */ (void) rename(backupName, filename); } /* Error notification to be made by caller */ return False; } } /*ARGSUSED*/ static void SaveOver(w, client_data, call_data) Widget w; XtPointer client_data, call_data; { AxeTextWidget axe = (AxeTextWidget) AxeTextWidgetParentOf(w); if (!AxeTextSaveAsFile(axe, (FileNominatorStruct *) client_data)) { MessageNotify(axe, AxeTextsaveFailure); } AxeTextFreeNominatorStruct((FileNominatorStruct *) client_data); } /*ARGSUSED*/ static void SaveAgain(w, client_data, call_data) Widget w; XtPointer client_data, call_data; { AxeTextFreeNominatorStruct((FileNominatorStruct *) client_data); NominateFile(AxeTextWidgetParentOf(w), "file save", SaveFileSelect); } /*ARGSUSED*/ static void SaveFileSelect(w, client_data, call_data) Widget w; XtPointer client_data, call_data; { Widget axe = AxeTextWidgetParentOf(w); FileNominatorStruct *data = (FileNominatorStruct *) call_data, *nomination; if (data->directoryPart && data->filenamePart) { if (data->filenameStatus & FileNominatorNonexistent) { if (AxeTextSaveAsFile(axe, data)) { XtPopdown(PRIVATE(axe,file_nominator)); } else { MessageNotify(axe, AxeTextsaveFailure); } } else { XtPopdown(PRIVATE(axe,file_nominator)); /* * The FileNominatorStruct in the call_data is owned by the * FileNominator. As it is possible for the user to use the * FileNominator for other purposes before responding to the * Confirmer we had better take a copy. */ nomination = XtNew(FileNominatorStruct); nomination->directoryPart = XtNewString(data->directoryPart); nomination->directoryStatus = data->directoryStatus; nomination->filenamePart = XtNewString(data->filenamePart); nomination->filenameStatus = data->filenameStatus; ConfirmerRequestConfirmation(PRIVATE(axe,confirm_popup), "The file already exists", "overwrite", SaveOver, "re-select", SaveAgain, nomination); } } else { MessageNotify(axe, AxeTextinvalidDirectory); } } static Boolean FileSaved(w) Widget w; { Boolean saved; if ((saved = SaveAsFile(XawTextGetSource(w), AxeTextGetAssociatedFile(w)))) { RecordAndNotifyChange(w, False); AxeiiTextWatchForChanges(w); } return saved; } /*ARGSUSED*/ static void SaveFile(w, client_data, call_data) Widget w; XtPointer client_data, call_data; { if (!PRIVATE(w,is_modified)) { MessageNotify(w, AxeTextnotSaved); } else if (PRIVATE(w,null_file) && !PRIVATE(w,associated_file)) { NominateFile(w, "file save", SaveFileSelect); } else if (!FileSaved(w)) { MessageNotify(w, AxeTextsaveFailure); } } /************************************************************* * * save-as * *************************************************************/ /*ARGSUSED*/ static void SaveAs(w, client_data, call_data) Widget w; XtPointer client_data, call_data; { NominateFile(w, "file save", SaveFileSelect); } /************************************************************* * * reload-file * *************************************************************/ /* ARGSUSED */ static void ReloadFileConfirm(widget, client_data, call_data) Widget widget; XtPointer client_data, call_data; { Widget axe = (Widget) client_data; char *filename, saveFilename[MAXPATHLEN]; XawTextEditType editType; Boolean exists; AccessMode mode; void (*proc)(); if (widget != axe) { XtPopdown(PRIVATE(axe,confirm_popup)); } XtVaGetValues(axe, XtNstring, &filename, XtNeditType, &editType, NULL); strcpy(saveFilename, filename); if (CheckPermission(saveFilename, &exists, &mode) != 0) { MessageNotify(axe, AxeTextreloadFailure); return; } /* AsciiSrc attempts to open for update if mode is XawtextEdit, * so avoid by switching into XawtextRead mode. But still * making assumption that access hasn't been removed altogether. */ if (editType == XawtextEdit) { XtVaSetValues(axe, XtNeditType, XawtextRead, NULL); } /* Reload the file */ XtVaSetValues(axe, XtNstring, saveFilename, NULL); /* Adjust editing mode if necessary */ if (mode == EDIT) { XtVaSetValues(axe, XtNeditType, XawtextEdit, NULL); } RecordAndNotifyChange(axe, False); AxeiiTextWatchForChanges(axe); if ( (proc = AxeiiTextUndoPostLoad(axe)) ) { (*proc)(axe); } } /* ARGSUSED */ static void ReloadFile(widget, client_data, call_data) Widget widget; XtPointer client_data, call_data; { String file; XtVaGetValues(widget, XtNstring, &file, NULL); if (strcmp(file, nullfile) == 0) { MessageNotify(widget, AxeTextreloadFailure); return; } if (PRIVATE(widget,is_modified)) { ConfirmDiscard(widget, ReloadFileConfirm); } else { ReloadFileConfirm(widget, (XtPointer) widget, (XtPointer) 0); } } /************************************************************* * * load-file * *************************************************************/ /*ARGSUSED*/ static void LoadFileSelect(w, client_data, call_data) Widget w; XtPointer client_data, call_data; { Widget axe = AxeTextWidgetParentOf(w); if (AxeTextLoadFile(axe, (FileNominatorStruct *) call_data)) { XtPopdown(PRIVATE(axe,file_nominator)); } } /* ARGSUSED */ static void LoadFileConfirm(widget, client_data, call_data) Widget widget; XtPointer client_data, call_data; { Widget axe = (Widget) client_data; XtPopdown(PRIVATE(axe,confirm_popup)); NominateFile(axe, "file load", LoadFileSelect); } /* ARGSUSED */ static void LoadFile(widget, client_data, call_data) Widget widget; XtPointer client_data, call_data; { if (PRIVATE(widget,is_modified)) { ConfirmDiscard(widget, LoadFileConfirm); } else { NominateFile(widget, "file load", LoadFileSelect); } } /* ARGSUSED */ static void NoUndo(widget, client_data, call_data) Widget widget; XtPointer client_data, call_data; { MessageNotify(widget, AxeTextnoUndo); } /************************************************************* * * Public functions * *************************************************************/ Widget AxeTextWidgetParentOf(w) Widget w; { Widget axeText; for (axeText = w; axeText; axeText = XtParent(axeText)) { if (XtIsSubclass(axeText, axeTextWidgetClass)) { return axeText; } } return (Widget) 0; } Widget AxeTextFileNominator(w) Widget w; { if (XtIsSubclass(w, axeTextWidgetClass)) { CompositeWidget nominator; if ( (nominator = ((CompositeWidget) PRIVATE(w,file_nominator)) )) { return nominator->composite.children[0]; } } return (Widget) 0; } Boolean AxeTextIsModified(atw) Widget atw; { if (XtIsSubclass(atw, axeTextWidgetClass)) { return PRIVATE(atw,is_modified); } else { return False; } } String AxeTextGetAssociatedFile(atw) Widget atw; { String file; if (!XtIsSubclass(atw, axeTextWidgetClass)) { return (String) 0; } if (PRIVATE(atw,null_file)) { if (PRIVATE(atw,associated_file)) { return PRIVATE(atw,associated_file); } else { return (String) 0; } } else { XtVaGetValues(atw, XtNstring, &file, NULL); return file; } } Boolean AxeTextSaveFile(atw) Widget atw; { if (!XtIsSubclass(atw, axeTextWidgetClass)) { return False; } if (!AxeTextGetAssociatedFile(atw)) { return False; } else { return FileSaved(atw); } } Boolean AxeTextSaveAsFile(widget, fnomStruct) Widget widget; FileNominatorStruct *fnomStruct; { String fileName, newName; if (!XtIsSubclass(widget, axeTextWidgetClass)) { return False; } if (fnomStruct->directoryPart && fnomStruct->filenamePart) { newName = XtMalloc(strlen(fnomStruct->directoryPart) + strlen(fnomStruct->filenamePart) + 1); strcpy(newName, fnomStruct->directoryPart); strcat(newName, fnomStruct->filenamePart); if (SaveAsFile(XawTextGetSource(widget), newName)) { if (PRIVATE(widget,null_file)) { PRIVATE(widget,null_file) = False; if (PRIVATE(widget,associated_file)) { XtFree(PRIVATE(widget,associated_file)); } PRIVATE(widget,associated_file) = NULL; XtVaSetValues(widget, XtNstring, newName, NULL); } else { XtVaGetValues(widget, XtNstring, &fileName, NULL); if (strcmp(fileName, newName) != 0) { XtVaSetValues(widget, XtNstring, newName, NULL); } } RecordAndNotifyChange(widget, False); AxeiiTextWatchForChanges(widget); XtFree(newName); return True; } else { MessageNotify(widget, AxeTextsaveFailure); XtFree(newName); return False; } } else { MessageNotify(widget, AxeTextinvalidDirectory); return False; } } void AxeTextFileToNominatorStruct(file, nomStruct) String file; FileNominatorStruct *nomStruct; { String r; struct stat fstats; int status; status = stat(file, &fstats); if (status != -1 && fstats.st_mode & S_IFDIR) { nomStruct->filenamePart = NULL; nomStruct->filenameStatus = FileNominatorNonexistent; status |= (access(file, R_OK) == 0) ? FileNominatorReadable : 0; status |= (access(file, W_OK) == 0) ? FileNominatorWritable : 0; status |= (access(file, X_OK) == 0) ? FileNominatorExecutable : 0; nomStruct->directoryPart = XtNewString(file); nomStruct->directoryStatus = status; } else if (status == 0 || (status == -1 && errno == ENOENT)) { status |= (access(file, R_OK) == 0) ? FileNominatorReadable : 0; status |= (access(file, W_OK) == 0) ? FileNominatorWritable : 0; status |= (access(file, X_OK) == 0) ? FileNominatorExecutable : 0; nomStruct->filenameStatus = status; r = rindex(file, '/'); nomStruct->filenamePart = XtNewString(r + 1); *(r + 1) = '\0'; status = stat(file, &fstats); if (status == -1) { nomStruct->directoryPart = 0; nomStruct->directoryStatus = FileNominatorNonexistent; } else { status |= (access(file, R_OK) == 0) ? FileNominatorReadable : 0; status |= (access(file, W_OK) == 0) ? FileNominatorWritable : 0; status |= (access(file, X_OK) == 0) ? FileNominatorExecutable : 0; nomStruct->directoryPart = XtNewString(file); nomStruct->directoryStatus = status; } } else { nomStruct->directoryPart = NULL; nomStruct->directoryStatus = FileNominatorNonexistent; nomStruct->filenamePart = NULL; nomStruct->filenameStatus = FileNominatorNonexistent; } } void AxeTextFreeNominatorStruct(nomStruct) FileNominatorStruct *nomStruct; { XtFree(nomStruct->filenamePart); XtFree(nomStruct->directoryPart); } Boolean AxeTextLoadFile(widget, fnomStruct) Widget widget; FileNominatorStruct *fnomStruct; { String newName, useName; XawTextEditType editMode; Boolean returnStatus; void (*proc)(); if (!XtIsSubclass(widget, axeTextWidgetClass)) { return False; } if (!fnomStruct->filenamePart) { MessageNotify(widget, AxeTextinvalidFilename); return False; } if (!fnomStruct->directoryPart) { MessageNotify(widget, AxeTextinvalidDirectory); return False; } if (fnomStruct->directoryStatus & FileNominatorExecutable) { newName = XtMalloc(strlen(fnomStruct->directoryPart) + strlen(fnomStruct->filenamePart) + 1); strcpy(newName, fnomStruct->directoryPart); strcat(newName, fnomStruct->filenamePart); if (PRIVATE(widget,associated_file)) { XtFree(PRIVATE(widget,associated_file)); } if (fnomStruct->filenameStatus & FileNominatorNonexistent) { PRIVATE(widget,null_file) = True; PRIVATE(widget,associated_file) = XtNewString(newName); useName = XtNewString(nullfile); editMode = XawtextEdit; } else { PRIVATE(widget,null_file) = False; PRIVATE(widget,associated_file) = NULL; useName = newName; editMode = (fnomStruct->filenameStatus & FileNominatorWritable) ? XawtextEdit : XawtextRead; } if (fnomStruct->filenameStatus & FileNominatorReadable || fnomStruct->filenameStatus & FileNominatorNonexistent) { XtVaSetValues(widget, XtNstring, useName, XtNeditType, editMode, NULL); RecordAndNotifyChange(widget, False); AxeiiTextWatchForChanges(widget); PRIVATE(widget,backed_up) = False; if ( (proc = AxeiiTextUndoPostLoad(widget)) ) { (*proc)(widget); } returnStatus = True; } else { MessageNotify(widget, AxeTextunreadableFile); returnStatus = False; } XtFree(newName); if (useName != newName) { XtFree(useName); } } else { MessageNotify(widget, AxeTextinvalidDirectory); returnStatus = False; } return returnStatus; } void AxeTextGotoLine(atw, line) Widget atw; int line; { XawTextPosition bol, eol; if (!XtIsSubclass(atw, axeTextWidgetClass)) { return; } AxeiiTextGotoLine(atw, line); bol = XawTextGetInsertionPoint(atw); eol = XawTextSourceScan(XawTextGetSource(atw), bol, XawstEOL, XawsdRight, 1, True); XawTextSetSelection(atw, bol, eol); XtCallActionProc(atw, "redraw-display", (XEvent *) 0, (String *) 0, (Cardinal) 0); } #undef AXEII #undef PRIVATE axe-6.1.2.orig/Widgets/AxeText.h100644 243 144 5720 5550557121 15140 0ustar joostusers/* * Copyright 1992, 1993 The University of Newcastle upon Tyne * * Permission to use, copy, modify and distribute this software and its * documentation for any purpose other than its commercial exploitation * is hereby granted without fee, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of The University of Newcastle upon Tyne not be used in * advertising or publicity pertaining to distribution of the software * without specific, written prior permission. The University of * Newcastle upon Tyne makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * THE UNIVERSITY OF NEWCASTLE UPON TYNE DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF * NEWCASTLE UPON TYNE BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. * * Author: Jim Wight (j.k.wight@newcastle.ac.uk) * Department of Computing Science * University of Newcastle upon Tyne, UK */ #ifndef _AxeText_h #define _AxeText_h #include typedef struct _AxeTextClassRec *AxeTextWidgetClass; typedef struct _AxeTextRec *AxeTextWidget; extern WidgetClass axeTextWidgetClass; #define XtNassociatedDirectory "associatedDirectory" #define XtCAssociatedDirectory "AssociatedDirectory" #define XtNgrabOnPopup "grabOnPopup" #define XtCGrabOnPopup "GrabOnPopup" #define XtNchangeCallback "changeCallback" #define XtNmessageCallback "messageCallback" #define XtNenableBackups "enableBackups" #define XtCEnableBackups "Enablebackups" #define XtNbackupNamePrefix "backupNamePrefix" #define XtCBackupNamePrefix "BackupNamePrefix" #define XtNbackupNameSuffix "backupNameSuffix" #define XtCBackupNameSuffix "BackupNameSuffix" #define AxeTextsaveSuccess 1 #define AxeTexterrorCodes 10 #define AxeTextnotSaved 11 #define AxeTextsaveFailure 12 #define AxeTextinvalidFilename 13 #define AxeTextinvalidDirectory 14 #define AxeTextinvalidControlCode 15 #define AxeTextreloadFailure 16 #define AxeTextunreadableFile 17 #define AxeTextnoUndo 18 extern Boolean AxeTextIsModified(); extern Widget AxeTextWidgetParentOf(); extern Widget AxeTextFileNominator(); extern String AxeTextGetAssociatedFile(); extern Boolean AxeTextSaveFile(); extern Boolean AxeTextSaveAsFile(); extern void AxeTextFileToNominatorStruct(); extern void AxeTextFreeNominatorStruct(); extern Boolean AxeTextLoadFile(); extern void AxeTextGotoLine(); #endif /* _AxeText_h */ axe-6.1.2.orig/Widgets/AxeTextDeck.c100644 243 144 40035 5550557112 15740 0ustar joostusers/* * Copyright 1992, 1993 The University of Newcastle upon Tyne * * Permission to use, copy, modify and distribute this software and its * documentation for any purpose other than its commercial exploitation * is hereby granted without fee, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of The University of Newcastle upon Tyne not be used in * advertising or publicity pertaining to distribution of the software * without specific, written prior permission. The University of * Newcastle upon Tyne makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * THE UNIVERSITY OF NEWCASTLE UPON TYNE DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF * NEWCASTLE UPON TYNE BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. * * Author: Jim Wight (j.k.wight@newcastle.ac.uk) * Department of Computing Science * University of Newcastle upon Tyne, UK */ #include #include #include #include #include #include #include #include #include #include #define CLASS(field) axeTextDeckClassRec.axeTextDeck_class.field #define PRIVATE(w,field) (((AxeTextDeckWidget) w)->axeTextDeck.field) #define Offset(field) XtOffsetOf(AxeTextDeckRec, axeTextDeck.field) static XtResource resources[] = { {XtNfile, XtCFile, XtRString, sizeof(String), Offset(file), XtRString, NULL}, {XtNchangeCallback, XtCCallback, XtRCallback, sizeof(XtCallbackList), Offset(change_callbacks), XtRCallback, (XtPointer) NULL}, {XtNfont, XtCFont, XtRFontStruct, sizeof(XFontStruct*), Offset(font), XtRFontStruct, (XtPointer) NULL}, }; #undef Offset static void Initialize(); static void Realize(), Resize(), InsertChild(), DeleteChild(); static Boolean SetValues(); static XtGeometryResult GeometryManager(); static void DeckChange(), Message(), Where(), Size(); AxeTextDeckClassRec axeTextDeckClassRec = { { /* core_class fields */ /* superclass */ (WidgetClass) &compositeClassRec, /* class_name */ "AxeTextDeck", /* widget_size */ sizeof(AxeTextDeckRec), /* class_initialize */ NULL, /* class_part_init */ NULL, /* class_inited */ FALSE, /* initialize */ Initialize, /* initialize_hook */ NULL, /* realize */ Realize, /* actions */ NULL, /* num_actions */ 0, /* resources */ resources, /* num_resources */ XtNumber(resources), /* xrm_class */ NULLQUARK, /* compress_motion */ TRUE, /* compress_exposure */ TRUE, /* compress_enterleave*/ TRUE, /* visible_interest */ FALSE, /* destroy */ NULL, /* resize */ Resize, /* expose */ XtInheritExpose, /* set_values */ SetValues, /* set_values_hook */ NULL, /* set_values_almost */ XtInheritSetValuesAlmost, /* get_values_hook */ NULL, /* accept_focus */ NULL, /* version */ XtVersion, /* callback_private */ NULL, /* tm_table */ NULL, /* query_geometry */ XtInheritQueryGeometry, /* display_accelerator*/ XtInheritDisplayAccelerator, /* extension */ NULL },{ /* composite_class fields */ /* geometry_manager */ GeometryManager, /* change_managed */ XtInheritChangeManaged, /* insert_child */ InsertChild, /* delete_child */ DeleteChild, /* extension */ NULL },{ /* AxeTextDeck class fields */ /* empty */ 0, } }; WidgetClass axeTextDeckWidgetClass = (WidgetClass) &axeTextDeckClassRec; /* ARGSUSED */ static void Initialize(req, new, args, num_args) Widget req, new; ArgList args; Cardinal *num_args; { String file = PRIVATE(new,file), fp, finalfp, fq, theFile, expandedName; char filename[MAXPATHLEN]; extern String AxeEditorExpandName(); /* * The file resource may be NULL or contain multiple files. * Do some cheap and nasty parsing. */ fp = file; if (fp && *fp == '\0') { fp = NULL; } if (fp) { finalfp = fp + strlen(fp); } else { finalfp = filename; /* Anything that's not NULL */ } while (fp != finalfp) { if (fp) { while (*fp == ' ' || *fp == '\n' || *fp == '\t') ++fp; if (!*fp) break; if ( (fq = index(fp, ' ')) || (fq = index(fp, '\n')) || (fq = index(fp, '\t'))) { strncpy(filename, fp, fq - fp); filename[fq - fp] = '\0'; theFile = filename; fp = fq + 1; } else { theFile = fp; fp = file + strlen(file); } } else { theFile = fp; fp = finalfp; } if (theFile) { expandedName = AxeEditorExpandName(theFile); } else { expandedName = theFile; } XtVaCreateManagedWidget("ed", axeTextWidgetClass, new, XtNstring, expandedName, NULL); if (expandedName) { XtFree(expandedName); } } } static void Realize(w, valueMask, attributes) Widget w; Mask *valueMask; XSetWindowAttributes *attributes; { WidgetList children; Cardinal numChildren, child; /* * Realizing in reverse order from normal means that the last value * put in PRIVATE(w,ed) by InsertChild is correct when the deck is * created with multiple children; also, the order is consistent * with the stacking of windows, i.e. last named file on top. */ (*axeTextDeckWidgetClass->core_class.superclass->core_class.realize) (w, valueMask, attributes); XtVaGetValues(w, XtNchildren, &children, XtNnumChildren, &numChildren, NULL); for (child = 0; child < numChildren; ++child) { XtRealizeWidget(children[child]); } XMapSubwindows(XtDisplay(w), XtWindow(w)); } static void Resize(w) AxeTextDeckWidget w; { int child; Widget childWidget; for (child = 0; child < w->composite.num_children; ++child) { childWidget = ((CompositeWidget) w)->composite.children[child]; if (childWidget == PRIVATE(w,ed)) { XtConfigureWidget(childWidget, (Position) -(childWidget->core.border_width), (Position) -(childWidget->core.border_width), w->core.width, w->core.height, childWidget->core.border_width); } } } /* ARGSUSED */ static Boolean SetValues(old, request, new, args, num_args) Widget old, request, new; ArgList args; Cardinal *num_args; { AxeTextDeckWidget oatdw = (AxeTextDeckWidget) old; AxeTextDeckWidget atdw = (AxeTextDeckWidget) new; int child; if (atdw->axeTextDeck.font != oatdw->axeTextDeck.font) { for (child = 0; child < atdw->composite.num_children; ++child) { XtVaSetValues(atdw->composite.children[child], XtNfont, atdw->axeTextDeck.font, NULL); } } return False; } static void InsertChild(w) Widget w; { AxeTextDeckWidget atdw = (AxeTextDeckWidget) XtParent(w); XFontStruct *font; (*((CompositeWidgetClass) (axeTextDeckWidgetClass-> core_class.superclass))->composite_class.insert_child) (w); /* The size of the AxeTextDeck containing the child is determined from * the size of the child in the case of the first child, so the core * variables obviously aren't available. */ if (atdw->composite.num_children ==1) { XtVaGetValues(w, XtNfont, &font, NULL); PRIVATE(atdw,font) = font; atdw->core.width = (atdw->composite.children[0])->core.width; atdw->core.height = (atdw->composite.children[0])->core.height; XtMoveWidget(w, (Position) -w->core.border_width, (Position) -w->core.border_width); } else { XtConfigureWidget(w, (Position) -w->core.border_width, (Position) -w->core.border_width, XtParent(w)->core.width, XtParent(w)->core.height, w->core.border_width); } PRIVATE(atdw,ed) = w; XtAddCallback(w, XtNchangeCallback, DeckChange, (XtPointer) 0); XtAddCallback(w, XtNmessageCallback, Message, (XtPointer) 0); XtAddCallback(w, XtNwhereCallback, Where, (XtPointer) 0); XtAddCallback(w, XtNsizeCallback, Size, (XtPointer) 0); XtCallCallbackList((Widget) atdw, PRIVATE(atdw,change_callbacks), (XtPointer) 0); } static void DeleteChild(child) Widget child; { AxeTextDeckWidget atdw = (AxeTextDeckWidget) XtParent(child); (*((CompositeWidgetClass) (axeTextDeckWidgetClass-> core_class.superclass))->composite_class.delete_child) (child); if (atdw->composite.num_children == 0) { XtDestroyWidget(XtParent(child)); } else { AxeTextDeckRaise(atdw, atdw->composite.children[0]); } } /* ARGSUSED */ static XtGeometryResult GeometryManager(w, desired, allowed) Widget w; XtWidgetGeometry *desired, *allowed; { AxeTextDeckWidget atdw = (AxeTextDeckWidget) XtParent(w); XtWidgetGeometry request; XtGeometryResult result; #define REQUESTS(flag) (desired->request_mode & flag) request.request_mode = desired->request_mode; request.width = desired->width; request.height = desired->height; result = XtMakeGeometryRequest((Widget) atdw, &request, (XtWidgetGeometry *) 0); if (REQUESTS(XtCWQueryOnly)) { return result; } if (result == XtGeometryYes) { if (REQUESTS(CWWidth)) { w->core.width = desired->width; } if (REQUESTS(CWHeight)) { w->core.height = desired->height; } return XtGeometryYes; } else { return XtGeometryNo; } #undef REQUESTS } /* ARGSUSED */ static void DeckChange(w, client_data, call_data) Widget w; XtPointer client_data, call_data; { XtCallCallbackList(XtParent(w), PRIVATE(XtParent(w),change_callbacks), (XtPointer) 0); } /* ARGSUSED */ static void Message(w, client_data, call_data) Widget w; XtPointer client_data, call_data; { int code = (int) call_data; Widget axeEditor = AxeEditorParentOf(w); switch (code) { case AxeTextsaveSuccess: AxeEditorUpdateInfoBar(axeEditor, "File written"); break; case AxeTextnotSaved: AxeEditorUpdateInfoBar(axeEditor, "No changes to save"); break; case AxeTextsaveFailure: AxeEditorUpdateInfoBar(axeEditor, "Save failed"); break; case AxeTextinvalidFilename: AxeEditorUpdateInfoBar(axeEditor, "Invalid filename component in path"); break; case AxeTextinvalidDirectory: AxeEditorUpdateInfoBar(axeEditor, "Invalid directory component in path"); break; case AxeTextunreadableFile: AxeEditorUpdateInfoBar(axeEditor, "File unreadable"); break; case AxeTextinvalidControlCode: AxeEditorUpdateInfoBar(axeEditor, "Control code value is greater than 255 decimal"); break; case AxeTextreloadFailure: AxeEditorUpdateInfoBar(axeEditor, "Reload failed"); break; case AxeTextnoUndo: AxeEditorUpdateInfoBar(axeEditor, "Nothing to undo"); break; default: AxeEditorUpdateInfoBar(axeEditor, "Unknown error reported"); break; } if (code > AxeTexterrorCodes) { XBell(XtDisplay(w), 100); } } /*ARGSUSED*/ static void Where(w, client_data, call_data) Widget w; XtPointer client_data, call_data; { AxeiiTextWhereStruct *where = (AxeiiTextWhereStruct *) call_data; char buf[BUFSIZ]; sprintf(buf, "Line %d Position %d", where->line, where->position); AxeEditorUpdateInfoBar(AxeEditorParentOf(w), buf); } /*ARGSUSED*/ static void Size(w, client_data, call_data) Widget w; XtPointer client_data, call_data; { AxeiiTextSizeStruct *size = (AxeiiTextSizeStruct *) call_data; char buf[BUFSIZ]; sprintf(buf, "The text buffer is %d x %d", size->columns, size->rows); AxeEditorUpdateInfoBar(AxeEditorParentOf(w), buf); } /************************************************************* * * Public functions * *************************************************************/ Widget AxeTextDeckTop(atdw) Widget atdw; { if (XtIsSubclass(atdw, axeTextDeckWidgetClass)) { return PRIVATE(atdw,ed); } return (Widget) 0; } void AxeTextDeckRaise(atdw, w) Widget atdw, w; { int rows, cols; Dimension width, height; if (!XtIsSubclass(atdw, axeTextDeckWidgetClass)) { return; } /* * The window being raised should be the same size as the one on top * Resetting the deck size should cope with scrollbar differences */ XtVaGetValues(PRIVATE(atdw,ed), XtNrows, &rows, XtNcolumns, &cols, NULL); XtVaSetValues(w, XtNrows, rows, XtNcolumns, cols, NULL); AxeiiTextRowsColumnsToWidthHeight(rows, cols, w, &width, &height), XRaiseWindow(XtDisplay(w), XtWindow(w)); PRIVATE(atdw,ed) = w; XtVaSetValues(atdw, XtNwidth, width, XtNheight, height, NULL); XtCallCallbackList(atdw, PRIVATE(atdw,change_callbacks), (XtPointer) 0); } AxeTextDeckList AxeTextDeckListOf(atdw) Widget atdw; { WidgetList children, copyChildren; Cardinal numChildren; int child; AxeTextDeckList list; String assocFile; if (!XtIsSubclass(atdw, axeTextDeckWidgetClass)) { return (AxeTextDeckList) 0; } XtVaGetValues(atdw, XtNchildren, &children, XtNnumChildren, &numChildren, NULL); copyChildren = (WidgetList) XtMalloc(numChildren * sizeof(Widget)); for (child = 0; child < numChildren; ++child) { copyChildren[child] = children[child]; } list = (AxeTextDeckList) XtMalloc((numChildren + 1) * sizeof(AxeTextDeckListItem)); for (child = 0; child < numChildren; ++child) { list[child].widget = copyChildren[child]; assocFile = AxeTextGetAssociatedFile(copyChildren[child]); list[child].file = assocFile ? XtNewString(assocFile) : XtNewString(noname); } list[numChildren].widget = (Widget) 0; list[numChildren].file = (String) 0; XtFree((char *) copyChildren); return list; } Boolean AxeTextDeckIterate(atdw, iteration) Widget atdw; AxeIterationType iteration; { WidgetList children; Cardinal numChildren; int child, count = 0; if (!XtIsSubclass(atdw, axeTextDeckWidgetClass)) { return False; } XtVaGetValues(atdw, XtNchildren, &children, XtNnumChildren, &numChildren, NULL); for (child = 0; child < numChildren; ++child) { switch (iteration) { case AxeIsModified: if (AxeTextIsModified(children[child])) { ++count; } break; case AxeSafeClose: if (!AxeTextIsModified(children[child])) { XtDestroyWidget(children[child]); ++count; } break; case AxeSave: if (AxeTextIsModified(children[child])) { if (AxeTextSaveFile(children[child])) { ++count; } } else { ++count; } break; default: ; } } return (iteration == AxeIsModified) ? count > 0 : count == numChildren; } void AxeTextDeckCloseTop(atdw) Widget atdw; { if (!XtIsSubclass(atdw, axeTextDeckWidgetClass)) { return; } XtDestroyWidget(PRIVATE(atdw,ed)); } void AxeTextDeckSetAssociatedDirectory(atdw, directory) Widget atdw; String directory; { WidgetList children; Cardinal numChildren; int child; if (!XtIsSubclass(atdw, axeTextDeckWidgetClass)) { return; } XtVaGetValues(atdw, XtNchildren, &children, XtNnumChildren, &numChildren, NULL); for (child = 0; child < numChildren; ++child) { XtVaSetValues(children[child], XtNassociatedDirectory, directory, NULL); } } #undef PRIVATE #undef CLASS axe-6.1.2.orig/Widgets/AxeTextDeck.h100644 243 144 3772 5550557121 15734 0ustar joostusers/* * Copyright 1992 The University of Newcastle upon Tyne * * Permission to use, copy, modify and distribute this software and its * documentation for any purpose other than its commercial exploitation * is hereby granted without fee, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of The University of Newcastle upon Tyne not be used in * advertising or publicity pertaining to distribution of the software * without specific, written prior permission. The University of * Newcastle upon Tyne makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * THE UNIVERSITY OF NEWCASTLE UPON TYNE DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF * NEWCASTLE UPON TYNE BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. * * Author: Jim Wight (j.k.wight@newcastle.ac.uk) * Department of Computing Science * University of Newcastle upon Tyne, UK */ #ifndef _AxeTextDeck_h #define _AxeTextDeck_h typedef struct _AxeTextDeckClassRec *AxeTextDeckClass; typedef struct _AxeTextDeckRec *AxeTextDeckWidget; extern WidgetClass axeTextDeckWidgetClass; typedef struct _AxeTextDeckList { Widget widget; String file; } *AxeTextDeckList, AxeTextDeckListItem; extern Widget AxeTextDeckTop(); extern void AxeTextDeckRaise(); extern AxeTextDeckList AxeTextDeckListOf(); extern Boolean AxeTextDeckIterate(); extern void AxeTextDeckCloseTop(); extern void AxeTextDeckSetAssociatedDirectory(); #endif /* _AxeTextDeck_h */ axe-6.1.2.orig/Widgets/AxeTextDeckP.h100644 243 144 4404 5550557121 16045 0ustar joostusers/* * Copyright 1992 The University of Newcastle upon Tyne * * Permission to use, copy, modify and distribute this software and its * documentation for any purpose other than its commercial exploitation * is hereby granted without fee, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of The University of Newcastle upon Tyne not be used in * advertising or publicity pertaining to distribution of the software * without specific, written prior permission. The University of * Newcastle upon Tyne makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * THE UNIVERSITY OF NEWCASTLE UPON TYNE DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF * NEWCASTLE UPON TYNE BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. * * Author: Jim Wight (j.k.wight@newcastle.ac.uk) * Department of Computing Science * University of Newcastle upon Tyne, UK */ #ifndef _AxeTextDeckP_h #define _AxeTextDeckP_h #include typedef struct { XtPointer extension; XtTranslations axeiiTextTranslations; } AxeTextDeckClassPart; typedef struct _AxeTextDeckClassRec { CoreClassPart core_class; CompositeClassPart composite_class; AxeTextDeckClassPart axeTextDeck_class; } AxeTextDeckClassRec; externalref AxeTextDeckClassRec axeTextDeckClassRec; typedef struct { /* Resources */ String file; XtCallbackList change_callbacks; XFontStruct *font; /* Private */ Widget ed; } AxeTextDeckPart, *AxeTextDeckPtr; typedef struct _AxeTextDeckRec { CorePart core; CompositePart composite; AxeTextDeckPart axeTextDeck; } AxeTextDeckRec; #endif /* _AxeTextDeckP_h */ axe-6.1.2.orig/Widgets/AxeTextP.h100644 243 144 5703 5550557121 15261 0ustar joostusers/* * Copyright 1992 The University of Newcastle upon Tyne * * Permission to use, copy, modify and distribute this software and its * documentation for any purpose other than its commercial exploitation * is hereby granted without fee, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of The University of Newcastle upon Tyne not be used in * advertising or publicity pertaining to distribution of the software * without specific, written prior permission. The University of * Newcastle upon Tyne makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * THE UNIVERSITY OF NEWCASTLE UPON TYNE DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF * NEWCASTLE UPON TYNE BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. * * Author: Jim Wight (j.k.wight@newcastle.ac.uk) * Department of Computing Science * University of Newcastle upon Tyne, UK */ #ifndef _AxeTextP_h #define _AxeTextP_h #include #include typedef struct { XtPointer extension; } AxeClassPart; typedef struct _AxeTextClassRec { CoreClassPart core_class; SimpleClassPart simple_class; TextClassPart text_class; AsciiClassPart ascii_class; AxeiiClassPart axeii_class; AxeClassPart axe_class; } AxeTextClassRec; extern AxeTextClassRec axeTextClassRec; typedef struct { /* Resources */ String associated_directory; Boolean grab_on_popup; XtCallbackList change_callbacks; XtCallbackList message_callbacks; Boolean enable_backups; String backup_name_prefix; String backup_name_suffix; /* Private variables */ String initial_directory; Boolean null_file; String associated_file; Boolean is_modified; Widget file_nominator; Widget numeric_pad; Widget control_selector; Widget confirm_popup; Widget confirm_message; Widget confirm_confirm; Widget preference_popup; Boolean backed_up; } AxePart; typedef struct _AxeTextRec { CorePart core; SimplePart simple; TextPart text; AsciiPart ascii; AxeiiPart axeii; AxePart axe; } AxeTextRec; #endif /* _AxeTextP_h */ axe-6.1.2.orig/Widgets/AxeWindow.c100644 243 144 23207 5600335236 15473 0ustar joostusers/* * Copyright 1992, 1994 The University of Newcastle upon Tyne * * Permission to use, copy, modify and distribute this software and its * documentation for any purpose other than its commercial exploitation * is hereby granted without fee, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of The University of Newcastle upon Tyne not be used in * advertising or publicity pertaining to distribution of the software * without specific, written prior permission. The University of * Newcastle upon Tyne makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * * * THE UNIVERSITY OF NEWCASTLE UPON TYNE DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF * NEWCASTLE UPON TYNE BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. * * Author: Jim Wight (j.k.wight@newcastle.ac.uk) * Department of Computing Science * University of Newcastle upon Tyne, UK */ #include #include #include #include #include #include "AxeWindowP.h" #define CARETHEIGHT (XT_REVISION < 5 ? caretHeight : 0) #define CLASS(field) axeWindowClassRec.axeWindow_class.field #define PRIVATE(w,field) (((AxeWindowWidget) w)->axeWindow.field) #define WMShellOffset(field) XtOffsetOf(AxeWindowRec, wm.field) #define TopLevelOffset(field) XtOffsetOf(AxeWindowRec, topLevel.field) #define Offset(field) XtOffsetOf(AxeWindowRec, axeWindow.field) static XtResource resources[] = { /* WMShell Widget Resources */ { XtNtitle, XtCTitle, XtRString, sizeof(String), WMShellOffset(title), XtRImmediate, (XtPointer) "axe"}, /* TopLevelShell Widget Resources */ { XtNiconName, XtCIconName, XtRString, sizeof(String), TopLevelOffset(icon_name), XtRImmediate, (XtPointer) "axe"}, /* AxeWindow Widget Resources */ {XtNfile, XtCFile, XtRString, sizeof(String), Offset(file), XtRString, NULL}, {XtNfileTitle, XtCFileTitle, XtRBoolean, sizeof(Boolean), Offset(file_title), XtRImmediate, (XtPointer) False}, {XtNfileTitlePrefix, XtCFileTitlePrefix, XtRString, sizeof(String), Offset(file_title_prefix), XtRImmediate, (XtPointer) "axe:"}, {XtNiconNamePrefix, XtCFileTitlePrefix, XtRString, sizeof(String), Offset(icon_name_prefix), XtRImmediate, (XtPointer) "axe:"}, {XtNexitOnCloseLastWindow, XtCExitOnCloseLastWindow, XtRBoolean, sizeof(Boolean), Offset(exit_on_close_last_window), XtRImmediate, (XtPointer) False}, }; #undef Offset static void Initialize(), Destroy(), Resize(); static XtGeometryResult GeometryManager(); static void DeleteChild(); static void ChangeOfTitle(), SetWMHints(), CloseWindow(); static XtActionsRec actions[] = { "close-window", CloseWindow, }; static char translations[] = "WM_PROTOCOLS:close-window()"; AxeWindowClassRec axeWindowClassRec = { { /* superclass */ (WidgetClass) &topLevelShellClassRec, /* class_name */ "AxeWindow", /* size */ sizeof(AxeWindowRec), /* Class Initializer */ NULL, /* class_part_initialize*/ NULL, /* Class init'ed ? */ FALSE, /* initialize */ Initialize, /* initialize_notify */ NULL, /* realize */ XtInheritRealize, /* actions */ actions, /* num_actions */ XtNumber(actions), /* resources */ resources, /* resource_count */ XtNumber(resources), /* xrm_class */ NULLQUARK, /* compress_motion */ FALSE, /* compress_exposure */ TRUE, /* compress_enterleave*/ FALSE, /* visible_interest */ FALSE, /* destroy */ Destroy, /* resize */ Resize, /* expose */ NULL, /* set_values */ NULL, /* set_values_hook */ NULL, /* set_values_almost */ XtInheritSetValuesAlmost, /* get_values_hook */ NULL, /* accept_focus */ NULL, /* intrinsics version */ XtVersion, /* callback offsets */ NULL, /* tm_table */ translations, /* query_geometry */ NULL, /* display_accelerator */ NULL, /* extension */ NULL },{ /* geometry_manager */ GeometryManager, /* change_managed */ XtInheritChangeManaged, /* insert_child */ XtInheritInsertChild, /* delete_child */ DeleteChild, /* extension */ NULL },{ /* extension */ NULL },{ /* extension */ NULL },{ /* extension */ NULL },{ /* extension */ NULL },{ /* extension */ NULL } }; WidgetClass axeWindowWidgetClass = (WidgetClass) &axeWindowClassRec; /* ARGSUSED */ static void Initialize(req, new, args, num_args) Widget req, new; ArgList args; Cardinal *num_args; { Widget aew; CLASS(number_of_windows) += 1; aew = PRIVATE(new,axe_editor) = XtVaCreateManagedWidget("panes", axeEditorWidgetClass, new, XtNfile, PRIVATE(new,file), NULL); if (PRIVATE(new,file_title)) { XtAddCallback(aew, XtNchangeCallback, ChangeOfTitle, (XtPointer) new); } } static void Destroy(w) Widget w; { CLASS(number_of_windows) -= 1; if (CLASS(number_of_windows) == 0 && PRIVATE(w,exit_on_close_last_window)) { exit(0); } } static void Resize(w) Widget w; { (*((TopLevelShellWidgetClass) (axeWindowWidgetClass-> core_class.superclass))->core_class.resize) (w); SetWMHints(w); } static XtGeometryResult GeometryManager(w, desired, allowed) Widget w; XtWidgetGeometry *desired, *allowed; { XtGeometryResult result; result = (*((TopLevelShellWidgetClass) (axeWindowWidgetClass-> core_class.superclass))-> composite_class.geometry_manager) (w, desired, allowed); if (result == XtGeometryYes) { SetWMHints(XtParent(w)); } return result; } static void DeleteChild(child) Widget child; { (*((CompositeWidgetClass) (axeWindowWidgetClass-> core_class.superclass))->composite_class.delete_child) (child); XtDestroyWidget(XtParent(child)); } /* ARGSUSED */ static void ChangeOfTitle(widget, client_data, call_data) Widget widget; XtPointer client_data, call_data; { Widget aww = (Widget) client_data; String title = (String) call_data, newTitle, iconName, icon; int len = strlen(PRIVATE(aww,file_title_prefix)); int ilen = strlen(PRIVATE(aww,icon_name_prefix)); if (len == 0) { newTitle = title; } else { len += strlen(title) + 1; newTitle = (String) XtMalloc(len); strcpy(newTitle, PRIVATE(aww,file_title_prefix)); strcat(newTitle, title); } if ( (icon = rindex(title, '/'))) { icon += 1; } else { icon = title; } if (ilen == 0) { iconName = icon; } else { ilen += strlen(icon) + 1; iconName = (String) XtMalloc(ilen); strcpy(iconName, PRIVATE(aww,icon_name_prefix)); strcat(iconName, icon); } XtVaSetValues(aww, XtNtitle, newTitle, XtNiconName, iconName, NULL); if (newTitle != title) { XtFree(newTitle); } if (iconName != icon) { XtFree(iconName); } } static void SetWMHints(shell) Widget shell; { XSizeHints hints; long supp; XFontStruct *font; Position lm, rm, tm, bm; Dimension height, pheight; Widget sink; XRectangle caret; Dimension caretHeight; Atom wm_delete_window; Display *display = XtDisplay(shell); Window window = XtWindow(shell); Widget ed = AxeEditorEdWidget(PRIVATE(shell,axe_editor)); XtVaGetValues(ed, XtNfont, &font, XtNheight, &height, XtNleftMargin, &lm, XtNrightMargin, &rm, XtNtopMargin, &tm, XtNbottomMargin, &bm, XtNtextSink, &sink, NULL); XawTextSinkGetCursorBounds(sink, &caret); caretHeight = (Dimension) caret.height; XtVaGetValues(PRIVATE(shell,axe_editor), XtNheight, &pheight, NULL); if (!XGetWMNormalHints(display, window, &hints, &supp)) { hints.flags = 0; } hints.flags |= PResizeInc | PBaseSize; hints.width_inc = font->max_bounds.width; hints.height_inc = font->max_bounds.ascent + font->max_bounds.descent; hints.base_width = lm + rm; hints.base_height = pheight - (height - tm - bm - CARETHEIGHT); XSetWMNormalHints(display, window, &hints); wm_delete_window = XInternAtom (display, "WM_DELETE_WINDOW", False); (void) XSetWMProtocols(display, window, &wm_delete_window, 1); } /* ARGSUSED */ static void CloseWindow(widget, event, params, num_params) Widget widget; XEvent *event; String *params; Cardinal *num_params; { XtCallActionProc(AxeEditorEdWidget(AxeWindowAxeEditor(widget)), "close-window", event, params, *num_params); } /************************************************************* * * Public functions * *************************************************************/ Widget AxeWindowAxeEditor(aww) Widget aww; { if (!XtIsSubclass(aww, axeWindowWidgetClass)) { return (Widget) 0; } else { return PRIVATE(aww,axe_editor); } } axe-6.1.2.orig/Widgets/AxeWindow.h100644 243 144 4067 5550557121 15466 0ustar joostusers/* * Copyright 1992 The University of Newcastle upon Tyne * * Permission to use, copy, modify and distribute this software and its * documentation for any purpose other than its commercial exploitation * is hereby granted without fee, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of The University of Newcastle upon Tyne not be used in * advertising or publicity pertaining to distribution of the software * without specific, written prior permission. The University of * Newcastle upon Tyne makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * THE UNIVERSITY OF NEWCASTLE UPON TYNE DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF * NEWCASTLE UPON TYNE BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. * * Author: Jim Wight (j.k.wight@newcastle.ac.uk) * Department of Computing Science * University of Newcastle upon Tyne, UK */ #ifndef AxeWindow_h #define AxeWindow_h #include typedef struct _AxeWindowClassRec *AxeWindowWidgetClass; typedef struct _AxeWindowRec *AxeWindowWidget; extern WidgetClass axeWindowWidgetClass; extern Widget AxeWindowAxeEditor(); #define XtNfileTitle "fileTitle" #define XtCFileTitle "FileTitle" #define XtNfileTitlePrefix "fileTitlePrefix" #define XtCFileTitlePrefix "FileTitlePrefix" #define XtNiconNamePrefix "iconNamePrefix" #define XtNexitOnCloseLastWindow "exitOnCloseLastWindow" #define XtCExitOnCloseLastWindow "ExitOnCloseLastWindow" #endif /* AxeWindow_h */ axe-6.1.2.orig/Widgets/AxeWindowP.h100644 243 144 5107 5600335244 15576 0ustar joostusers/* * Copyright 1992, 1994 The University of Newcastle upon Tyne * * Permission to use, copy, modify and distribute this software and its * documentation for any purpose other than its commercial exploitation * is hereby granted without fee, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of The University of Newcastle upon Tyne not be used in * advertising or publicity pertaining to distribution of the software * without specific, written prior permission. The University of * Newcastle upon Tyne makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * THE UNIVERSITY OF NEWCASTLE UPON TYNE DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF * NEWCASTLE UPON TYNE BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. * * Author: Jim Wight (j.k.wight@newcastle.ac.uk) * Department of Computing Science * University of Newcastle upon Tyne, UK */ #ifndef AxeWindowP_h #define AxeWindowP_h #include #include "AxeWindow.h" typedef struct { XtPointer extension; int number_of_windows; } AxeWindowClassPart; typedef struct _AxeWindowClassRec { CoreClassPart core_class; CompositeClassPart composite_class; ShellClassPart shell_class; WMShellClassPart wm_shell_class; VendorShellClassPart vendor_shell_class; TopLevelShellClassPart top_level_shell_class; AxeWindowClassPart axeWindow_class; } AxeWindowClassRec; extern AxeWindowClassRec axeWindowClassRec; typedef struct { /* Resources */ String file; Boolean file_title; String file_title_prefix; String icon_name_prefix; Boolean exit_on_close_last_window; /* Private date */ Widget axe_editor; } AxeWindowPart; typedef struct _AxeWindowRec { CorePart core; CompositePart composite; ShellPart shell; WMShellPart wm; VendorShellPart vendor; TopLevelShellPart topLevel; AxeWindowPart axeWindow; } AxeWindowRec; #endif /* AxeWindowP_h */ axe-6.1.2.orig/Widgets/AxeiiSink.c100644 243 144 17764 5550557113 15471 0ustar joostusers/* * Copyright 1993 The University of Newcastle upon Tyne * * Permission to use, copy, modify and distribute this software and its * documentation for any purpose other than its commercial exploitation * is hereby granted without fee, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of The University of Newcastle upon Tyne not be used in * advertising or publicity pertaining to distribution of the software * without specific, written prior permission. The University of * Newcastle upon Tyne makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * THE UNIVERSITY OF NEWCASTLE UPON TYNE DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF * NEWCASTLE UPON TYNE BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. * * Author: Jim Wight (j.k.wight@newcastle.ac.uk) * Department of Computing Science * University of Newcastle upon Tyne, UK */ /************************************************************************ * * * WARNING: This object assumes knowledge of its superclass' internals * * * ************************************************************************/ #include #include #include #include "blockCaret.xbm" #define Offset(field) XtOffsetOf(AxeiiSinkRec, axeii_sink.field) static XtResource resources[] = { {XtNblockCursor, XtCBlockCursor, XtRBoolean, sizeof(Boolean), Offset(block_cursor), XtRImmediate, (XtPointer) False}, {XtNcursorBitmap, XtCBitmap, XtRString, sizeof(String), Offset(cursor_bitmap), XtRString, (XtPointer) NULL}, }; #undef Offset #define PRIVATE(w,field) (((AxeiiSinkObject) w)->axeii_sink.field) static void Initialize(); static void InsertCursor(), GetCursorBounds(); #define SuperClass (&asciiSinkClassRec) AxeiiSinkClassRec axeiiSinkClassRec = { { /* core_class fields */ /* superclass */ (WidgetClass) SuperClass, /* class_name */ "AxeiiSink", /* widget_size */ sizeof(AxeiiSinkRec), /* class_initialize */ NULL, /* class_part_initialize */ NULL, /* class_inited */ FALSE, /* initialize */ Initialize, /* initialize_hook */ NULL, /* obj1 */ NULL, /* obj2 */ NULL, /* obj3 */ 0, /* resources */ resources, /* num_resources */ XtNumber(resources), /* xrm_class */ NULLQUARK, /* obj4 */ FALSE, /* obj5 */ FALSE, /* obj6 */ FALSE, /* obj7 */ FALSE, /* destroy */ NULL, /* obj8 */ NULL, /* obj9 */ NULL, /* set_values */ NULL, /* set_values_hook */ NULL, /* obj10 */ NULL, /* get_values_hook */ NULL, /* obj11 */ NULL, /* version */ XtVersion, /* callback_private */ NULL, /* obj12 */ NULL, /* obj13 */ NULL, /* obj14 */ NULL, /* extension */ NULL }, /* text_sink_class fields */ { /* DisplayText */ XtInheritDisplayText, /* InsertCursor */ InsertCursor, /* ClearToBackground */ XtInheritClearToBackground, /* FindPosition */ XtInheritFindPosition, /* FindDistance */ XtInheritFindDistance, /* Resolve */ XtInheritResolve, /* MaxLines */ XtInheritMaxLines, /* MaxHeight */ XtInheritMaxHeight, /* SetTabs */ XtInheritSetTabs, /* GetCursorBounds */ GetCursorBounds }, /* ascii_sink_class fields */ { /* unused */ 0 }, /* axeii_sink_class fields */ { /* unused */ 0 } }; WidgetClass axeiiSinkObjectClass = (WidgetClass)&axeiiSinkClassRec; /* ARGSUSED */ static void Initialize(request, new) Widget request, new; { AxeiiSinkObject sink = (AxeiiSinkObject) new; Display *display = XtDisplayOfObject(new); Pixmap pix = None; Window root; int x, y; unsigned int borderWidth, depth; if (PRIVATE(new,cursor_bitmap)) { int junk; pix = XmuLocateBitmapFile(XDefaultScreenOfDisplay(display), PRIVATE(new,cursor_bitmap), (char *) 0, 0, &junk, &junk, &junk, &junk); } else if (PRIVATE(new,block_cursor)) { pix = XCreateBitmapFromData (display, XDefaultRootWindow(display), (char *) blockCaret_bits, blockCaret_width, blockCaret_height); } if (pix != None) { XFreePixmap(display, sink->ascii_sink.insertCursorOn); sink->ascii_sink.insertCursorOn = pix; } XGetGeometry(display, sink->ascii_sink.insertCursorOn, &root, &x, &y, &PRIVATE(new,cursor_width), &PRIVATE(new,cursor_height), &borderWidth, &depth); } /* $XConsortium: AsciiSink.c,v 1.57 91/07/21 20:35:00 converse Exp $ */ /*********************************************************** Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts, and the Massachusetts Institute of Technology, Cambridge, Massachusetts. All Rights Reserved Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation, and that the names of Digital or MIT not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ******************************************************************/ /* * The following are little-modified copies of the equivalent AsciiSink * functions, hence the inclusion of the above copyright notice. */ static void GetCursorBounds(w, rect) Widget w; XRectangle * rect; { AsciiSinkObject sink = (AsciiSinkObject) w; rect->width = (unsigned short) PRIVATE(w,cursor_width); rect->height = (unsigned short) PRIVATE(w,cursor_height); rect->x = sink->ascii_sink.cursor_x - (short) (rect->width / 2); rect->y = sink->ascii_sink.cursor_y - (short) rect->height; } /* * Although this is unchanged it can't be inherited because it calls * GetCursorBounds, which would be AsciiSink's GetCursorBounds. The * GetCursorBounds which now gets called is our own. Maybe AsciiSink's * InsertCursor should call XawTextGetCursorBounds. */ static void InsertCursor (w, x, y, state) Widget w; Position x, y; XawTextInsertState state; { AsciiSinkObject sink = (AsciiSinkObject) w; Widget text_widget = XtParent(w); XRectangle rect; sink->ascii_sink.cursor_x = x; sink->ascii_sink.cursor_y = y; GetCursorBounds(w, &rect); if (state != sink->ascii_sink.laststate && XtIsRealized(text_widget)) XCopyPlane(XtDisplay(text_widget), sink->ascii_sink.insertCursorOn, XtWindow(text_widget), sink->ascii_sink.xorgc, 0, 0, (unsigned int) rect.width, (unsigned int) rect.height, (int) rect.x, (int) rect.y, 1); sink->ascii_sink.laststate = state; } axe-6.1.2.orig/Widgets/AxeiiSink.h100644 243 144 3413 5550557121 15437 0ustar joostusers/* * Copyright 1993 The University of Newcastle upon Tyne * * Permission to use, copy, modify and distribute this software and its * documentation for any purpose other than its commercial exploitation * is hereby granted without fee, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of The University of Newcastle upon Tyne not be used in * advertising or publicity pertaining to distribution of the software * without specific, written prior permission. The University of * Newcastle upon Tyne makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * THE UNIVERSITY OF NEWCASTLE UPON TYNE DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF * NEWCASTLE UPON TYNE BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. * * Author: Jim Wight (j.k.wight@newcastle.ac.uk) * Department of Computing Science * University of Newcastle upon Tyne, UK */ #ifndef _AxeiiSink_h #define _AxeiiSink_h extern WidgetClass axeiiSinkObjectClass; typedef struct _AxeiiSinkClassRec *AxeiiSinkObjectClass; typedef struct _AxeiiSinkRec *AxeiiSinkObject; #define XtNblockCursor "blockCursor" #define XtCBlockCursor "BlockCursor" #define XtNcursorBitmap "cursorBitmap" #endif /* _AxeiiSrc_h */ axe-6.1.2.orig/Widgets/AxeiiSinkP.h100644 243 144 4467 5550557121 15571 0ustar joostusers/* * Copyright 1993 The University of Newcastle upon Tyne * * Permission to use, copy, modify and distribute this software and its * documentation for any purpose other than its commercial exploitation * is hereby granted without fee, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of The University of Newcastle upon Tyne not be used in * advertising or publicity pertaining to distribution of the software * without specific, written prior permission. The University of * Newcastle upon Tyne makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * THE UNIVERSITY OF NEWCASTLE UPON TYNE DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF * NEWCASTLE UPON TYNE BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. * * Author: Jim Wight (j.k.wight@newcastle.ac.uk) * Department of Computing Science * University of Newcastle upon Tyne, UK */ #ifndef _AxeiiSinkP_h #define _AxeiiSinkP_h #include #include #include typedef struct _AxeiiSinkClassPart { int foo; } AxeiiSinkClassPart; typedef struct _AxeiiSinkClassRec { ObjectClassPart object_class; TextSinkClassPart text_sink_class; AsciiSinkClassPart ascii_sink_class; AxeiiSinkClassPart axeii_sink_class; } AxeiiSinkClassRec; extern AxeiiSinkClassRec axeiiSinkClassRec; typedef struct { /* resources */ Boolean block_cursor; String cursor_bitmap; /* private state */ unsigned int cursor_width; unsigned int cursor_height; } AxeiiSinkPart; typedef struct _AxeiiSinkRec { ObjectPart object; TextSinkPart text_sink; AsciiSinkPart ascii_sink; AxeiiSinkPart axeii_sink; } AxeiiSinkRec; #endif /* _AxeiiSinkP_h */ axe-6.1.2.orig/Widgets/AxeiiText.c100644 243 144 213315 5550557113 15517 0ustar joostusers/* * Copyright 1992 The University of Newcastle upon Tyne * * Permission to use, copy, modify and distribute this software and its * documentation for any purpose other than its commercial exploitation * is hereby granted without fee, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of The University of Newcastle upon Tyne not be used in * advertising or publicity pertaining to distribution of the software * without specific, written prior permission. The University of * Newcastle upon Tyne makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * THE UNIVERSITY OF NEWCASTLE UPON TYNE DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF * NEWCASTLE UPON TYNE BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. * * Author: Jim Wight (j.k.wight@newcastle.ac.uk) * Department of Computing Science * University of Newcastle upon Tyne, UK */ #include #include #include #include #include #include #include #include #include "AxeiiSink.h" #include "AxeiiTextP.h" #include "AxeiiUndo.h" #include "regexp.h" /* * Mimics use in TextPop.c w.r.t. search popup's direction toggles' radio data */ #define R_OFFSET 1 #define CLOSURE 01010 #define CARETHEIGHT (XT_REVISION < 5 ? caretHeight : 0) #define Offset(field) XtOffsetOf(AxeiiTextRec, axeii.field) static XtResource resources[] = { {XtNrows, XtCRows, XtRInt, sizeof(int), Offset(rows), XtRImmediate, (XtPointer) 24}, {XtNcolumns, XtCColumns, XtRInt, sizeof(int), Offset(columns), XtRImmediate, (XtPointer) 80}, /* * These have yet to be catered for in SetValues */ {XtNblockCaret, XtCBlockCaret, XtRBoolean, sizeof(Boolean), Offset(block_caret), XtRImmediate, (XtPointer) False}, {XtNcaretBitmap, XtCBitmap, XtRString, sizeof(String), Offset(caret_bitmap), XtRString, (XtPointer) NULL}, {XtNtabEvery, XtCTabEvery, XtRInt, sizeof(int), Offset(tab_every), XtRImmediate, (XtPointer) NULL}, {XtNblinkPeriod, XtCBlinkPeriod, XtRLong, sizeof(long), Offset(blink_period), XtRString, (XtPointer) "500"}, {XtNexpandTabs, XtCExpandTabs, XtRBoolean, sizeof(Boolean), Offset(expand_tabs), XtRImmediate, (XtPointer) False}, {XtNwatchingChanges, XtCWatchingChanges, XtRBoolean, sizeof(Boolean), Offset(watching_changes), XtRImmediate, (XtPointer) False}, {XtNmodifiedCallback, XtCCallback, XtRCallback, sizeof(XtPointer), Offset(modified_callbacks), XtRCallback, (XtPointer) NULL}, {XtNgotoLineCallback, XtCCallback, XtRCallback, sizeof(XtPointer), Offset(goto_line_callbacks), XtRCallback, (XtPointer) NULL}, {XtNincludeFileCallback, XtCCallback, XtRCallback, sizeof(XtPointer), Offset(include_file_callbacks), XtRCallback, (XtPointer) NULL}, {XtNinsertControlCallback, XtCCallback, XtRCallback, sizeof(XtPointer), Offset(insert_control_callbacks), XtRCallback, (XtPointer) NULL}, {XtNwhereCallback, XtCCallback, XtRCallback, sizeof(XtPointer), Offset(where_callbacks), XtRCallback, (XtPointer) NULL}, {XtNsizeCallback, XtCCallback, XtRCallback, sizeof(XtPointer), Offset(size_callbacks), XtRCallback, (XtPointer) NULL}, {XtNpreferencesCallback, XtCCallback, XtRCallback, sizeof(XtPointer), Offset(preferences_callbacks), XtRCallback, (XtPointer) NULL}, {XtNclearBufferCallback, XtCCallback, XtRCallback, sizeof(XtPointer), Offset(clear_buffer_callbacks), XtRCallback, (XtPointer) NULL}, {XtNsaveFileCallback, XtCCallback, XtRCallback, sizeof(XtPointer), Offset(save_file_callbacks), XtRCallback, (XtPointer) NULL}, {XtNsaveAsCallback, XtCCallback, XtRCallback, sizeof(XtPointer), Offset(save_as_callbacks), XtRCallback, (XtPointer) NULL}, {XtNreloadFileCallback, XtCCallback, XtRCallback, sizeof(XtPointer), Offset(reload_file_callbacks), XtRCallback, (XtPointer) NULL}, {XtNloadFileCallback, XtCCallback, XtRCallback, sizeof(XtPointer), Offset(load_file_callbacks), XtRCallback, (XtPointer) NULL}, {XtNnoUndoCallback, XtCCallback, XtRCallback, sizeof(XtPointer), Offset(no_undo_callbacks), XtRCallback, (XtPointer) NULL}, {XtNundo, XtCUndo, XtRBoolean, sizeof(Boolean), Offset(undo), XtRImmediate, (XtPointer) True}, {XtNundoLevel, XtCUndoLevel, XtRInt, sizeof(int), Offset(undo_level), XtRImmediate, (XtPointer) 1}, {XtNdeleteOnInsert, XtCDeleteOnInsert, XtRBoolean, sizeof(Boolean), Offset(delete_on_insert), XtRImmediate, (XtPointer) False}, }; #undef Offset #define CLASS(field) axeiiTextClassRec.axeii_class.field #define PRIVATE(w,field) (((AxeiiTextWidget) w)->axeii.field) static void InsertCharAction(), SearchAction(); static void GotoLine(), SearchCaret(), FwdSearchSelection(), BwdSearchSelection(); static void ReSearch(), DoReSearch(), DoReReplace(), PopdownSearch(); static void Search(), ReplaceOne(), ReplaceAll(); static void IncludeFile(), IncludeSelection(), Paste(), InsertControl(); static void DeleteWord(), DeleteLine(); static void Where(), Size(), CentreLine(), SetPreferences(); static void ClearBuffer(); static void SaveFile(), SaveAs(), LoadFile(), ReloadFile(); static void MatchParens(), FindMatch(); static void ForwardLine(), BackwardLine(), DelSelOrPrevChar(), InsertOrExpandTab(); static void SetMark(), HighlightRegion(), KillRegion(), CopyRegion(), YankRegion(); static void KeyMap(); static void TextSetTabs(); static void FwdBwdLineHook(); static char matchingPairs[] = { '(', ')', '{', '}', '[', ']', '\0', '\0'}; static char searchTranslations[] = "~ShiftReturn: DoReSearch(Popdown) \n\ ShiftReturn: DoReSearch() SetField(Replace) \n\ Ctrlq,Tab: insert-char() \n\ Ctrlc: PopdownSearchAction() \n\ : select-start() SetField(Search) \n\ Tab: DoReSearch() SetField(Replace)"; static char replaceTranslations[] = "~ShiftReturn: DoReReplace(Popdown) \n\ ShiftReturn: SetField(Search) \n\ Ctrlq,Tab: insert-char() \n\ Ctrlc: PopdownSearchAction() \n\ : select-start() DoReSearch() SetField(Replace)\n\ Tab: SetField(Search)"; static char translations[] = "Tab:insert-or-expand-tab()"; static XtActionsRec actions[] = { #if defined(XtSpecificationRelease) && XtSpecificationRelease > 4 "insert-char", InsertCharAction, /* Text Widget */ "search", SearchAction, /* Overrides */ #endif "goto-line", GotoLine, "search-line", GotoLine, /* For backwards compatability */ "search-caret", SearchCaret, "forward-search-selection", FwdSearchSelection, "backward-search-selection", BwdSearchSelection, "re-search", ReSearch, "DoReSearch", DoReSearch, "DoReReplace", DoReReplace, "include-file", IncludeFile, "include-selection", IncludeSelection, "paste", Paste, "insert-control", InsertControl, "delete-word", DeleteWord, "delete-line", DeleteLine, "where", Where, "size", Size, "centre-line", CentreLine, "set-preferences", SetPreferences, "clear-buffer", ClearBuffer, "save-file", SaveFile, "save-as", SaveAs, "revert-file", ReloadFile, /* For backwards compatability */ "load-file", LoadFile, "reload-file", ReloadFile, /* In place of revert-file */ "match-parens", MatchParens, "find-match", FindMatch, "forward-line", ForwardLine, "backward-line", BackwardLine, "delete-selection-or-previous-character", DelSelOrPrevChar, "insert-or-expand-tab", InsertOrExpandTab, "set-mark", SetMark, "highlight-region", HighlightRegion, "kill-region", KillRegion, "copy-region", CopyRegion, "yank-region", YankRegion, "keymap", KeyMap, "undo", UndoAction, }; static void ClassInitialize(), Initialize(), Destroy(), Resize(); static Boolean SetValues(); AxeiiTextClassRec axeiiTextClassRec = { /* Core class part */ { /* superclass */ (WidgetClass) &asciiTextClassRec, /* class_name */ "AxeiiText", /* widget_size */ sizeof(AxeiiTextRec), /* class_initialize */ ClassInitialize, /* class_part_initialize */ NULL, /* class_inited */ FALSE, /* initialize */ Initialize, /* initialize_hook */ NULL, /* realize */ XtInheritRealize, /* actions */ actions, /* num_actions */ XtNumber(actions), /* resources */ resources, /* num_resources */ XtNumber(resources), /* xrm_class */ NULLQUARK, /* compress_motion */ TRUE, #if defined(XtSpecificationRelease) && XtSpecificationRelease > 4 /* compress_exposure */ XtExposeGraphicsExpose | XtExposeNoExpose, #else /* compress_exposure */ XtExposeGraphicsExpose, #endif /* compress_enterleave */ TRUE, /* visible_interest */ FALSE, /* destroy */ Destroy, /* resize */ Resize, /* expose */ XtInheritExpose, /* set_values */ SetValues, /* set_values_hook */ NULL, /* set_values_almost */ XtInheritSetValuesAlmost, /* get_values_hook */ NULL, /* accept_focus */ XtInheritAcceptFocus, /* version */ XtVersion, /* callback offsets */ NULL, /* tm_table */ XtInheritTranslations, /* query_geometry */ XtInheritQueryGeometry, /* display_accelerator */ XtInheritDisplayAccelerator, /* extension */ NULL, }, { /* Simple fields */ /* change_sensitive */ XtInheritChangeSensitive }, { /* text fields */ /* empty */ 0 }, { /* ascii fields */ /* empty */ 0 }, { /* axeii fields */ /* extension */ NULL } }; WidgetClass axeiiTextWidgetClass = (WidgetClass) &axeiiTextClassRec; static void ClassInitialize() { XtActionList actionList; Cardinal action, numActions; XtAddConverter(XtRString, XtRLong, XmuCvtStringToLong, NULL, 0); CLASS(translations) = XtParseTranslationTable(translations); CLASS(search_translations) = XtParseTranslationTable(searchTranslations); CLASS(replace_translations) = XtParseTranslationTable(replaceTranslations); CLASS(preInsertUndo) = InsertUndo; CLASS(preReplaceUndo) = ReplaceUndo; CLASS(postLoadUndo) = ResetUndo; #if defined(XtSpecificationRelease) && XtSpecificationRelease > 4 XtGetActionList(textWidgetClass, &actionList, &numActions); for (action = 0; action < numActions; ++action) { if (strcmp(actionList[action].string, "insert-char") == 0) { CLASS(superInsertChar) = actionList[action].proc; } else if (strcmp(actionList[action].string, "search") == 0) { CLASS(superSearch) = actionList[action].proc; } } XtFree((char *) actionList); #endif } /* ARGSUSED */ static void Initialize(req, new, args, num_args) Widget req, new; ArgList args; Cardinal *num_args; { AxeiiTextWidget atw = (AxeiiTextWidget) new; Dimension width, height; atw->axeii.action_hook = (XtActionHookId) 0; atw->axeii.blink_timer = (XtIntervalId) 0; atw->axeii.watching_changes = False; atw->axeii.mark = (XawTextPosition) 0; AxeiiTextRowsColumnsToWidthHeight(atw->axeii.rows, atw->axeii.columns, atw, &width, &height); atw->core.width = width; atw->core.height = height; if (atw->axeii.caret_bitmap) { XtVaSetValues(new, XtNtextSink, XtVaCreateWidget("axeiisink", axeiiSinkObjectClass, new, XtNcursorBitmap, atw->axeii.caret_bitmap, NULL), NULL); } else if (atw->axeii.block_caret) { XtVaSetValues(new, XtNtextSink, XtVaCreateWidget("axeiisink", axeiiSinkObjectClass, new, XtNblockCursor, True, NULL), NULL); } if (atw->axeii.tab_every) { TextSetTabs(atw, atw->axeii.tab_every); } else { atw->axeii.tab_every = 8; } XtOverrideTranslations(new, CLASS(translations)); atw->axeii.translations = atw->core.tm.translations; atw->axeii.search = (Widget) 0; atw->axeii.label1 = (Widget) 0; atw->axeii.compexp = (regexp *) 0; atw->axeii.matchedText = (String) 0; atw->axeii.matchBegin = 1; /* Different. So that AxeiiTextReSearch */ atw->axeii.matchEnd = 2; /* search for "^" works at beginning of */ /* file */ if (atw->axeii.undo) { InitialiseUndo(atw); atw->axeii.undo_hook = XtAppAddActionHook(XtWidgetToApplicationContext(new), UndoHook, (XtPointer) new); atw->axeii.lastAction = 0; atw->axeii.insertFileCallbacks = 0; atw->axeii.searchOneCallbacks = 0; atw->axeii.searchAllCallbacks = 0; } /* Cause scrollbar lengths to be recomputed for new core width & height */ (*((AsciiTextWidgetClass) (axeiiTextWidgetClass->core_class.superclass))->core_class.resize)(new); } static void Destroy(w) Widget w; { AxeiiTextWidget atw = (AxeiiTextWidget) w; if (atw->axeii.action_hook) { XtRemoveActionHook(atw->axeii.action_hook); } if (atw->axeii.blink_timer) { XtRemoveTimeOut(atw->axeii.blink_timer); } if (atw->axeii.label1) { XtFree((char*) atw->axeii.searchCallbacks); XtFree((char*) atw->axeii.replaceOneCallbacks); XtFree((char*) atw->axeii.replaceAllCallbacks); XtFree((char*) atw->axeii.compexp); XtDestroyWidget(atw->axeii.searchTranslations); XtDestroyWidget(atw->axeii.replaceTranslations); XtFree(atw->axeii.matchedText); } if (atw->axeii.undo) { XtRemoveActionHook(atw->axeii.undo_hook); FreeUndo(atw, True); XtFree((char *) atw->axeii.insertFileCallbacks); XtFree((char *) atw->axeii.searchOneCallbacks); XtFree((char *) atw->axeii.searchAllCallbacks); } } static void Resize(w) Widget w; { /* * Too bad if not resizing in character increments */ AxeiiTextWidget atw = (AxeiiTextWidget) w; int rows, columns; (*((AsciiTextWidgetClass) (axeiiTextWidgetClass->core_class.superclass))->core_class.resize) (w); AxeiiTextWidthHeightToRowsColumns(w, &rows, &columns); atw->axeii.rows = rows; atw->axeii.columns = columns; } /* ARGSUSED */ static Boolean SetValues(old, request, new, args, num_args) Widget old, request, new; ArgList args; Cardinal *num_args; { AxeiiTextWidget oldatw = (AxeiiTextWidget) old; AxeiiTextWidget newatw = (AxeiiTextWidget) new; Dimension width, height; int i, rows, columns; Boolean redisplay = False; for (i = 0; i < *num_args; ++i) { if (strcmp(args[i].name,"font") == 0) { redisplay = True; } } #define NE(field) (oldatw->field != newatw->field) if (NE(axeii.rows) || NE(axeii.columns) || redisplay) { AxeiiTextRowsColumnsToWidthHeight(newatw->axeii.rows, newatw->axeii.columns, newatw, &width, &height); newatw->core.width = width; newatw->core.height = height; redisplay = True; } else if (NE(core.width) || NE(core.height)) { AxeiiTextWidthHeightToRowsColumns(newatw, &rows, &columns); newatw->axeii.rows = rows; newatw->axeii.columns = columns; redisplay = True; } if (NE(axeii.tab_every)) { TextSetTabs(newatw, newatw->axeii.tab_every); redisplay = True; } if (NE(axeii.watching_changes)) { if (PRIVATE(new,watching_changes)) { AxeiiTextWatchForChanges(new); } else { XtRemoveAllCallbacks(XawTextGetSource(new), XtNcallback); } } if (NE(text.scroll_vert)) { AxeiiTextRowsColumnsToWidthHeight(newatw->axeii.rows, newatw->axeii.columns, newatw, &width, &height); newatw->core.width = width; newatw->core.height = height; redisplay = True; } #undef NE return redisplay; } /************************************************************* * * utilities * *************************************************************/ static void GetLineInfo(widget, bol, insert, eol) Widget widget; XawTextPosition *bol, *insert, *eol; { Widget textSrc; XawTextPosition target; textSrc = XawTextGetSource(widget); target = XawTextGetInsertionPoint(widget); *bol = XawTextSourceScan(textSrc, target, XawstEOL, XawsdLeft, 1, False); *insert = target; *eol = XawTextSourceScan(textSrc, target, XawstEOL, XawsdRight, 1, True); } static void TextSetTabs(widget, tabevery) Widget widget; int tabevery; { int columns, rows; Widget sink; int tabCount, *tabStops, tabPos; AxeiiTextWidthHeightToRowsColumns(widget, &rows, &columns); XtVaGetValues(widget, XtNtextSink, &sink, NULL); tabCount = columns / tabevery; tabStops = (int *) XtMalloc(tabCount * sizeof(int)); for (tabPos = 1; tabPos <= tabCount; ++tabPos) { tabStops[tabPos - 1] = tabPos * tabevery; } XawTextSinkSetTabs(sink, tabCount, tabStops); XtFree((char *) tabStops); } /*ARGSUSED*/ static void blinkOff(client_data, id) XtPointer client_data; XtIntervalId *id; { Widget widget = (Widget) client_data; XawTextUnsetSelection(widget); PRIVATE(widget,blink_timer) = 0; } /*ARGSUSED*/ static void AsciiSourceChanged(w, client_data, call_data) Widget w; XtPointer client_data, call_data; { Widget atw = XtParent(w); XtRemoveCallback(w, XtNcallback, AsciiSourceChanged, (XtPointer) CLOSURE); PRIVATE(atw,watching_changes) = False; XtCallCallbackList(atw, PRIVATE(atw,modified_callbacks), (XtPointer) 0); } /************************************************************* * * search * *************************************************************/ /*ARGSUSED*/ static void SearchAction(widget, event, params, num_params) Widget widget; XEvent *event; String *params; Cardinal *num_params; { #if defined(XtSpecificationRelease) && XtSpecificationRelease > 4 /* * Regular expression searching and undo modify the behaviour * of the search popup. Restoration to the original state is * expected to be carried out on popping down, so ensure that * gets done before coming up in the new state. */ if (PRIVATE(widget,search)) { XtPopdown(PRIVATE(widget,search)); } (*CLASS(superSearch))(widget, event, params, num_params); if (!PRIVATE(widget,search)) { PRIVATE(widget,search) = XtNameToWidget(widget, ".search"); } #endif } /************************************************************* * * re-search * *************************************************************/ /*ARGSUSED*/ static void NewRegexp(widget, client_data, call_data) Widget widget; XtPointer client_data, call_data; { Widget text = (Widget) client_data; XtFree((char *) PRIVATE(text,compexp)); PRIVATE(text,compexp) = (regexp *) 0; XtRemoveAllCallbacks(widget, XtNcallback); } /*ARGSUSED*/ static void PopdownSearch(widget, client_data, call_data) Widget widget; XtPointer client_data, call_data; { AxeiiTextWidget axeii = (AxeiiTextWidget) client_data; XtTranslations translations; XtVaSetValues(PRIVATE(axeii,search), "title", "search", NULL); XtRemoveCallback(widget, XtNpopdownCallback, PopdownSearch, client_data); XtVaGetValues(PRIVATE(axeii,searchTranslations), XtNtranslations, &translations, NULL); XtVaSetValues(PRIVATE(axeii,searchText), XtNtranslations, translations, NULL); XtVaGetValues(PRIVATE(axeii,replaceTranslations), XtNtranslations, &translations, NULL); XtVaSetValues(PRIVATE(axeii,replaceText), XtNtranslations, translations, NULL); XtRemoveAllCallbacks(PRIVATE(axeii,searchOne), XtNcallback); XtAddCallbacks(PRIVATE(axeii,searchOne), XtNcallback, PRIVATE(axeii,searchCallbacks)); XtRemoveAllCallbacks(PRIVATE(axeii,replaceOne), XtNcallback); XtAddCallbacks(PRIVATE(axeii,replaceOne), XtNcallback, PRIVATE(axeii,replaceOneCallbacks)); XtRemoveAllCallbacks(PRIVATE(axeii,replaceAll), XtNcallback); XtAddCallbacks(PRIVATE(axeii,replaceAll), XtNcallback, PRIVATE(axeii,replaceAllCallbacks)); NewRegexp(XawTextGetSource(PRIVATE(axeii,searchText)), (XtPointer) axeii); } /*ARGSUSED*/ static void ReSearch(widget, event, params, num_params) Widget widget; XEvent *event; String *params; Cardinal *num_params; { AxeiiTextWidget atw = (AxeiiTextWidget) widget; XtTranslations translations; XtCallbackList list; char buf[BUFSIZ]; if ( (*num_params < 1) || (*num_params > 2) ) { sprintf(buf, "AxeiiText Widget - re-search: %s\n%s", "This action must have only", "one or two parameters"); XtAppWarning(XtWidgetToApplicationContext(widget), buf); return; } XtCallActionProc(widget, "search", event, params, *num_params); if (!PRIVATE(widget,label1)) { PRIVATE(widget,searchTranslations) = XtVaCreateWidget("tmpSearch", coreWidgetClass, widget, NULL); PRIVATE(widget,replaceTranslations) = XtVaCreateWidget("tmpReplace", coreWidgetClass, widget, NULL); PRIVATE(widget,label1) = XtNameToWidget(PRIVATE(widget,search), "*label1"); PRIVATE(widget,label2) = XtNameToWidget(PRIVATE(widget,search), "*label2"); PRIVATE(widget,forwards) = XtNameToWidget(PRIVATE(widget,search), "*forwards"); PRIVATE(widget,searchText) = XtNameToWidget(PRIVATE(widget,search), "*searchText"); PRIVATE(widget,replaceText) = XtNameToWidget(PRIVATE(widget,search), "*replaceText"); PRIVATE(widget,searchOne) = XtNameToWidget(PRIVATE(widget,search), "*search"); PRIVATE(widget,replaceOne) = XtNameToWidget(PRIVATE(widget,search), "*replaceOne"); PRIVATE(widget,replaceAll) = XtNameToWidget(PRIVATE(widget,search), "*replaceAll"); XtVaGetValues(PRIVATE(widget,searchText), XtNtranslations, &translations, NULL); XtVaSetValues(PRIVATE(widget,searchTranslations), XtNtranslations, translations, NULL); XtVaGetValues(PRIVATE(widget,replaceText), XtNtranslations, &translations, NULL); XtVaSetValues(PRIVATE(widget,replaceTranslations), XtNtranslations, translations, NULL); XtVaGetValues(PRIVATE(widget,searchOne), XtNcallback, &list, NULL); CopyCallbackList(list, &PRIVATE(widget,searchCallbacks)); XtVaGetValues(PRIVATE(widget,replaceOne), XtNcallback, &list, NULL); CopyCallbackList(list, &PRIVATE(widget,replaceOneCallbacks)); XtVaGetValues(PRIVATE(widget,replaceAll), XtNcallback, &list, NULL); CopyCallbackList(list, &PRIVATE(widget,replaceAllCallbacks)); } XtVaSetValues(PRIVATE(widget,search), "title", "RE search", NULL); XtAddCallback(PRIVATE(widget,search), XtNpopdownCallback, PopdownSearch, (XtPointer) widget); XtOverrideTranslations(PRIVATE(widget,searchText), CLASS(search_translations)); XtAddCallback(XawTextGetSource(PRIVATE(widget,searchText)), XtNcallback, NewRegexp, (XtPointer) widget); XtOverrideTranslations(PRIVATE(widget,replaceText), CLASS(replace_translations)); XtRemoveAllCallbacks(PRIVATE(atw,searchOne), XtNcallback); XtAddCallback(PRIVATE(widget,searchOne), XtNcallback, Search, (XtPointer) widget); XtRemoveAllCallbacks(PRIVATE(atw,replaceOne), XtNcallback); XtAddCallback(PRIVATE(widget,replaceOne), XtNcallback, ReplaceOne, (XtPointer) widget); XtRemoveAllCallbacks(PRIVATE(atw,replaceAll), XtNcallback); XtAddCallback(PRIVATE(widget,replaceAll), XtNcallback, ReplaceAll, (XtPointer) widget); } static void SetSearchLabels(widget, message1, message2, bell) Widget widget; String message1, message2; Boolean bell; { XtVaSetValues(PRIVATE(widget,label1), XtNlabel, message1, NULL); XtVaSetValues(PRIVATE(widget,label2), XtNlabel, message2, NULL); if (bell) { XBell(XtDisplay(widget), 0); } } static Boolean PerformSearch(widget) Widget widget; { String regexpr; Boolean forward; XtVaGetValues(PRIVATE(widget,searchText), XtNstring, ®expr, NULL); if (!PRIVATE(widget,compexp)) { if (!(PRIVATE(widget,compexp) = regcomp(regexpr))) { return False; } XtAddCallback(XawTextGetSource(PRIVATE(widget,searchText)), XtNcallback, NewRegexp, (XtPointer) widget); } /* * The next line depends on implementation in TextPop.c. */ forward = (((XawTextScanDirection) ((int) XawToggleGetCurrent(PRIVATE(widget,forwards)) - R_OFFSET)) == XawsdRight); return AxeiiTextReSearch(widget, forward, regexpr, PRIVATE(widget,compexp), &PRIVATE(widget,matchedText), &PRIVATE(widget,matchBegin), &PRIVATE(widget,matchEnd)); } /*ARGSUSED*/ static void DoReSearch(widget, event, params, num_params) Widget widget; XEvent *event; String *params; Cardinal *num_params; { Widget axeii; Boolean popdown = False, found; for (axeii = XtParent(widget); !XtIsSubclass(axeii, axeiiTextWidgetClass); axeii = XtParent(axeii)) {} if ((*num_params == 1) && ((params[0][0] == 'p') || (params[0][0] == 'P'))) { popdown = True; } SetSearchLabels(axeii, "", "", False); found = PerformSearch(axeii); if (RegError) { SetSearchLabels(axeii, "Regexp error:", RegError, True); RegError = 0; } else if (found && popdown) { XtCallActionProc(widget, "PopdownSearchAction", event, params, *num_params); } else if (!found) { SetSearchLabels(axeii, "Could not find search string.", "", True); } } /*ARGSUSED*/ static void Search(widget, client_data, call_data) Widget widget; XtPointer client_data, call_data; { AxeiiTextWidget axeii = (AxeiiTextWidget) client_data; Boolean found; SetSearchLabels(axeii, "", "", False); found = PerformSearch(axeii); if (RegError) { SetSearchLabels(axeii, "Regexp error:", RegError, True); RegError = 0; } else if (!found) { SetSearchLabels(axeii, "Could not find search string.", "", True); } } static Boolean PerformReplace(widget, once) Widget widget; Boolean once; { XawTextPosition begin, end; XawTextBlock block; String replacement, regexpr; Boolean success = True; UndoRecord *record; if (!PRIVATE(widget,matchedText)) { return False; } for (;;) { XawTextGetSelectionPos(widget, &begin, &end); if ((begin != PRIVATE(widget,matchBegin) || end != PRIVATE(widget,matchEnd)) && begin != end) { SetSearchLabels(widget, "Selection has been modified; aborting.", "", True); return False; } XtVaGetValues(PRIVATE(widget,replaceText), XtNstring, &replacement, NULL); block.firstPos = 0; block.length = strlen(replacement); block.ptr = replacement; block.format = FMT8BIT; if (PRIVATE(widget,undo)) { record = LinkNewUndoRecord(widget); record->begin = PRIVATE(widget,matchBegin); record->end = PRIVATE(widget,matchEnd); record->undoType = REPLACE; record->data = AxeiiTextRead(widget, PRIVATE(widget,matchBegin), PRIVATE(widget,matchEnd)); } if (XawTextReplace(widget, PRIVATE(widget,matchBegin), PRIVATE(widget,matchEnd), &block) != XawEditDone) { SetSearchLabels(widget, "*** Error while replacing.", "", True); success = False; if (PRIVATE(widget,undo)) { UnlinkUndoRecord(widget, record); } break; } else { XawTextPosition end = PRIVATE(widget,matchBegin) + block.length; XawTextSetInsertionPoint(widget, end); if (PRIVATE(widget,undo)) { record->end = end; } } /* * An automatic search after a single replace is not performed * prior to X11R5 patchlevel 20 since it results in the next * match not being selected, and hence not replaceable. The * standard search popup suffers similarly. */ #ifndef HAVEX11R5PL20 if (once) { break; } #endif /* * If the regular expression is plain ^ or $ we need to take * steps to force the next match to occur on the next line, * otherwise we get into an infinite loop on the current line */ XtVaGetValues(PRIVATE(widget,searchText), XtNstring, ®expr, NULL); if (regexpr[0] == '^' || regexpr[strlen(regexpr) - 1] == '$') { Boolean forward = (((XawTextScanDirection) ((int) XawToggleGetCurrent(PRIVATE(widget,forwards)) - R_OFFSET)) == XawsdRight); XawTextPosition before, after; before = XawTextGetInsertionPoint(widget); if (forward) { after = XawTextSourceScan(XawTextGetSource(widget), before, XawstEOL, XawsdRight, 1, True); } else { after = XawTextSourceScan(XawTextGetSource(widget), before, XawstEOL, XawsdLeft, 1, True); } /* Attempted to pass beyond beginning or end of buffer? */ if (after == 0 || after == XawTextSourceScan(XawTextGetSource(widget), after, XawstPositions, XawsdRight, 1, True)) { XtFree(PRIVATE(widget,matchedText)); /* Kludge to stop */ PRIVATE(widget,matchedText) = 0; /* single replaces */ PRIVATE(widget,matchBegin) = 1; /* beyond ends */ PRIVATE(widget,matchEnd) = 2; /* doing anything */ break; } else { XawTextSetInsertionPoint(widget, after); } } /* End of special processing for ^ and $ */ if (!PerformSearch(widget)) { break; } #ifdef HAVEX11R5PL20 if (once) { break; } #endif } return once ? success : False; } /*ARGSUSED*/ static void DoReReplace(widget, event, params, num_params) Widget widget; XEvent *event; String *params; Cardinal *num_params; { Widget axeii; Boolean popdown; for (axeii = XtParent(widget); !XtIsSubclass(axeii, axeiiTextWidgetClass); axeii = XtParent(axeii)) {} if ((*num_params == 1) && ((params[0][0] == 'p') || (params[0][0] == 'P'))) { popdown = True; } if (PerformReplace(axeii, True) && popdown) { XtCallActionProc(widget, "PopdownSearchAction", event, params, *num_params); } } /*ARGSUSED*/ static void ReplaceOne(widget, client_data, call_data) Widget widget; XtPointer client_data, call_data; { AxeiiTextWidget axeii = (AxeiiTextWidget) client_data; (void) PerformReplace(axeii, True); } /*ARGSUSED*/ static void ReplaceAll(widget, client_data, call_data) Widget widget; XtPointer client_data, call_data; { AxeiiTextWidget axeii = (AxeiiTextWidget) client_data; (void) PerformReplace(axeii, False); } /************************************************************* * * forward/backward-search-selection * *************************************************************/ /*ARGSUSED*/ static void DeliverSelection(w, client_data, selection, type, value, length, format) Widget w; XtPointer client_data; Atom *selection, *type; XtPointer value; unsigned long *length; int *format; { XawTextBlock textBlock; XawTextPosition position; XawTextScanDirection direction = (XawTextScanDirection) client_data; textBlock.firstPos = 0; textBlock.length = (int) *length; textBlock.ptr = (char *) value; textBlock.format = FMT8BIT; if ((position = XawTextSearch(w, direction, &textBlock)) != XawTextSearchError) { XawTextSetSelection(w, position, (XawTextPosition) (position + textBlock.length)); XawTextSetInsertionPoint(w, (direction == XawsdRight) ? position + textBlock.length : position); } XtFree(value); } static void SearchSelection(widget, direction) Widget widget; XawTextScanDirection direction; { XtGetSelectionValue(widget, XA_PRIMARY, XA_STRING, DeliverSelection, (XtPointer) direction, XtLastTimestampProcessed(XtDisplay(widget))); } /*ARGSUSED*/ static void FwdSearchSelection(widget, event, params, num_params) Widget widget; XEvent *event; String *params; Cardinal *num_params; { SearchSelection(widget, XawsdRight); } /*ARGSUSED*/ static void BwdSearchSelection(widget, event, params, num_params) Widget widget; XEvent *event; String *params; Cardinal *num_params; { SearchSelection(widget, XawsdLeft); } static void WhereAmI(widget, line, position) Widget widget; int *line, *position; { Widget textSrc, textSink; Position lmargin; XFontStruct *font; XawTextPosition caret, bol, eol, nexteol, garbage; int where = 1, howfar, distance, junk; XtVaGetValues(widget, XtNtextSource, &textSrc, XtNtextSink, &textSink, XtNfont, &font, XtNleftMargin, &lmargin, NULL); caret = XawTextGetInsertionPoint(widget); eol = XawTextSourceScan(textSrc, 0, XawstEOL, XawsdRight, 1, False); nexteol = XawTextSourceScan(textSrc, eol + 1, XawstEOL, XawsdRight, 1, False); while (eol < caret) { eol = nexteol; nexteol = XawTextSourceScan(textSrc, eol + 1, XawstEOL, XawsdRight, 1, False); ++where; } bol = XawTextSourceScan(textSrc, caret, XawstEOL, XawsdLeft, 1, False); XawTextSinkFindDistance(textSink, bol, (int) lmargin, caret, &distance, &garbage, &junk); howfar = distance / font->max_bounds.width; *line = where; *position = howfar; } /************************************************************* * * insert-char * *************************************************************/ /*ARGSUSED*/ static void InsertCharAction(widget, event, params, num_params) Widget widget; XEvent *event; String *params; Cardinal *num_params; { #if defined(XtSpecificationRelease) && XtSpecificationRelease > 4 if (PRIVATE(widget,delete_on_insert)) { XawTextPosition begin, end; XawTextEditType editType; XawTextBlock block; UndoRecord *tail = PRIVATE(widget,undo_tail); if (!IsModifierKey(XtGetActionKeysym(event, (Modifiers *) 0))) { XawTextGetSelectionPos(widget, &begin, &end); if (begin != end && !PRIVATE(widget,blink_timer)) { if (PRIVATE(widget,undo)) { /* * Convert the DELETING undo record that has just been * created to one of type REPLACE that will cause the * character that is about to be inserted to be replaced * by the selected text that is about to be deleted when * undone. This implementation assumes that the * character being inserted is the first of a sequence * of insertions, the reasoning being that any preceding * sequence will have been terminated by the setting of * the selection. */ XtVaGetValues(widget, XtNeditType, &editType, NULL); if (editType != XawtextRead) { tail->begin = begin; tail->end = begin + 1; tail->undoType = REPLACE; tail->data = AxeiiTextRead(widget, begin, end); tail->complete = 0; } } block.firstPos = 0; block.length = 0; block.ptr = 0; block.format = FMT8BIT; (void) XawTextReplace(widget, begin, end, &block); XawTextSetInsertionPoint(widget, begin); } } } (*CLASS(superInsertChar))(widget, event, params, num_params); #endif } /************************************************************* * * goto-line * *************************************************************/ /*ARGSUSED*/ static void GotoLine(widget, event, params, num_params) Widget widget; XEvent *event; String *params; Cardinal *num_params; { XtCallCallbackList(widget, PRIVATE(widget,goto_line_callbacks), (XtPointer) 0); } /************************************************************* * * search-caret * *************************************************************/ /*ARGSUSED*/ static void SearchCaret(widget, event, params, num_params) Widget widget; XEvent *event; String *params; Cardinal *num_params; { XawTextPosition bol, insPos, eol; GetLineInfo(widget, &bol, &insPos, &eol); if (eol > bol) { --eol; } XawTextSetSelection(widget, bol, eol + 1); /* Force scrolling if necessary */ XawTextSetInsertionPoint(widget, insPos); } /************************************************************* * * include-file * *************************************************************/ /*ARGSUSED*/ static void IncludeFile(widget, event, params, num_params) Widget widget; XEvent *event; String *params; Cardinal *num_params; { XtCallCallbackList(widget, PRIVATE(widget,include_file_callbacks), (XtPointer) 0); } /************************************************************* * * include-selection * *************************************************************/ /*ARGSUSED*/ static void IncludeSelection(widget, event, params, num_params) Widget widget; XEvent *event; String *params; Cardinal *num_params; { String parm[2]; Cardinal num_parm; parm[0] = "PRIMARY"; parm[1] = (char *) 0; num_parm = 1; XtCallActionProc(widget, "insert-selection", event, parm, num_parm); } /************************************************************* * * paste * *************************************************************/ /*ARGSUSED*/ static void Paste(widget, event, params, num_params) Widget widget; XEvent *event; String *params; Cardinal *num_params; { String parm[2]; Cardinal num_parm; parm[0] = "CUT_BUFFER1"; parm[1] = (char *) 0; num_parm = 1; XtCallActionProc(widget, "insert-selection", event, parm, num_parm); } /************************************************************* * * insert-control * *************************************************************/ /*ARGSUSED*/ static void InsertControl(widget, event, params, num_params) Widget widget; XEvent *event; String *params; Cardinal *num_params; { XtCallCallbackList(widget, PRIVATE(widget,insert_control_callbacks), (XtPointer) 0); } /************************************************************* * * delete-word * *************************************************************/ static void DeleteWord(widget, event, params, num_params) Widget widget; XEvent *event; String *params; Cardinal *num_params; { XtCallActionProc(widget, "forward-word", event, params, *num_params); XtCallActionProc(widget, "backward-word", event, params, *num_params); XtCallActionProc(widget, "delete-next-word", event, params, *num_params); } /************************************************************* * * delete-line * *************************************************************/ /*ARGSUSED*/ static void DeleteLine(widget, event, params, num_params) Widget widget; XEvent *event; String *params; Cardinal *num_params; { XtCallActionProc(widget, "beginning-of-line", event, params, *num_params); XtCallActionProc(widget, "kill-to-end-of-line", event, params,*num_params); } /************************************************************* * * where * *************************************************************/ /*ARGSUSED*/ static void Where(widget, event, params, num_params) Widget widget; XEvent *event; String *params; Cardinal *num_params; { AxeiiTextWhereStruct where; WhereAmI(widget, &where.line, &where.position); XtCallCallbackList(widget, PRIVATE(widget,where_callbacks), (XtPointer) &where); } /************************************************************* * * size * *************************************************************/ /*ARGSUSED*/ static void Size(widget, event, params, num_params) Widget widget; XEvent *event; String *params; Cardinal *num_params; { AxeiiTextSizeStruct size; size.rows = PRIVATE(widget,rows); size.columns = PRIVATE(widget,columns); XtCallCallbackList(widget, PRIVATE(widget,size_callbacks), (XtPointer) &size); } /************************************************************* * * centre-line * *************************************************************/ /*ARGSUSED*/ static void CentreLine(widget, event, params, num_params) Widget widget; XEvent *event; String *params; Cardinal *num_params; { AxeiiTextWidget atw = (AxeiiTextWidget) widget; XawTextPosition bol, insPos, eol; String currentLine, cp, ep, newLine; int indent, i; XawTextBlock newText; GetLineInfo(widget, &bol, &insPos, &eol); if (eol > bol) { --eol; } currentLine = AxeiiTextRead(widget, bol, eol); for (cp = currentLine; *cp != '\0' && (*cp == ' ' || *cp == '\t'); ++cp) ; for (ep = cp + strlen(cp) - 1; ep > cp && (*ep == ' ' || *ep == '\t'); --ep) ; *++ep = '\0'; if (strlen(cp) >= atw->axeii.columns) { indent = 0; } else { indent = (atw->axeii.columns - strlen(cp)) / 2; } newLine = (String) XtMalloc(indent + strlen(cp) + 1); for (i = 0; i < indent; ++i) { newLine[i] = ' '; } newLine[i] = '\0'; strcat(newLine, cp); newText.firstPos = 0; newText.length = strlen(newLine); newText.ptr = newLine; newText.format = FMT8BIT; XawTextReplace(widget, bol, eol, &newText); eol = XawTextSourceScan(XawTextGetSource(widget), bol, XawstEOL, XawsdRight, 1, False); XawTextSetInsertionPoint(widget, eol); XtFree(currentLine); XtFree(newLine); } /************************************************************* * * set-preferences * *************************************************************/ /*ARGSUSED*/ static void SetPreferences(widget, event, params, num_params) Widget widget; XEvent *event; String *params; Cardinal *num_params; { XtCallCallbackList(widget, PRIVATE(widget,preferences_callbacks), (XtPointer) 0); } /************************************************************* * * clear-text * *************************************************************/ /*ARGSUSED*/ static void ClearBuffer(widget, event, params, num_params) Widget widget; XEvent *event; String *params; Cardinal *num_params; { XtCallCallbackList(widget, PRIVATE(widget,clear_buffer_callbacks), (XtPointer) 0); } /************************************************************* * * save-file * *************************************************************/ /*ARGSUSED*/ static void SaveFile(widget, event, params, num_params) Widget widget; XEvent *event; String *params; Cardinal *num_params; { XtCallCallbackList(widget, PRIVATE(widget,save_file_callbacks), (XtPointer) 0); } /************************************************************* * * save-as * *************************************************************/ /*ARGSUSED*/ static void SaveAs(widget, event, params, num_params) Widget widget; XEvent *event; String *params; Cardinal *num_params; { XtCallCallbackList(widget, PRIVATE(widget,save_as_callbacks), (XtPointer) 0); } /************************************************************* * * reload-file * *************************************************************/ /*ARGSUSED*/ static void ReloadFile(widget, event, params, num_params) Widget widget; XEvent *event; String *params; Cardinal *num_params; { XtCallCallbackList(widget, PRIVATE(widget,reload_file_callbacks), (XtPointer) 0); } /************************************************************* * * load-file * *************************************************************/ /*ARGSUSED*/ static void LoadFile(widget, event, params, num_params) Widget widget; XEvent *event; String *params; Cardinal *num_params; { XtCallCallbackList(widget, PRIVATE(widget,load_file_callbacks), (XtPointer) 0); } /************************************************************* * * match-parens * *************************************************************/ /*ARGSUSED*/ static void MatchParens(w, event, params, num_params) Widget w; XEvent *event; String *params; Cardinal *num_params; { AxeiiTextWidget atw = (AxeiiTextWidget) w; Widget textSrc = XawTextGetSource(w); XawTextPosition top, from, open, close; XawTextBlock openPatt, closePatt; int level; char openParen, closeParen; if (event->type != KeyPress) { return; } XtCallActionProc(w, "insert-char", event, (String *) 0, (Cardinal) 0); if (PRIVATE(atw,blink_period) == 0) { return; } (void) XLookupString((XKeyEvent *) event, &closeParen, 1, (KeySym *) 0, (XComposeStatus *) 0); switch (closeParen) { case ')': openParen = '('; break; case '}': openParen = '{'; break; case ']': openParen = '['; break; default: return; } openPatt.firstPos = closePatt.firstPos = 0; openPatt.length = closePatt.length = 1; openPatt.ptr = &openParen; closePatt.ptr = &closeParen; openPatt.format = closePatt.format = FMT8BIT; level = 0; top = XawTextTopPosition(w); from = XawTextGetInsertionPoint(w) - 1; for(;;) { open = XawTextSourceSearch(textSrc, from, XawsdLeft, &openPatt); close = XawTextSourceSearch(textSrc, from, XawsdLeft, &closePatt); if (open == XawTextSearchError) { break; } else if (close > open) { ++level; if (close > top) { from = close; } else { break; } } else if (level == 0 && open >= top) { if (PRIVATE(atw,blink_timer)) { XtRemoveTimeOut(PRIVATE(atw,blink_timer)); } XawTextSetSelection(w, open, open + 1); PRIVATE(atw,blink_timer) = XtAppAddTimeOut(XtWidgetToApplicationContext(w), (unsigned long) PRIVATE(atw,blink_period), blinkOff, (XtPointer) w); break; } else { --level; if (open > top) { from = open; } else { break; } } } } /************************************************************* * * find-match * *************************************************************/ /*ARGSUSED*/ static void FindMatch(w, event, params, num_params) Widget w; XEvent *event; String *params; Cardinal *num_params; { Widget asciiSrc = XawTextGetSource(w); XawTextPosition insPos = XawTextGetInsertionPoint(w), from, found, open, close; XawTextBlock openBrack, closeBrack; XawTextScanDirection direction; char opn = '\0', cls; int i, level; if (insPos > 0) { insPos -= 1; } (void) XawTextSourceRead(asciiSrc, insPos, &closeBrack, 1); cls = *closeBrack.ptr; for (i = 0; matchingPairs[i]; i += 2) { if (cls == matchingPairs[i]) { direction = XawsdRight; opn = matchingPairs[i + 1]; break; } } if (!opn) { for (i = 1; matchingPairs[i]; i += 2) { if (cls == matchingPairs[i]) { direction = XawsdLeft; opn = matchingPairs[i - 1]; break; } } } openBrack.firstPos = closeBrack.firstPos = 0; openBrack.length = closeBrack.length = 1; openBrack.ptr = &opn; closeBrack.ptr = &cls; found = XawTextSearchError; for (level = 1, from = (direction == XawsdLeft) ? insPos : insPos + 1;;) { if ((open = XawTextSourceSearch(asciiSrc, from, direction, &openBrack)) == XawTextSearchError) { break; } if ((close = XawTextSourceSearch(asciiSrc, from, direction, &closeBrack)) != XawTextSearchError) { if ( open > close) { if (direction == XawsdLeft) { --level; from = open; } else { ++level; from = close + 1; } } else { if (direction == XawsdLeft) { ++level; from = close; } else { --level; from = open + 1; } } } else { --level; if (direction == XawsdLeft) { from = open; } else { from = open + 1; } } if (level == 0) { found = from; break; } } if (found != XawTextSearchError) { if (direction == XawsdLeft) { ++insPos; } XawTextSetSelection(w, found <= insPos ? found : insPos, found > insPos ? found : insPos); } } /************************************************************* * * forward-line & backward-line * *************************************************************/ static void AddActionHook(w) Widget w; { AxeiiTextWidget atw = (AxeiiTextWidget) w; Widget source, sink; Position lmargin; int insertPosition, distance, morejunk; XawTextPosition bol, junk; if (!atw->axeii.action_hook) { atw->axeii.action_hook = XtAppAddActionHook(XtWidgetToApplicationContext(w), FwdBwdLineHook, (XtPointer) w); XtVaGetValues(w, XtNtextSource, &source, XtNtextSink, &sink, XtNleftMargin, &lmargin, XtNinsertPosition, &insertPosition, NULL); bol = XawTextSourceScan(source, insertPosition, XawstEOL, XawsdLeft, 1, False); XawTextSinkFindDistance(sink, bol, (int) lmargin, (XawTextPosition) insertPosition, &distance, &junk, &morejunk); atw->axeii.fwd_bwd_indent = distance; } } static void FwdBwdLine(w, dir) Widget w; XawTextScanDirection dir; { AxeiiTextWidget atw = (AxeiiTextWidget) w; Widget source, sink; int insertPosition, junk; Position lmargin; XawTextPosition bol, eol, position; XtVaGetValues(w, XtNtextSource, &source, XtNtextSink, &sink, XtNleftMargin, &lmargin, XtNinsertPosition, &insertPosition, NULL); bol = XawTextSourceScan(source, insertPosition, XawstEOL, dir, (dir == XawsdLeft) ? 2 : 1, (dir == XawsdRight)); eol = XawTextSourceScan(source, bol, XawstEOL, XawsdRight, 1, False); XawTextSinkFindPosition(sink, bol, (int) lmargin, atw->axeii.fwd_bwd_indent, False, &position, &junk, &junk); if (eol > position) { XawTextSetInsertionPoint(w, position); } else { XawTextSetInsertionPoint(w, eol); } } /*ARGSUSED*/ static void BackwardLine(w, event, params, num_params) Widget w; XEvent *event; String *params; Cardinal *num_params; { AddActionHook(w); FwdBwdLine(w, XawsdLeft); } /*ARGSUSED*/ static void ForwardLine(w, event, params, num_params) Widget w; XEvent *event; String *params; Cardinal *num_params; { AddActionHook(w); FwdBwdLine(w, XawsdRight); } /*ARGSUSED*/ static void FwdBwdLineHook(w, client_data, action_name, event, params, num_params) Widget w; XtPointer client_data; String action_name; XEvent *event; String *params; Cardinal *num_params; { AxeiiTextWidget atw = (AxeiiTextWidget) w; if ((Widget) client_data != w) { return; } if (strcmp(action_name, "forward-line") != 0 && strcmp(action_name, "backward-line") != 0) { XtRemoveActionHook(atw->axeii.action_hook); atw->axeii.action_hook = (XtActionHookId) 0; return; } } /************************************************************* * * delete-selection-or-previous-character * *************************************************************/ /*ARGSUSED*/ static void DelSelOrPrevChar(w, event, params, num_params) Widget w; XEvent *event; String *params; Cardinal *num_params; { XawTextPosition begin, end; XawTextGetSelectionPos(w, &begin, &end); if (begin != end && !PRIVATE(w,blink_timer)) { XtCallActionProc(w, "delete-selection", event, (String *) 0, (Cardinal) 0); } else { XtCallActionProc(w, "delete-previous-character", event, (String *) 0, (Cardinal) 0); } } /************************************************************* * * insert-or-expand-tab * *************************************************************/ static void InsertOrExpandTab(w, event, params, num_params) Widget w; XEvent *event; String *params; Cardinal *num_params; { XawTextPosition bol, before = XawTextGetInsertionPoint(w), junk; Position lmargin; Widget source, sink; XFontStruct *font; int bdistance, adistance, moreJunk; XawTextBlock block; static char spaces[] = " "; XtCallActionProc(w, "insert-char", event, params, *num_params); if (!PRIVATE(w,expand_tabs)) { return; } XtVaGetValues(w, XtNleftMargin, &lmargin, XtNtextSource, &source, XtNtextSink, &sink, XtNfont, &font, NULL); bol = XawTextSourceScan(source, before, XawstEOL, XawsdLeft, 1, False); XawTextSinkFindDistance(sink, bol, (int) lmargin, before, &bdistance, &junk, &moreJunk); XawTextSinkFindDistance(sink, bol, (int) lmargin, before + 1, &adistance, &junk, &moreJunk); block.firstPos = 0; block.length = (adistance - bdistance) / font->max_bounds.width; block.ptr = spaces; block.format = FMT8BIT; XawTextReplace(w, before, before + 1, &block); XawTextSetInsertionPoint(w, before + block.length); } /************************************************************* * * set-mark * *************************************************************/ /*ARGSUSED*/ static void SetMark(w, event, params, num_params) Widget w; XEvent *event; String *params; Cardinal *num_params; { PRIVATE(w,mark) = XawTextGetInsertionPoint(w); } /************************************************************* * * highlight-region * *************************************************************/ /*ARGSUSED*/ static void HighlightRegion(w, event, params, num_params) Widget w; XEvent *event; String *params; Cardinal *num_params; { XawTextPosition from, to; AxeiiTextGetRegion(w, &from, &to); XawTextSetSelection(w, from, to); } /************************************************************* * * kill-region * *************************************************************/ /*ARGSUSED*/ static void KillRegion(w, event, params, num_params) Widget w; XEvent *event; String *params; Cardinal *num_params; { XawTextPosition from, to; String region; XawTextBlock block; AxeiiTextGetRegion(w, &from, &to); region = AxeiiTextRead(w, from, to); XStoreBuffer(XtDisplay(w), region, to - from, 2); block.firstPos = 0; block.length = 0; block.ptr = NULL; block.format = FMT8BIT; XawTextReplace(w, from, to, &block); XtFree(region); } /************************************************************* * * copy-region * *************************************************************/ /*ARGSUSED*/ static void CopyRegion(w, event, params, num_params) Widget w; XEvent *event; String *params; Cardinal *num_params; { XawTextPosition from, to; String region; AxeiiTextGetRegion(w, &from, &to); region = AxeiiTextRead(w, from, to); XStoreBuffer(XtDisplay(w), region, to - from, 2); XtFree(region); } /************************************************************* * * yank-region * *************************************************************/ /*ARGSUSED*/ static void YankRegion(w, event, params, num_params) Widget w; XEvent *event; String *params; Cardinal *num_params; { XawTextPosition pos = XawTextGetInsertionPoint(w); XawTextBlock block; block.firstPos = 0; block.ptr = XFetchBuffer(XtDisplay(w), &block.length, 2); block.format = FMT8BIT; XawTextReplace(w, pos, pos, &block); XawTextSetInsertionPoint(w, pos + block.length); } /************************************************************* * * keymap * *************************************************************/ /* ARGSUSED */ static void KeyMap(widget, event, params, num_params) Widget widget; XEvent *event; String *params; Cardinal *num_params; { static XtResource key_resources[] = { {XtNtranslations, XtCTranslations, XtRTranslationTable, sizeof(XtTranslations), 0, XtRTranslationTable, (XtPointer) 0} }; char mapName[1000]; char mapClass[1000]; if (*num_params != 1) { return; } if (strcmp(params[0], "None") == 0) { XtOverrideTranslations(widget, PRIVATE(widget,translations)); return; } (void) sprintf( mapName, "%sKeymap", params[0] ); (void) strcpy( mapClass, mapName ); if (islower(mapClass[0])) { mapClass[0] = toupper(mapClass[0]); } XtGetSubresources(widget, (XtPointer) &PRIVATE(widget,keymap), mapName, mapClass, key_resources, (Cardinal) 1, NULL, (Cardinal) 0); if (PRIVATE(widget,keymap)) { XtOverrideTranslations(widget, PRIVATE(widget,keymap)); } } /************************************************************* * * Semi-public functions * *************************************************************/ /* * CopyCallbackList is used by the undo module, * which is logically part of AxeiiText anyway. */ void CopyCallbackList(src, dst) XtCallbackList src, *dst; { int number; for (number = 0; src[number].callback; ++number); ++number; *dst = (XtCallbackList) XtMalloc((Cardinal) (number * sizeof(XtCallbackRec))); for (--number; number >= 0; --number) { (*dst)[number].callback = src[number].callback; (*dst)[number].closure = src[number].closure; } } /* * AxeiiTextReSearch isn't really public; it is like this so that it can * be called by AxeEditor. The String pointed to by match on entry should * either be NULL or freeable by XtFree. The returned string should either * be freed by the caller or passed in the next call. */ Boolean AxeiiTextReSearch(widget, forward, regexpr, compexp, match, begin, end) Widget widget; Boolean forward; String regexpr; regexp *compexp; String *match; XawTextPosition *begin, *end; { Widget textSrc; XawTextBlock block; XawTextPosition pos, lastPos, xoff, yoff; XawTextPosition bol, eol, lastEol, swap, readfrom, toread; Boolean found; int length; String subText, startp, endp; if (!XtIsSubclass(widget, axeiiTextWidgetClass)) { return False; } textSrc = XawTextGetSource(widget); found = False; pos = XawTextGetInsertionPoint(widget); if (regexpr[0] == '^') { bol = XawTextSourceScan(textSrc, pos, XawstEOL, XawsdLeft, 1, False); if (forward) { /* * Move to next line if not at beginning of a line or * the last match matched the beginning of this line */ if (pos != bol || (pos == bol && PRIVATE(widget,matchBegin) == pos && PRIVATE(widget,matchEnd) == pos)) { pos = XawTextSourceScan(textSrc, pos, XawstEOL, XawsdRight, 1, True); } /* * Don't go past last newline if nothing follows it */ if (pos != XawTextSourceScan(textSrc, pos, XawstPositions, XawsdRight, 1, True)) { XawTextSetInsertionPoint(widget, pos); } else { return False; } } else /* backwards */ { /* * Move to previous line if not at beginning of a line or * the last match matched the beginning of this line or * on empty line at end of file */ if (pos == bol && (PRIVATE(widget,matchBegin) == pos && PRIVATE(widget,matchEnd) == pos || pos == XawTextSourceScan(textSrc, pos, XawstPositions, XawsdRight, 1, True))) { pos = XawTextSourceScan(textSrc, pos, XawstEOL, XawsdLeft, 2, False); } else { pos = bol; } /* * Beginning of first line matches unless previously matched */ if (pos == 0 && PRIVATE(widget,matchBegin) == pos && PRIVATE(widget,matchEnd) == pos) { return False; } else { XawTextSetInsertionPoint(widget, pos); } } } else if (regexpr[strlen(regexpr) - 1] == '$') { eol = XawTextSourceScan(textSrc, pos, XawstEOL, XawsdRight, 1, False); if (forward) { /* * Move to next line if not at end of a line or * the last match matched the end of this line */ if (pos != eol) { pos = eol; } else if (PRIVATE(widget,matchBegin) == pos && PRIVATE(widget,matchEnd) == pos) { XawTextPosition one, two; one = XawTextSourceScan(textSrc, pos, XawstPositions, XawsdRight, 1, True); two = XawTextSourceScan(textSrc, pos, XawstEOL, XawsdRight, 2, False); /* * Don't go past last newline if nothing follows it */ if (one != two) { pos = two; XawTextSetInsertionPoint(widget, pos); } else { return False; } } } else /* backwards */ { /* * Move to previous line if not at end of a line or * the last match matched the end of this line or * at end of file beyond last newline */ if (pos != eol || ((PRIVATE(widget,matchBegin) == pos && PRIVATE(widget,matchEnd) == pos)) || (pos == XawTextSourceScan(textSrc, pos, XawstPositions, XawsdRight, 1, True) && pos == XawTextSourceScan(textSrc, pos, XawstEOL, XawsdLeft, 1, False))) { pos = XawTextSourceScan(textSrc, pos, XawstEOL, XawsdLeft, 1, True); } /* * Trap attempts to go past beginning of file */ if (pos > 0) { XawTextSetInsertionPoint(widget, pos); } else { return False; } } } for (lastPos = pos - 1, eol = -1, lastEol = 0; pos != lastPos && eol != lastEol; ) { lastEol = eol; if (forward) { eol = XawTextSourceScan(textSrc, pos, XawstEOL, XawsdRight, 1, False); } else { eol = XawTextSourceScan(textSrc, pos, XawstEOL, XawsdLeft, 1, False); swap = pos; pos = eol; eol = swap; } length = (int) (eol - pos); block.format = FMT8BIT; XtFree(*match); *match = XtMalloc(length + 1); (*match)[0] = '\0'; for(toread = length, readfrom = pos; toread > 0; toread = toread - block.length, readfrom = readfrom + block.length) { (void) XawTextSourceRead(textSrc, readfrom, &block, toread); (void) strncat(*match, block.ptr, block.length); } if (regexec(compexp,*match)) { found = True; startp = compexp->startp[0]; endp = compexp->endp[0]; if (!forward && startp != endp) { for (subText = startp + 1; regexec(compexp, subText); subText = compexp->startp[0] + 1) { if ((compexp->endp[0] - compexp->startp[0]) > (endp - startp)) { startp = compexp->startp[0]; endp = compexp->endp[0]; } } if (RegError) { break; } compexp->startp[0] = startp; compexp->endp[0] = endp; } xoff = (XawTextPosition) (compexp->startp[0] - *match); yoff = (XawTextPosition) (compexp->endp[0] - *match); XawTextSetSelection(widget, pos + xoff, pos + yoff); *begin = pos + xoff; *end = pos + yoff; if (forward) { XawTextSetInsertionPoint(widget, pos + yoff); } else { XawTextSetInsertionPoint(widget, pos + xoff); } break; } if (RegError) { break; } lastPos = pos; if (forward) { pos = eol + 1; } else { if (pos > 0) { pos -= 1; } } } if (!found) { *begin = *end = 0; } return found; } /************************************************************* * * Public functions * *************************************************************/ void AxeiiTextWidthHeightToRowsColumns(widget, rows, cols) Widget widget; int *rows, *cols; { XFontStruct *font; Position lm, rm, tm, bm; Dimension width, height, caretHeight; Widget sink; XRectangle caret; XtVaGetValues(widget, XtNfont, &font, XtNwidth, &width, XtNheight, &height, XtNleftMargin, &lm, XtNrightMargin, &rm, XtNtopMargin, &tm, XtNbottomMargin, &bm, XtNtextSink, &sink, NULL); XawTextSinkGetCursorBounds(sink, &caret); caretHeight = (Dimension) caret.height; *cols = (width - lm - rm) / font->max_bounds.width; *rows = (height - tm - bm - CARETHEIGHT) / (font->max_bounds.ascent + font->max_bounds.descent); } void AxeiiTextRowsColumnsToWidthHeight(rows, cols, widget, width, height) int rows, cols; Widget widget; Dimension *width, *height; { XFontStruct *font; Dimension caretHeight; Position lm, rm, tm, bm; Widget sink; XRectangle caret; XtVaGetValues(widget, XtNfont, &font, XtNleftMargin, &lm, XtNrightMargin, &rm, XtNtopMargin, &tm, XtNbottomMargin, &bm, XtNtextSink, &sink, NULL); XawTextSinkGetCursorBounds(sink, &caret); caretHeight = (Dimension) caret.height; *width = cols * font->max_bounds.width + lm + rm; *height = rows * (font->max_bounds.ascent +font->max_bounds.descent) + tm + bm + CARETHEIGHT; } void AxeiiTextWatchForChanges(atw) Widget atw; { if (XtIsSubclass(atw, axeiiTextWidgetClass) && !PRIVATE(atw,watching_changes)) { XtAddCallback(XawTextGetSource(atw), XtNcallback, AsciiSourceChanged, (XtPointer) CLOSURE); PRIVATE(atw,watching_changes) = True; } } void AxeiiTextGotoLine(atw, line) Widget atw; int line; { XawTextPosition bol; if (!XtIsSubclass(atw, axeiiTextWidgetClass)) { return; } bol = XawTextSourceScan(XawTextGetSource(atw), (XawTextPosition) 0, XawstEOL,XawsdRight, line - 1, True); XawTextSetInsertionPoint(atw, bol); } String AxeiiTextRead(text, from, to) Widget text; XawTextPosition from, to; { int length = (int) (to - from), toread; XawTextBlock block; XawTextPosition readfrom; String theText = XtMalloc(length + 1); block.format = FMT8BIT; theText[0] = '\0'; for(toread = length, readfrom = from; toread > 0; toread = toread - block.length, readfrom = readfrom + block.length) { (void) XawTextSourceRead(XawTextGetSource(text), readfrom, &block, toread); (void) strncat(theText, block.ptr, block.length); } return theText; } void AxeiiTextGetRegion(widget, begin, end) Widget widget; XawTextPosition *begin, *end; { XawTextPosition now = XawTextGetInsertionPoint(widget); *begin = PRIVATE(widget,mark) <= now ? PRIVATE(widget,mark) : now; *end = PRIVATE(widget,mark) > now ? PRIVATE(widget,mark) : now; } void (* AxeiiTextUndoPreInsert(atw))() Widget atw; { if (XtIsSubclass(atw, axeiiTextWidgetClass) && PRIVATE(atw,undo)) { return CLASS(preInsertUndo); } return 0; } void (* AxeiiTextUndoPreReplace(atw))() Widget atw; { if (XtIsSubclass(atw, axeiiTextWidgetClass) && PRIVATE(atw,undo)) { return CLASS(preReplaceUndo); } return 0; } void (* AxeiiTextUndoPostLoad(atw))() Widget atw; { if (XtIsSubclass(atw, axeiiTextWidgetClass) && PRIVATE(atw,undo)) { return CLASS(postLoadUndo); } return 0; } #undef PRIVATE #undef CLASS axe-6.1.2.orig/Widgets/AxeiiText.h100644 243 144 7474 5550557122 15473 0ustar joostusers/* * Copyright 1992 The University of Newcastle upon Tyne * * Permission to use, copy, modify and distribute this software and its * documentation for any purpose other than its commercial exploitation * is hereby granted without fee, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of The University of Newcastle upon Tyne not be used in * advertising or publicity pertaining to distribution of the software * without specific, written prior permission. The University of * Newcastle upon Tyne makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * THE UNIVERSITY OF NEWCASTLE UPON TYNE DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF * NEWCASTLE UPON TYNE BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. * * Author: Jim Wight (j.k.wight@newcastle.ac.uk) * Department of Computing Science * University of Newcastle upon Tyne, UK */ #ifndef _AxeiiText_h #define _AxeiiText_h #include typedef struct _AxeiiTextClassRec *AxeiiTextWidgetClass; typedef struct _AxeiiTextRec *AxeiiTextWidget; extern WidgetClass axeiiTextWidgetClass; extern void AxeiiTextWatchForChanges(); typedef struct { int line; int position; } AxeiiTextWhereStruct; typedef struct { int rows; int columns; } AxeiiTextSizeStruct; #define XtNrows "rows" #define XtCRows "Rows" #define XtNcolumns "columns" #define XtCColumns "Columns" #define XtNblockCaret "blockCaret" #define XtCBlockCaret "BlockCaret" #define XtNcaretBitmap "caretBitmap" #define XtNtabEvery "tabEvery" #define XtCTabEvery "TabEvery" #define XtNblinkPeriod "blinkPeriod" #define XtCBlinkPeriod "BlinkPeriod" #define XtNexpandTabs "expandTabs" #define XtCExpandTabs "ExpandTabs" #define XtNwatchingChanges "watchingChanges" #define XtCWatchingChanges "WatchingChanges" #define XtNmodifiedCallback "modifiedCallback" #define XtNgotoLineCallback "gotoLineCallback" #define XtNincludeFileCallback "includeFileCallback" #define XtNinsertControlCallback "insertControlCallback" #define XtNwhereCallback "whereCallback" #define XtNsizeCallback "sizeCallback" #define XtNpreferencesCallback "preferencesCallback" #define XtNclearBufferCallback "clearBufferCallback" #define XtNsaveFileCallback "saveFileCallback" #define XtNsaveAsCallback "saveAsCallback" #define XtNloadFileCallback "loadFileCallback" #define XtNreloadFileCallback "reloadFileCallback" #define XtNnoUndoCallback "noUndoCallback" #define XtNundo "undo" #define XtCUndo "Undo" #define XtNundoLevel "undoLevel" #define XtCUndoLevel "UndoLevel" #define XtNdeleteOnInsert "deleteOnInsert" #define XtCDeleteOnInsert "DeleteOnInsert" void AxeiiTextWidthHeightToRowsColumns(); void AxeiiTextRowsColumnsToWidthHeight(); void AxeiiTextWatchForChanges(); void AxeiiTextGotoLine(); Boolean AxeiiTextReSearch(); String AxeiiTextRead(); void AxeiiTextGetRegion(); void CopyCallbackList(); void (*AxeiiTextUndoPreInsert())(); void (*AxeiiTextUndoPreReplace())(); void (*AxeiiTextUndoPostLoad())(); #endif /* _AxeiiText_h */ axe-6.1.2.orig/Widgets/AxeiiTextP.h100644 243 144 11367 5550557122 15627 0ustar joostusers/* * Copyright 1992 The University of Newcastle upon Tyne * * Permission to use, copy, modify and distribute this software and its * documentation for any purpose other than its commercial exploitation * is hereby granted without fee, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of The University of Newcastle upon Tyne not be used in * advertising or publicity pertaining to distribution of the software * without specific, written prior permission. The University of * Newcastle upon Tyne makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * THE UNIVERSITY OF NEWCASTLE UPON TYNE DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF * NEWCASTLE UPON TYNE BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. * * Author: Jim Wight (j.k.wight@newcastle.ac.uk) * Department of Computing Science * University of Newcastle upon Tyne, UK */ #ifndef _AxeiiTextP_h #define _AxeiiTextP_h #include #include #include #include "regexp.h" typedef struct { XtPointer extension; XtTranslations translations; XtTranslations search_translations; XtTranslations replace_translations; void (*preInsertUndo)(); void (*preReplaceUndo)(); void (*postLoadUndo)(); void (*superInsertChar)(); void (*superSearch)(); } AxeiiClassPart; typedef struct _AxeiiTextClassRec { CoreClassPart core_class; SimpleClassPart simple_class; TextClassPart text_class; AsciiClassPart ascii_class; AxeiiClassPart axeii_class; } AxeiiTextClassRec; extern AxeiiTextClassRec axeiiTextClassRec; typedef struct { /* Resources */ int rows; int columns; Boolean block_caret; String caret_bitmap; int tab_every; long blink_period; Boolean expand_tabs; Boolean watching_changes; XtCallbackList modified_callbacks; XtCallbackList goto_line_callbacks; XtCallbackList include_file_callbacks; XtCallbackList insert_control_callbacks; XtCallbackList where_callbacks; XtCallbackList size_callbacks; XtCallbackList preferences_callbacks; XtCallbackList clear_buffer_callbacks; XtCallbackList save_file_callbacks; XtCallbackList save_as_callbacks; XtCallbackList load_file_callbacks; XtCallbackList reload_file_callbacks; XtCallbackList no_undo_callbacks; Boolean undo; int undo_level; Boolean delete_on_insert; /* Private variables */ XtActionHookId action_hook; XtIntervalId blink_timer; int fwd_bwd_indent; XawTextPosition mark; XtTranslations translations; XtTranslations keymap; /* Regular expression searching */ Widget search; Widget label1; Widget label2; Widget forwards; Widget searchText; Widget replaceText; Widget searchTranslations; Widget replaceTranslations; Widget searchOne; XtCallbackList searchCallbacks; Widget replaceOne; XtCallbackList replaceOneCallbacks; Widget replaceAll; XtCallbackList replaceAllCallbacks; regexp *compexp; String matchedText; XawTextPosition matchBegin; XawTextPosition matchEnd; XtActionHookId undo_hook; XtActionHookId insert_popup_hook; XtActionHookId search_popup_hook; UndoRecord *undo_head; UndoRecord *undo_tail; Boolean undoing; XrmQuark lastAction; XtCallbackList insertFileCallbacks; XtCallbackList searchOneCallbacks; XtCallbackList searchAllCallbacks; } AxeiiPart; typedef struct _AxeiiTextRec { CorePart core; SimplePart simple; TextPart text; AsciiPart ascii; AxeiiPart axeii; } AxeiiTextRec; #endif /* _AxeiiTextP_h */ axe-6.1.2.orig/Widgets/AxeiiUndo.c100644 243 144 123721 5550557113 15501 0ustar joostusers/* * Copyright 1993 The University of Newcastle upon Tyne * * Permission to use, copy, modify and distribute this software and its * documentation for any purpose other than its commercial exploitation * is hereby granted without fee, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of The University of Newcastle upon Tyne not be used in * advertising or publicity pertaining to distribution of the software * without specific, written prior permission. The University of * Newcastle upon Tyne makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * THE UNIVERSITY OF NEWCASTLE UPON TYNE DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF * NEWCASTLE UPON TYNE BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. * * Author: Jim Wight (j.k.wight@newcastle.ac.uk) * Department of Computing Science * University of Newcastle upon Tyne, UK */ /* * The implemenatation of Undo in aXe * * Undo in aXe is built upon the Action Hook mechanism. Advantage is taken of * the fact that a procedure that will be called before every action routine * is invoked can be specified. aXe tries to predict in the hook procedure * what the action will do and construct an undo record containing enough * information to enable the inverse operation to be carried out. If * sufficient information can't be obtained at that time a routine that will * complete the job is registered for calling just before the next action is * similarly treated. * * The information enabling undos to be carried out is held on a per widget * basis in doubly linked lists of records having the following structure:- * * +--------------+ * | prev | * +--------------+ * | begin | * +--------------+ * | end | * +--------------+ * | undoType | * +--------------+ * | data | * +--------------+ * | complete | * +--------------+ * | next | * +--------------+ * * where * * prev - is a link to the previous record. * * begin - is the position at which the undo takes place. * * end - together with begin delimits a region of text involved in * the undo. * * undoType - specifies the type of undo operation, and is either INSERT, * DELETE or REPLACE. * * data - is a pointer to an associated string. * * complete - is a pointer to a routine that should be called to complete * the gathering of information for the undo record. * * next - is a pointer to the next record. * * Records are used in the following way for the three types of alteration: * * Insertion * begin - start of region to be deleted * end - end of region to be deleted * undoType - DELETE * data - NULL * complete - usually needed * * Deletion * begin - point at which text should be inserted * end - undefined, probably 0 * undoType - INSERT * data - the text to be inserted * complete - not usually needed * * Replacement * begin - start of region to be replaced * end - end of region to be replaced * undoType - REPLACE * data - replacement text * complete - may or may not be needed * * An empty chain is represented by a spare record that is pointed to by head * and tail pointers in the widget record. Two of its fields are used to * contain other information: prev is used to point to the record that would * be used if an undo were requested, and begin is used to record the length * of the chain. If prev points to the head record, as it does initially, and * an undo is requested then it is changed to point to the tail record before * embarking on the undo. After an undo it is made to point to the previous * record pointed to by the undo record just used. * * New records are appended to the chain and undos are carried out by * traversing backwards from the tail. As each undo is performed a record to * undo the undo is constructed and appended. If sufficient consecutive undos * are performed to cause the head of the chain to be reached, wraparound to * the end of the now extended tail takes place, enabling the most recent * undos also to be undone. The process comes to a halt when the first * non-undo action is encountered, at which point, if appropriate, the chain * is reduced to its preferred length. That length is specified by the * resource undoLevel, a value of 0 for which implies unlimited undo * information being kept and the length of the chain never being cropped. * * A single record is kept for a block of consecutively inserted characters up * to a line in length, rather than maintaining records for the individual * characters. Thus executing undo will delete the entire block, not the most * recently inserted character. That is best done by deleting the character. * Control codes entered via the control code selector popup are an exception * in that individual undo records are kept. Undo records are kept for deleted * characters. */ #include #include #include #include #include "AxeiiTextP.h" #include "AxeiiUndo.h" #define HEAD(w) ((w)->axeii.undo_head) #define TAIL(w) ((w)->axeii.undo_tail) #define UNDO(w) ((w)->axeii.undo_head->prev) #define LEVEL(w) ((w)->axeii.undo_head->begin) typedef struct { String action; void (*proc)(); } ActionForUndo; static XrmQuark undoQuark; static XrmQuark inscharQuark, newlineQuark, indentQuark, backupQuark; static void NoOp(); static void InsertChar(), InsertText(), InsertFile(); static void TransposeChars(), ClearBuffer(), DeleteSelection(); static void DeleteAmount(), DeleteNextWord(), DeletePreviousWord(); static void DeleteEndLine(), DeleteEndParagraph(), DeleteSelOrChar(); static void DeletePrevChar(), DeleteNextChar(); static void CentreLine(), FormParagraph(); static void DeleteRegion(); static void Undoing(); static void RecordAmount(), RecordParagraph(); static void ReSearch(), SearchReplace(); static void AdjustChainLength(); static Boolean searchFromReSearch = False; #ifdef DEBUG static void PrintChain(); #endif static ActionForUndo actionTable[] = { {"centre-line", CentreLine}, {"clear-buffer", ClearBuffer}, {"undo", Undoing}, {"kill-region", DeleteRegion}, {"yank-region", InsertText}, {"backward-kill-word", DeletePreviousWord}, {"delete-next-character", DeleteNextChar}, {"delete-next-word", DeleteNextWord}, {"delete-previous-character", DeletePrevChar}, {"delete-previous-word", DeletePreviousWord}, {"delete-selection", DeleteSelection}, {"form-paragraph", FormParagraph}, {"insert-char", InsertChar}, {"insert-file", InsertFile}, {"insert-selection", InsertText}, {"insert-string", InsertText}, {"kill-selection", DeleteSelection}, {"kill-to-end-of-line", DeleteEndLine}, {"kill-to-end-of-paragraph", DeleteEndParagraph}, {"kill-word", DeleteNextWord}, {"newline", InsertChar}, {"newline-and-backup", InsertChar}, {"newline-and-indent", InsertChar}, {"re-search", ReSearch}, {"search", SearchReplace}, {"transpose-characters", TransposeChars}, /* {"delete-selection-or-previous-character", DeleteSelOrChar}, */ /* {"DoReReplace", NoOp}, */ /* {"DoReSearch", NoOp}, */ /* {"backward-line", NoOp}, */ /* {"backward-search-selection", NoOp}, */ /* {"copy-region", NoOp}, */ /* {"delete-line", NoOp}, */ /* {"delete-word", NoOp}, */ /* {"find-match", NoOp}, */ /* {"forward-line", NoOp}, */ /* {"forward-search-selection", NoOp}, */ /* {"goto-line", NoOp}, */ /* {"highlight-region", NoOp}, */ /* {"include-file", NoOp}, */ /* {"include-selection", NoOp}, */ /* {"insert-control", NoOp}, */ /* {"insert-or-expand-tab", NoOp}, */ /* {"keymap", NoOp}, */ /* {"load-file", NoOp}, */ /* {"match-parens", NoOp}, */ /* {"paste", NoOp}, */ /* {"re-search", NoOp}, */ /* {"reload-file", NoOp}, */ /* {"save-as", NoOp}, */ /* {"save-file", NoOp}, */ /* {"search-caret", NoOp}, */ /* {"search-line", NoOp}, */ /* {"set-mark", NoOp}, */ /* {"set-preferences", NoOp}, */ /* {"size", NoOp}, */ /* {"where", NoOp}, */ /* {"DoReplaceAction", NoOp}, */ /* {"DoSearchAction", NoOp}, */ /* {"InsertFileAction", NoOp}, */ /* {"PopdownSearchAction", NoOp}, */ /* {"SetField", NoOp}, */ /* {"backward-character", NoOp}, */ /* {"backward-paragraph", NoOp}, */ /* {"backward-word", NoOp}, */ /* {"beginning-of-file", NoOp}, */ /* {"beginning-of-line", NoOp}, */ /* {"display-caret", NoOp}, */ /* {"end-of-file", NoOp}, */ /* {"end-of-line", NoOp}, */ /* {"extend-adjust", NoOp}, */ /* {"extend-end", NoOp}, */ /* {"extend-start", NoOp}, */ /* {"focus-in", NoOp}, */ /* {"focus-out", NoOp}, */ /* {"forward-character", NoOp}, */ /* {"forward-paragraph", NoOp}, */ /* {"forward-word", NoOp}, */ /* {"insert-file", NoOp}, */ /* {"multiply", NoOp}, */ /* {"next-line", NoOp}, */ /* {"next-page", NoOp}, */ /* {"no-op", NoOp}, */ /* {"previous-line", NoOp}, */ /* {"previous-page", NoOp}, */ /* {"redraw-display", NoOp}, */ /* {"scroll-one-line-down", NoOp}, */ /* {"scroll-one-line-up", NoOp}, */ /* {"search", NoOp}, */ /* {"select-adjust", NoOp}, */ /* {"select-all", NoOp}, */ /* {"select-end", NoOp}, */ /* {"select-save", NoOp}, */ /* {"select-start", NoOp}, */ /* {"select-word", NoOp}, */ /* {"close-all", NoOp}, */ /* {"close-buffer", NoOp}, */ /* {"close-window", NoOp}, */ /* {"deiconify-all", NoOp}, */ /* {"end-macro", NoOp}, */ /* {"exec-macro", NoOp}, */ /* {"help", NoOp}, */ /* {"iconify-all", NoOp}, */ /* {"mini-abort", NoOp}, */ /* {"mini-clear", NoOp}, */ /* {"mini-commit", NoOp}, */ /* {"mini-insert", NoOp}, */ /* {"mini-leave", NoOp}, */ /* {"mini-load", NoOp}, */ /* {"mini-pipe", NoOp}, */ /* {"mini-saveas", NoOp}, */ /* {"mini-search", NoOp}, */ /* {"mini-select", NoOp}, */ /* {"mini-shell", NoOp}, */ /* {"new-buffer", NoOp}, */ /* {"new-window", NoOp}, */ /* {"repeat-macro", NoOp}, */ /* {"restack", NoOp}, */ /* {"save-all", NoOp}, */ /* {"save-and-close", NoOp}, */ /* {"save-and-exit ", NoOp}, */ /* {"start-macro", NoOp}, */ /* {"update-info", NoOp}, */ {0, 0} }; static XrmQuark allQuarks[sizeof(actionTable) / sizeof(ActionForUndo)] = { 0 }; /************************************************************* * * Chain Management * *************************************************************/ UndoRecord* NewUndoRecord() { UndoRecord *record; record = XtNew(UndoRecord); record->prev = record->next = 0; record->begin = record->end = 0; record->undoType = 0; record->data = 0; record->complete = 0; return record; } void InitialiseUndo(atw) AxeiiTextWidget atw; { int s; String str; if (!allQuarks[0]) { for (s = 0; (str = actionTable[s].action); ++s) { allQuarks[s] = XrmStringToQuark(str); if (strcmp(str, "undo") == 0) { undoQuark = allQuarks[s]; } else if (strcmp(str, "insert-char") == 0) { inscharQuark = allQuarks[s]; } else if (strcmp(str, "newline") == 0) { newlineQuark = allQuarks[s]; } else if (strcmp(str, "newline-and-indent") == 0) { indentQuark = allQuarks[s]; } else if (strcmp(str, "newline-and-backup") == 0) { backupQuark = allQuarks[s]; } } allQuarks[s] = 0; } HEAD(atw) = TAIL(atw) = NewUndoRecord(); UNDO(atw) = HEAD(atw); } UndoRecord* LinkNewUndoRecord(widget) Widget widget; { AxeiiTextWidget atw = (AxeiiTextWidget) widget; UndoRecord *record = NewUndoRecord(); record->prev = TAIL(atw); TAIL(atw)->next = record; TAIL(atw) = record; ++LEVEL(atw); return record; } void UnlinkUndoRecord(widget, record) Widget widget; UndoRecord *record; { AxeiiTextWidget atw = (AxeiiTextWidget) widget; TAIL(atw) = record->prev; if (UNDO(atw) == record) { UNDO(atw) = record->prev; } record->prev->next = 0; XtFree(record->data); XtFree((char *) record); --LEVEL(atw); } void FreeUndo(widget, head) Widget widget; Boolean head; { AxeiiTextWidget atw = (AxeiiTextWidget) widget; UndoRecord *this = HEAD(atw), *next;; if (!head) { this = this->next; HEAD(atw)->next = 0; UNDO(atw) = TAIL(atw) = HEAD(atw); LEVEL(atw) = 0; } for (next = this ? this->next : 0; this; this = next, next = this ? this->next : 0) { XtFree(this->data); XtFree((char *) this); } } static void AdjustChainLength(widget) Widget widget; { AxeiiTextWidget atw = (AxeiiTextWidget) widget; int level = atw->axeii.undo_level, removals; UndoRecord *next, *delete; if (!level || (removals = LEVEL(atw) - level) <= 0) { return; } for (next = HEAD(atw)->next; removals > 0; --removals) { delete = next; next = delete->next; if (UNDO(atw) == delete) { UNDO(atw) = HEAD(atw); } XtFree(delete->data); XtFree((char *) delete); } HEAD(atw)->next = next; next->prev = HEAD(atw); LEVEL(atw) = level; #ifdef DEBUG PrintChain(widget); #endif } /************************************************************* * * The Action Hook on which it all hangs * *************************************************************/ /*ARGSUSED*/ void UndoHook(widget, client_data, action, event, params, num_params) Widget widget; XtPointer client_data; String action; XEvent *event; String *params; Cardinal *num_params; { AxeiiTextWidget atw = (AxeiiTextWidget) widget; XrmQuark quark = XrmStringToQuark(action); XawTextEditType editType; int q; void (*proc)(), (*complete)(); if (widget != (Widget) client_data) { return; } for (q = 0; allQuarks[q] && quark != allQuarks[q]; ++q) ; /* Perform 2nd phase of previous action */ if ( (!(proc = actionTable[q].proc) || proc != InsertChar || (proc == InsertChar && atw->axeii.lastAction != inscharQuark)) && (complete = TAIL(atw)->complete)) { (*complete)(widget); } if (quark != undoQuark || atw->axeii.lastAction != undoQuark) { AdjustChainLength(widget); } if (proc) { /* No point in continuing if action is going to fail */ XtVaGetValues(widget, XtNeditType, &editType, NULL); if (editType == XawtextRead) { return; } (*proc)(widget, &quark); } atw->axeii.lastAction = quark; } /************************************************************* * * Insert * *************************************************************/ static void RecordAmount(widget) Widget widget; { AxeiiTextWidget atw = (AxeiiTextWidget) widget; UndoRecord *tail = TAIL(atw); if (!tail->end) { tail->end = XawTextGetInsertionPoint(widget); } if (tail->begin == tail->end) { UnlinkUndoRecord(widget, tail); } else { if (tail->undoType == DELETING) { tail->undoType = DELETE; } tail->complete = 0; } } static void RecordParagraph(widget) Widget widget; { AxeiiTextWidget atw = (AxeiiTextWidget) widget; TAIL(atw)->end = XawTextSourceScan(XawTextGetSource(widget), XawTextGetInsertionPoint(widget), XawstParagraph, XawsdRight, 1, False); TAIL(atw)->complete = 0; } /*ARGSUSED*/ static void RemoveActionHook(widget, client_data, call_data) Widget widget; XtPointer client_data, call_data; { XtRemoveActionHook(((AxeiiTextWidget) client_data)->axeii.insert_popup_hook); } /*ARGSUSED*/ static void InsertFileAction(widget, client_data, action, event, params, num_params) Widget widget; XtPointer client_data; String action; XEvent *event; String *params; Cardinal *num_params; { Widget atw = (Widget) client_data; if (strcmp(action, "InsertFileAction") != 0) { return; } /* Create the undo record */ InsertText(atw, (XrmQuark) 0); } /*ARGSUSED*/ static void InsertFileCallback(widget, client_data, call_data) Widget widget; XtPointer client_data, call_data; { Widget atw = (Widget) client_data; AxeiiTextWidget axtw = (AxeiiTextWidget) atw; XtCallbackList callb; /* Create the undo record */ InsertText(atw, (XrmQuark) 0); /* Call the original callback list */ for (callb = axtw->axeii.insertFileCallbacks; callb->callback; ++callb) { (*callb->callback)(atw, callb->closure, (XtPointer) 0); } } static Boolean ModifyInsertFile(client_data) XtPointer client_data; { Widget widget = (Widget) client_data; AxeiiTextWidget atw = (AxeiiTextWidget) widget; Widget popup = XtNameToWidget(widget, "*insertFile"); Widget insert = XtNameToWidget(widget, "*insertFile*insert"); XtCallbackList callbacks, callb; int ncallb; /* * We have arrived here as a result of the insert-file action * being invoked, i.e. the popup has just been created. It is * too early to create an undo record as the user might cancel * the popup or make other changes before really inserting a * file. So what we do is add an action hook routine to the * filename entry field and save the callback list attached to * the insert button, replacing it with our own. The user is * committed when they hit Return or click the insert button so * it is safe for our action hook and callback routines to * create an undo record. A callback that removes the action * hook is attached to the popup's popdownCallback list. * * Add an action hook routine to trap the user hitting * Return in the text field of the insert file popup. */ atw->axeii.insert_popup_hook = XtAppAddActionHook(XtWidgetToApplicationContext(widget), InsertFileAction, (XtPointer) widget); /* * We only save the callback list once. Assumption * is that it is the same for all text widgets. */ if (atw->axeii.insertFileCallbacks) { return True; } XtVaGetValues(insert, XtNcallback, &callbacks, NULL); CopyCallbackList(callbacks, &atw->axeii.insertFileCallbacks); XtRemoveAllCallbacks(insert, XtNcallback); XtAddCallback(popup, XtNpopdownCallback, RemoveActionHook, (XtPointer) widget); XtAddCallback(insert, XtNcallback, InsertFileCallback, (XtPointer) widget); return True; } static void InsertChar(widget, quark) Widget widget; XrmQuark *quark; { AxeiiTextWidget atw = (AxeiiTextWidget) widget; UndoRecord *record; if (*quark == inscharQuark) { if (TAIL(atw)->undoType == DELETING) { return; } } else if (*quark == newlineQuark || *quark == indentQuark) { if (TAIL(atw)->undoType == DELETING) { *quark = 0; /* force completion on next action */ return; } } else if (*quark == backupQuark) { if (TAIL(atw)->undoType == DELETING) { TAIL(atw)->end = XawTextGetInsertionPoint(widget) + 1; *quark = 0; /* force completion on next action */ return; } } record = LinkNewUndoRecord(widget); record->begin = XawTextGetInsertionPoint(widget); if (*quark == backupQuark) /* Can this ever be true */ { record->end = record->begin + 1; } record->undoType = DELETING; record->complete = RecordAmount; } /*ARGSUSED*/ static void InsertText(widget, quark) Widget widget; XrmQuark *quark; { UndoRecord *record = LinkNewUndoRecord(widget); record->begin = XawTextGetInsertionPoint(widget); record->undoType = DELETE; record->complete = RecordAmount; } /*ARGSUSED*/ static void InsertFile(widget, quark) Widget widget; XrmQuark *quark; { /* * The insert-file action is about to be called. As a result the * insert popup will be created. We need to do some work on it. * Let's hope that a work proc will get in before the user */ (void) XtAppAddWorkProc(XtWidgetToApplicationContext(widget), ModifyInsertFile, (XtPointer) widget); } void InsertUndo(widget) Widget widget; { AxeiiTextWidget atw = (AxeiiTextWidget) widget; /* * This routine may be called from the minibuffer as a result of * an "r" command, i.e. not as the result of an action. Hence it * has to do some of the work of UndoHook. The reason for the last * statement of the block is in case it is called in the middle * of a sequence of inserting characters, in which case the completion * of the insertion of the file won't get done. Setting lastAction to * 0 gets round the problem. */ if (TAIL(atw)->complete) { (*(TAIL(atw)->complete))(widget); TAIL(atw)->complete = 0; atw->axeii.lastAction = 0; } InsertText(widget, (XrmQuark) 0); } void ReplaceUndo(widget) Widget widget; { AxeiiTextWidget atw = (AxeiiTextWidget) widget; UndoRecord *record; XawTextPosition begin, end; /* * This routine may be called from the minibuffer as a result of * a "|" command, i.e. not as the result of an action. Hence it * has to do some of the work of UndoHook. The reason for the last * statement of the block is in case it is called in the middle * of a sequence of inserting characters, in which case the completion * of the insertion of the text won't get done. Setting lastAction to * 0 gets round the problemy. */ if (TAIL(atw)->complete) { (*(TAIL(atw)->complete))(widget); TAIL(atw)->complete = 0; atw->axeii.lastAction = 0; } XawTextGetSelectionPos(widget, &begin, &end); if (end != begin) { record = LinkNewUndoRecord(widget); record->begin = begin; record->undoType = REPLACE; record->data = AxeiiTextRead(widget, begin, end); record->complete = RecordAmount; } } /************************************************************* * * Delete * *************************************************************/ static void MakeUndoRecord(widget, begin, end, dir, op, complete) Widget widget; XawTextPosition begin, end; XawTextScanDirection dir; int op; void (*complete)(); { UndoRecord *record; if (end != begin) { record = LinkNewUndoRecord(widget); record->begin = (dir == XawsdRight) ? begin : end; record->end = (dir == XawsdRight) ? end : begin; record->undoType = op; record->data = AxeiiTextRead(widget, record->begin, record->end); if (complete) { record->complete = complete; } } } /*ARGSUSED*/ static void DeleteSelection(widget, quark) Widget widget; XrmQuark *quark; { XawTextPosition begin, end; XawTextGetSelectionPos(widget, &begin, &end); MakeUndoRecord(widget, begin, end, XawsdRight, INSERT, NULL); } static void DeleteScanAmount(widget, type, dir, op, complete) Widget widget; XawTextScanType type; XawTextScanDirection dir; int op; void (*complete)(); { XawTextPosition pos, begin, end; begin = XawTextGetInsertionPoint(widget); end = XawTextSourceScan(XawTextGetSource(widget), begin, type, dir, 1, False); if (begin == end && type == XawstEOL && dir == XawsdRight) { end = XawTextSourceScan(XawTextGetSource(widget), begin, XawstEOL, XawsdRight, 1, True); if (end - begin != 1) { end = begin; } } MakeUndoRecord(widget, begin, end, dir, op, complete); } /*ARGSUSED*/ static void DeleteNextWord(widget, quark) Widget widget; XrmQuark *quark; { DeleteScanAmount(widget, XawstWhiteSpace, XawsdRight, INSERT, NULL); } /*ARGSUSED*/ static void DeletePreviousWord(widget, quark) Widget widget; XrmQuark *quark; { DeleteScanAmount(widget, XawstWhiteSpace, XawsdLeft, INSERT, NULL); } /*ARGSUSED*/ static void DeleteEndLine(widget, quark) Widget widget; XrmQuark *quark; { DeleteScanAmount(widget, XawstEOL, XawsdRight, INSERT, NULL); } /*ARGSUSED*/ static void DeleteEndParagraph(widget, quark) Widget widget; XrmQuark *quark; { DeleteScanAmount(widget, XawstParagraph, XawsdRight, INSERT, NULL); } static void DeleteOneChar(widget, dir) Widget widget; XawTextScanDirection dir; { XawTextPosition begin, end; Widget textSrc = XawTextGetSource(widget); begin = XawTextGetInsertionPoint(widget); if (dir == XawsdLeft) { end = begin > 0 ? begin - 1 : 0; } else { end = XawTextSourceScan(textSrc, begin, XawstPositions, dir, 1, True); } MakeUndoRecord(widget, begin, end, dir, INSERT, NULL); } /*ARGSUSED*/ static void DeletePrevChar(widget, quark) Widget widget; XrmQuark *quark; { DeleteOneChar(widget, XawsdLeft); } /*ARGSUSED*/ static void DeleteNextChar(widget, quark) Widget widget; XrmQuark *quark; { DeleteOneChar(widget, XawsdRight); } /* * Not needed, because the work is done by the delete-selection * and delete-previous-character actions when they are called. * static void DeleteSelOrChar(widget, quark) Widget widget; XrmQuark *quark; { XawTextPosition begin, end; XawTextGetSelectionPos(widget, &begin, &end); if (begin == end) { DeletePrevChar(widget, quark); } else { DeleteSelection(widget, quark); } } */ /*ARGSUSED*/ static void DeleteRegion(widget, quark) Widget widget; XrmQuark *quark; { XawTextPosition begin, end; AxeiiTextGetRegion(widget, &begin, &end); MakeUndoRecord(widget, begin, end, XawsdRight, INSERT, NULL); } /************************************************************* * * Replace * *************************************************************/ /*ARGSUSED*/ static void CentreLine(widget, quark) Widget widget; XrmQuark *quark; { XawTextPosition pos = XawTextGetInsertionPoint(widget), begin, end; begin = XawTextSourceScan(XawTextGetSource(widget), pos, XawstEOL, XawsdLeft, 1, False); end = XawTextSourceScan(XawTextGetSource(widget), pos, XawstEOL, XawsdRight, 1, False); MakeUndoRecord(widget, begin, end, XawsdRight, REPLACE, RecordAmount); TAIL((AxeiiTextWidget) widget)->end = 0; } /*ARGSUSED*/ static void FormParagraph(widget, quark) Widget widget; XrmQuark *quark; { XawTextPosition pos = XawTextGetInsertionPoint(widget), begin, end; begin = XawTextSourceScan(XawTextGetSource(widget), pos, XawstParagraph, XawsdLeft, 1, False); end = XawTextSourceScan(XawTextGetSource(widget), pos, XawstParagraph, XawsdRight, 1, False); MakeUndoRecord(widget, begin, end, XawsdRight, REPLACE, RecordParagraph); } /*ARGSUSED*/ static void TransposeChars(widget, quark) Widget widget; XrmQuark quark; { XawTextPosition pos = XawTextGetInsertionPoint(widget), begin, end; begin = XawTextSourceScan(XawTextGetSource(widget), pos, XawstPositions, XawsdLeft, 1, True); end = XawTextSourceScan(XawTextGetSource(widget), pos, XawstPositions, XawsdRight, 1, True); if (end - begin != 2) { end = begin; } MakeUndoRecord(widget, begin, end, XawsdRight, REPLACE, NULL); } /*ARGSUSED*/ static void ReSearch(widget, quark) Widget widget; XrmQuark *quark; { searchFromReSearch = True; } static Boolean RemoveSearchHook(client_data) XtPointer client_data; { AxeiiTextWidget atw = (AxeiiTextWidget) client_data; XtRemoveActionHook(atw->axeii.search_popup_hook); return True; } /*ARGSUSED*/ static void SearchPopdown(widget, client_data, call_data) Widget widget; XtPointer client_data, call_data; { XtCallbackList callb; Widget one = XtNameToWidget(widget, "*replaceOne"); Widget all = XtNameToWidget(widget, "*replaceAll"); AxeiiTextWidget atw = (AxeiiTextWidget) XtParent(widget); /* * This may be treating the symptons rather than the cause, but removing * the action hook directly here causes core dumps when hitting the Cancel * button if the Search button has been used. In the absence of an * understanding of the problem get round it by doing the work later in * a work proc. */ (void) XtAppAddWorkProc(XtWidgetToApplicationContext(widget), RemoveSearchHook, (XtPointer) atw); /* * Restore "Replace One" and "Replace All" callbacks */ XtRemoveAllCallbacks(one, XtNcallback); for (callb = atw->axeii.searchOneCallbacks; callb->callback; ++callb) { XtAddCallback(one, XtNcallback, callb->callback, callb->closure); } XtRemoveAllCallbacks(all, XtNcallback); for (callb = atw->axeii.searchAllCallbacks; callb->callback; ++callb) { XtAddCallback(all, XtNcallback, callb->callback, callb->closure); } /* * Remove ourself; it appears to work but is this really safe? */ XtRemoveCallback(widget, XtNpopdownCallback, SearchPopdown, client_data); } /*ARGSUSED*/ static void ReplaceText(widget, srchFor, rplcWith) Widget widget; String *srchFor, *rplcWith; { Widget searchFor, replaceWith; String selection, searchText, replaceText; XawTextPosition begin, end; UndoRecord *record; *srchFor = 0; *rplcWith = 0; XawTextGetSelectionPos(widget, &begin, &end); /* Selection has probably been tampered with */ if (begin == end) { return; } selection = AxeiiTextRead(widget, begin, end); searchFor = XtNameToWidget(widget, "*search*searchText"); XtVaGetValues(searchFor, XtNstring, &searchText, NULL); /* Selection has probably been tampered with */ if (strcmp(selection, searchText) != 0) { XtFree(selection); return; } XtFree(selection); replaceWith = XtNameToWidget(widget, "*search*replaceText"); XtVaGetValues(replaceWith, XtNstring, &replaceText, NULL); record = LinkNewUndoRecord(widget); record->begin = begin; record->end = begin + strlen(replaceText); record->undoType = REPLACE; record->data = XtNewString(searchText); *srchFor = searchText; *rplcWith = replaceText; } /*ARGSUSED*/ void DoReplaceAction(widget, client_data, action, event, params, num_params) Widget widget; XtPointer client_data; String action; XEvent *event; String *params; Cardinal *num_params; { Widget atw = (Widget) client_data; String searchFor, replaceWith; if (strcmp(action, "DoReplaceAction") != 0) { return; } /* Create the undo record */ ReplaceText(atw, &searchFor, &replaceWith); } /*ARGSUSED*/ static void DoReplaceCallback(widget, client_data, call_data) Widget widget; XtPointer client_data, call_data; { Widget atw = (Widget) client_data; AxeiiTextWidget axtw = (AxeiiTextWidget) atw; String searchFor, replaceWith; XtCallbackList callb; /* Create the undo record */ ReplaceText(atw, &searchFor, &replaceWith); if (!searchFor || !replaceWith) { return; } /* Call the original callback list */ for (callb = axtw->axeii.searchOneCallbacks; callb->callback; ++callb) { (*callb->callback)(atw, callb->closure, (XtPointer) 0); } } /*ARGSUSED*/ static void DoReplaceAllCallback(widget, client_data, call_data) Widget widget; XtPointer client_data, call_data; { Widget atw = (Widget) client_data; AxeiiTextWidget axtw = (AxeiiTextWidget) atw; Widget textSrc = XawTextGetSource(atw); String searchFor, replaceWith; int slen, rlen, diff, adjustment; XawTextPosition found; XawTextBlock block; UndoRecord *record; XtCallbackList callb; /* Do the first one */ ReplaceText(atw, &searchFor, &replaceWith); if (!searchFor || !replaceWith) { return; } slen = strlen(searchFor); rlen = strlen(replaceWith); diff = rlen - slen; block.firstPos = 0; block.length = slen; block.ptr = searchFor; block.format = FMT8BIT; /* * Deal with subsequent occurrences, making allowance for the * difference in lengths of the search and replacement strings */ for (found = XawTextGetInsertionPoint(atw), adjustment = diff; (found = XawTextSourceSearch(textSrc, found, XawsdRight, &block )) != XawTextSearchError; found += block.length, adjustment += diff) { record = LinkNewUndoRecord(atw); record->begin = found + adjustment; record->end = found + rlen + adjustment; record->undoType = REPLACE; record->data = XtNewString(block.ptr); } /* * Now call the original callback list to perform the replacements */ for (callb = axtw->axeii.searchAllCallbacks; callb->callback; ++callb) { (*callb->callback)(atw, callb->closure, (XtPointer) 0); } } static Boolean ModifySearchReplace(client_data) XtPointer client_data; { Widget widget = (Widget) client_data; AxeiiTextWidget atw = (AxeiiTextWidget) widget; Widget popup = XtNameToWidget(widget, "*search"); Widget with = XtNameToWidget(popup, "*replaceText"); Widget one = XtNameToWidget(popup, "*replaceOne"); Widget all = XtNameToWidget(popup, "*replaceAll"); XtCallbackList callbacks, callb; int ncallb; /* * We have arrived here as a result of the search action being * invoked on its own, i.e. not from re-search. It is too early to * create an undo record as the user might cancel the popup or make * other changes before replacing anything. So what we do is add an * action hook routine to the "Replace with" entry field and save the * callback list attached to the Replace One/All buttons, replacing them * with our own. The user is committed when they hit Return or click the * Replace One/All buttons, so it is safe for our action hook and callback * routines to create undo record/s. A callback that removes them is * is attached to the popup's popdownCallback list. * * Add an action hook routine to trap the user hitting * Return in the text field of the search file popup. */ atw->axeii.search_popup_hook = XtAppAddActionHook(XtWidgetToApplicationContext(widget), DoReplaceAction, (XtPointer) widget); XtVaGetValues(one, XtNcallback, &callbacks, NULL); XtFree((char *) atw->axeii.searchOneCallbacks); CopyCallbackList(callbacks, &atw->axeii.searchOneCallbacks); XtRemoveAllCallbacks(one, XtNcallback); XtAddCallback(one, XtNcallback, DoReplaceCallback, (XtPointer) widget); XtVaGetValues(all, XtNcallback, &callbacks, NULL); XtFree((char *) atw->axeii.searchAllCallbacks); CopyCallbackList(callbacks, &atw->axeii.searchAllCallbacks); XtRemoveAllCallbacks(all, XtNcallback); XtAddCallback(all, XtNcallback, DoReplaceAllCallback, (XtPointer) widget); XtAddCallback(popup, XtNpopdownCallback, SearchPopdown, (XtPointer) widget); return True; } /*ARGSUSED*/ static void SearchReplace(widget, quark) Widget widget; XrmQuark *quark; { /* * The search action is about to be called. The search popup may * be about to be created or already exist from earlier execution * of the search or re-search actions. Whatever the case, we need * to do some work on it, but only if not called via the re-search * action since re-search (own code) does undos a different way. * Let's hope that a work proc will get in before the user. */ if (!searchFromReSearch) { (void) XtAppAddWorkProc(XtWidgetToApplicationContext(widget), ModifySearchReplace, (XtPointer) widget); } else { searchFromReSearch = False; } } /************************************************************* * * Reset * *************************************************************/ void ResetUndo(widget) Widget widget; { FreeUndo(widget, False); } /*ARGSUSED*/ static void ClearBuffer(widget, quark) Widget widget; XrmQuark quark; { FreeUndo(widget, False); } /************************************************************* * * Undo * *************************************************************/ static void Undoing(widget, quark) Widget widget; XrmQuark *quark; { AxeiiTextWidget atw = (AxeiiTextWidget) widget; if (*quark == undoQuark) { atw->axeii.undoing = (atw->axeii.lastAction == undoQuark); } } /*ARGSUSED*/ void UndoAction(widget, event, params, num_params) Widget widget; XEvent *event; String *params; Cardinal *num_params; { AxeiiTextWidget atw = (AxeiiTextWidget) widget; XawTextBlock block; UndoRecord *element, *inverse; String replaced; if (!atw->axeii.undo) { XtCallCallbackList(widget, atw->axeii.no_undo_callbacks, (XtPointer)0); return; } if (!atw->axeii.undo) { return; } if (!atw->axeii.undoing) { UNDO(atw) = TAIL(atw); } else if (UNDO(atw) == HEAD(atw)) { UNDO(atw) = TAIL(atw); } if (UNDO(atw) == HEAD(atw)) { XtCallCallbackList(widget, atw->axeii.no_undo_callbacks, (XtPointer)0); return; } /* * Perform the undo action specified in the undo record; * Construct a record to specify the inverse action; * Add that record to the tail of the undo chain; */ element = UNDO(atw); inverse = LinkNewUndoRecord(atw); inverse->begin = element->begin; block.firstPos = 0; block.format = FMT8BIT; switch (element->undoType) { case INSERT: block.length = strlen(element->data); block.ptr = element->data; XawTextReplace(widget, element->begin, element->begin, &block); XawTextSetInsertionPoint(widget, element->begin + block.length); inverse->end = inverse->begin + block.length; inverse->undoType = DELETE; break; case DELETE: inverse->data = AxeiiTextRead(widget, element->begin, element->end); block.length = 0; block.ptr = 0; XawTextReplace(widget, element->begin, element->end, &block); XawTextSetInsertionPoint(widget, element->begin); inverse->end = element->end; inverse->undoType = INSERT; break; case REPLACE: replaced = AxeiiTextRead(widget, element->begin, element->end); block.length = strlen(element->data); block.ptr = element->data; XawTextReplace(widget, element->begin, element->end, &block); XawTextSetInsertionPoint(widget, element->begin + block.length); inverse->end = inverse->begin + block.length; inverse->undoType = element->undoType; inverse->data = replaced; break; default: break; } UNDO(atw) = element->prev; #ifdef DEBUG PrintChain(widget); #endif } /************************************************************* * * Were useful once * *************************************************************/ /* static void NoOp(widget, quark) Widget widget; XrmQuark *quark; { printf("%s\n", XrmQuarkToString(*quark)); } */ #ifdef DEBUG static void PrintChain(widget) Widget widget; { AxeiiTextWidget atw = (AxeiiTextWidget) widget; UndoRecord *next; printf("\n========================\n"); for (next = HEAD(atw); next; next = next->next) { printf("%x\n %x %d %d %d %s %x\n", next, next->prev, next->begin, next->end, next->undoType, next->data, next->next); } } #endif axe-6.1.2.orig/Widgets/AxeiiUndo.h100644 243 144 4221 5550557122 15437 0ustar joostusers/* * Copyright 1993 The University of Newcastle upon Tyne * * Permission to use, copy, modify and distribute this software and its * documentation for any purpose other than its commercial exploitation * is hereby granted without fee, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of The University of Newcastle upon Tyne not be used in * advertising or publicity pertaining to distribution of the software * without specific, written prior permission. The University of * Newcastle upon Tyne makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * THE UNIVERSITY OF NEWCASTLE UPON TYNE DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF * NEWCASTLE UPON TYNE BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. * * Author: Jim Wight (j.k.wight@newcastle.ac.uk) * Department of Computing Science * University of Newcastle upon Tyne, UK */ #ifndef _AxeiiUndo_h #define _AxeiiUndo_h #include #include #define INSERT 1 #define DELETE 2 #define DELETING 3 #define REPLACE 4 typedef struct _UndoRecord { struct _UndoRecord *prev; XawTextPosition begin; XawTextPosition end; int undoType; char *data; void (*complete)(); struct _UndoRecord *next; } UndoRecord; extern void InitialiseUndo(); extern void UndoHook(); extern UndoRecord *LinkNewUndoRecord(); extern void UnlinkUndoRecord(); extern void NullAction(); extern void UndoAction(); extern void InsertUndo(); extern void ReplaceUndo(); extern void ResetUndo(); #endif /* _AxeiiUndo_h */ axe-6.1.2.orig/Widgets/Confirmer.c100644 243 144 22007 5550557113 15513 0ustar joostusers/* * Copyright 1992 The University of Newcastle upon Tyne * * Permission to use, copy, modify and distribute this software and its * documentation for any purpose other than its commercial exploitation * is hereby granted without fee, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of The University of Newcastle upon Tyne not be used in * advertising or publicity pertaining to distribution of the software * without specific, written prior permission. The University of * Newcastle upon Tyne makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * * * THE UNIVERSITY OF NEWCASTLE UPON TYNE DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF * NEWCASTLE UPON TYNE BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. * * Author: Jim Wight (j.k.wight@newcastle.ac.uk) * Department of Computing Science * University of Newcastle upon Tyne, UK */ #include #include #include #include #include #include #include "util.h" #include "ConfirmerP.h" #include "warn.xbm" #define CLASS(field) confirmerClassRec.confirmer_class.field #define PRIVATE(w,field) (((ConfirmerWidget) w)->confirmer.field) static void Initialize(); static Widget ConfirmerOf(); static void OnPopup(), Confirm(), Alt(), Cancel(); #define ShellOffset(field) XtOffsetOf(ConfirmerRec, shell.field) #define Offset(field) XtOffsetOf(ConfirmerRec, confirmer.field) static XtResource resources[] = { /* Shell Widget Resources */ { XtNallowShellResize, XtCAllowShellResize, XtRBoolean, sizeof(Boolean), ShellOffset(allow_shell_resize), XtRImmediate, (XtPointer) False}, /* Confirmer Widget Resources */ {XtNgrabOnPopup, XtCGrabOnPopup, XtRBoolean, sizeof(Boolean), Offset(grab_on_popup), XtRImmediate, (XtPointer) False}, }; #undef Offset ConfirmerClassRec confirmerClassRec = { { /* superclass */ (WidgetClass) &transientShellClassRec, /* class_name */ "Confirmer", /* size */ sizeof(ConfirmerRec), /* Class Initializer */ NULL, /* class_part_initialize*/ NULL, /* Class init'ed ? */ FALSE, /* initialize */ Initialize, /* initialize_notify */ NULL, /* realize */ XtInheritRealize, /* actions */ NULL, /* num_actions */ 0, /* resources */ resources, /* resource_count */ XtNumber(resources), /* xrm_class */ NULLQUARK, /* compress_motion */ FALSE, /* compress_exposure */ TRUE, /* compress_enterleave*/ FALSE, /* visible_interest */ FALSE, /* destroy */ NULL, /* resize */ XtInheritResize, /* expose */ XtInheritExpose, /* set_values */ NULL, /* set_values_hook */ NULL, /* set_values_almost */ XtInheritSetValuesAlmost, /* get_values_hook */ NULL, /* accept_focus */ NULL, /* intrinsics version */ XtVersion, /* callback offsets */ NULL, /* tm_table */ XtInheritTranslations, /* query_geometry */ NULL, /* display_accelerator */ NULL, /* extension */ NULL },{ /* geometry_manager */ XtInheritGeometryManager, /* change_managed */ XtInheritChangeManaged, /* insert_child */ XtInheritInsertChild, /* delete_child */ XtInheritDeleteChild, /* extension */ NULL },{ /* extension */ NULL },{ /* extension */ NULL },{ /* extension */ NULL },{ /* extension */ NULL },{ /* extension */ NULL } }; WidgetClass confirmerWidgetClass = (WidgetClass) &confirmerClassRec; /* ARGSUSED */ static void Initialize(req, new, args, num_args) Widget req, new; ArgList args; Cardinal *num_args; { Display *display = XtDisplay(new); Widget conform, actions, cancel; static char layout[] = "exclam 0 0; warning 0 1; actions 0 2;"; XpTableLoc tableLoc; if (!CLASS(warnLogo)) { CLASS(warnLogo) = XCreateBitmapFromData(display, XDefaultRootWindow(display), (char *) warn_bits, warn_width, warn_height); } XtAddCallback(new, XtNpopupCallback, OnPopup, (XtPointer) 0); tableLoc = XpTableLocParse(layout); conform = XtVaCreateManagedWidget("conf", xpTableWidgetClass, new, XtNlayout, tableLoc, XtNmarginWidth, 5, XtNmarginHeight, 5, XtNrowSpacing, 5, XtNcolumnSpacing, 5, NULL); XpTableLocFree(tableLoc); XtVaCreateManagedWidget("exclam", labelWidgetClass, conform, XtNbitmap, CLASS(warnLogo), XtNborderWidth, 0, NULL); PRIVATE(new,warning_widget) = XtVaCreateManagedWidget("warning", labelWidgetClass, conform, NULL); actions = XtVaCreateManagedWidget("actions", boxWidgetClass, conform, NULL); PRIVATE(new,confirm_widget) = XtVaCreateManagedWidget("confirm", commandWidgetClass, actions, NULL); PRIVATE(new,alt_widget) = XtVaCreateManagedWidget("alternative", commandWidgetClass, actions, NULL); cancel = XtVaCreateManagedWidget("cancel", commandWidgetClass, actions, NULL); XtAddCallback(cancel, XtNcallback, Cancel, (XtPointer) new); XtInstallAllAccelerators(conform, conform); } static Widget ConfirmerOf(widget) Widget widget; { Widget w; for (w = widget; w; w = XtParent(w)) { if (XtIsSubclass(w, confirmerWidgetClass)) { return w; } } return (Widget) 0; } /* ARGSUSED */ static void OnPopup(widget, client_data, call_data) Widget widget; XtPointer client_data, call_data; { XBell(XtDisplay(widget), 100); } /* ARGSUSED */ static void Confirm(widget, client_data, call_data) Widget widget; XtPointer client_data, call_data; { Widget confirmer = ConfirmerOf(widget); XtPopdown(confirmer); PRIVATE(confirmer,confirm_callback) (widget, client_data, call_data); } /* ARGSUSED */ static void Alt(widget, client_data, call_data) Widget widget; XtPointer client_data, call_data; { Widget confirmer = ConfirmerOf(widget); XtPopdown(confirmer); PRIVATE(confirmer,alt_callback) (widget, client_data, call_data); } /* ARGSUSED */ static void Cancel(widget, client_data, call_data) Widget widget; XtPointer client_data, call_data; { XtPopdown((Widget) client_data); } /************************************************************* * * Public functions * *************************************************************/ void ConfirmerRequestConfirmation(w, warning, confirm, confCallback, alt, altCallback, client_data) Widget w; String warning; String confirm, alt; XtCallbackProc confCallback, altCallback; XtPointer client_data; { String nlab; if (!XtIsSubclass(w, confirmerWidgetClass)) { return; } XtVaSetValues(PRIVATE(w,warning_widget), XtNlabel, warning, NULL); nlab = XtMalloc(strlen(confirm) + 6); strcpy(nlab, confirm); strcat(nlab, " (^A)"); XtVaSetValues(PRIVATE(w,confirm_widget), XtNlabel, nlab, NULL); XtFree(nlab); if (altCallback) { nlab = XtMalloc(strlen(alt) + 6); strcpy(nlab, alt); strcat(nlab, " (^B)"); } else { nlab = alt; } XtVaSetValues(PRIVATE(w,alt_widget), XtNlabel, nlab, XtNsensitive, altCallback ? True : False, NULL); if (nlab != alt) { XtFree(nlab); } XtRemoveAllCallbacks(PRIVATE(w,confirm_widget), XtNcallback); XtRemoveAllCallbacks(PRIVATE(w,alt_widget), XtNcallback); if (confCallback) { PRIVATE(w,confirm_callback) = confCallback; XtAddCallback(PRIVATE(w,confirm_widget), XtNcallback, Confirm, (confCallback == ConfirmerPopdown) ? (XtPointer) w : client_data); } if (altCallback) { PRIVATE(w,alt_callback) = altCallback; XtAddCallback(PRIVATE(w,alt_widget), XtNcallback, Alt, (altCallback == ConfirmerPopdown) ? (XtPointer) w : client_data); } PopupCentred(w, PRIVATE(w,grab_on_popup) ? XtGrabExclusive : XtGrabNone); } /* ARGSUSED */ void ConfirmerPopdown(widget, client_data, call_data) Widget widget; XtPointer client_data, call_data; { XtPopdown((Widget) client_data); } axe-6.1.2.orig/Widgets/Confirmer.h100644 243 144 3505 5550557122 15502 0ustar joostusers/* * Copyright 1992 The University of Newcastle upon Tyne * * Permission to use, copy, modify and distribute this software and its * documentation for any purpose other than its commercial exploitation * is hereby granted without fee, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of The University of Newcastle upon Tyne not be used in * advertising or publicity pertaining to distribution of the software * without specific, written prior permission. The University of * Newcastle upon Tyne makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * THE UNIVERSITY OF NEWCASTLE UPON TYNE DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF * NEWCASTLE UPON TYNE BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. * * Author: Jim Wight (j.k.wight@newcastle.ac.uk) * Department of Computing Science * University of Newcastle upon Tyne, UK */ #ifndef Confirmer_h #define Confirmer_h #include typedef struct _ConfirmerClassRec *ConfirmerWidgetClass; typedef struct _ConfirmerRec *ConfirmerWidget; extern WidgetClass confirmerWidgetClass; extern void ConfirmerRequestConfirmation(); extern void ConfirmerPopdown(); #define XtNgrabOnPopup "grabOnPopup" #define XtCGrabOnPopup "GrabOnPopup" #endif /* Confirmer_h */ axe-6.1.2.orig/Widgets/ConfirmerP.h100644 243 144 5155 5550557122 15625 0ustar joostusers/* * Copyright 1992 The University of Newcastle upon Tyne * * Permission to use, copy, modify and distribute this software and its * documentation for any purpose other than its commercial exploitation * is hereby granted without fee, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of The University of Newcastle upon Tyne not be used in * advertising or publicity pertaining to distribution of the software * without specific, written prior permission. The University of * Newcastle upon Tyne makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * THE UNIVERSITY OF NEWCASTLE UPON TYNE DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF * NEWCASTLE UPON TYNE BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. * * Author: Jim Wight (j.k.wight@newcastle.ac.uk) * Department of Computing Science * University of Newcastle upon Tyne, UK */ #ifndef ConfirmerP_h #define ConfirmerP_h #include #include "Confirmer.h" typedef struct { XtPointer extension; Pixmap warnLogo; } ConfirmerClassPart; typedef struct _ConfirmerClassRec { CoreClassPart core_class; CompositeClassPart composite_class; ShellClassPart shell_class; WMShellClassPart wm_shell_class; VendorShellClassPart vendor_shell_class; TransientShellClassPart transient_shell_class; ConfirmerClassPart confirmer_class; } ConfirmerClassRec; extern ConfirmerClassRec confirmerClassRec; typedef struct { /* Resources */ Boolean grab_on_popup; /* Private data */ Widget warning_widget; Widget confirm_widget; XtCallbackProc confirm_callback; Widget alt_widget; XtCallbackProc alt_callback; } ConfirmerPart; typedef struct _ConfirmerRec { CorePart core; CompositePart composite; ShellPart shell; WMShellPart wm; VendorShellPart vendor; TransientShellPart transient; ConfirmerPart confirmer; } ConfirmerRec; #endif /* ConfirmerP_h */ axe-6.1.2.orig/Widgets/CtrlCodeSel.c100644 243 144 25065 5550557114 15742 0ustar joostusers/* * Copyright 1992 The University of Newcastle upon Tyne * * Permission to use, copy, modify and distribute this software and its * documentation for any purpose other than its commercial exploitation * is hereby granted without fee, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of The University of Newcastle upon Tyne not be used in * advertising or publicity pertaining to distribution of the software * without specific, written prior permission. The University of * Newcastle upon Tyne makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * THE UNIVERSITY OF NEWCASTLE UPON TYNE DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF * NEWCASTLE UPON TYNE BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. * * Author: Jim Wight (j.k.wight@newcastle.ac.uk) * Department of Computing Science * University of Newcastle upon Tyne, UK */ #include #include #include #include #include #include #define CLASS(field) controlCodeSelectorClassRec.control_code_selector_class.field #define PRIVATE(w,field) (((ControlCodeSelectorWidget) w)->control.field) #define TableOffset(field) XtOffsetOf(ControlCodeSelectorRec, table.field) #define Offset(field) XtOffsetOf(ControlCodeSelectorRec, control.field) static char layout[] = "list 0 0 12; \ code 0 1 2 whH; enter 2 1 5 whH; cancel 7 1 5 whH;"; static XtResource resources[] = { /* Table Widget Resources */ { XtNlayout, XtCLayout, XtRXpTableLoc, sizeof(XpTableLoc), TableOffset(default_layout), XtRString, (XtPointer) layout }, { XtNmarginWidth, XtCMargins, XtRInt, sizeof(int), TableOffset(margin_width), XtRImmediate, (XtPointer) 5 }, { XtNmarginHeight, XtCMargins, XtRInt, sizeof(int), TableOffset(margin_height), XtRImmediate, (XtPointer) 5 }, { XtNcolumnSpacing, XtCSpacing, XtRInt, sizeof(int), TableOffset(col_spacing), XtRImmediate, (XtPointer) 5 }, { XtNrowSpacing, XtCSpacing, XtRInt, sizeof(int), TableOffset(row_spacing), XtRImmediate, (XtPointer) 5 }, /* ControlCodeSelector Widget Resources */ {XtNbase, XtCBase, XtRInt, sizeof(int), Offset(base), XtRImmediate, (XtPointer) 8}, {XtNenterCallback, XtCCallback, XtRCallback, sizeof(XtCallbackList), Offset(enter_callbacks), XtRCallback, (XtPointer) NULL}, {XtNcancelCallback, XtCCallback, XtRCallback, sizeof(XtCallbackList), Offset(cancel_callbacks), XtRCallback, (XtPointer) NULL}, }; #undef Offset static char *ctrlCodes[] = {" NUL", "A - SOH", "B - STX", "C - ETX", "D - EOT", "E - ENQ", "F - ACK", "G - BEL", "H - BS ", "I - HT ", "J - NL ", "K - VT ", "L - NP ", "M - CR ", "N - SO ", "O - SI ", "P - DLE", "Q - DC1", "R - DC2", "S - DC3", "T - DC4", "U - NAK", "V - SYN", "W - ETB", "X - CAN", "Y - EM ", "Z - SUB", " ESC", " FS ", " GS ", " RS ", " US ", }; static char listTranslations[] = ": Set() Notify() Forward()"; static void ClassInitialize(), Initialize(); static Boolean SetValues(); static void LabelCodeWidget(), Selected(), Enter(), Cancel(), Forward(); static XtActionsRec actions[] = { "Forward", Forward, }; ControlCodeSelectorClassRec controlCodeSelectorClassRec = { { /* superclass */ (WidgetClass) &xpTableClassRec, /* class_name */ "ControlCodeSelector", /* size */ sizeof(ControlCodeSelectorRec), /* class_initialize */ ClassInitialize, /* class_part_initialize */ NULL, /* class_inited */ FALSE, /* initialize */ Initialize, /* initialize_hook */ NULL, /* realize */ XtInheritRealize, /* actions */ actions, /* num_actions */ XtNumber(actions), /* resources */ resources, /* resource_count */ XtNumber(resources), /* xrm_class */ NULLQUARK, /* compress_motion */ FALSE, /* compress_exposure */ TRUE, /* compress_enterleave */ TRUE, /* visible_interest */ FALSE, /* destroy */ NULL, /* resize */ XtInheritResize, /* expose */ XtInheritExpose, /* set_values */ SetValues, /* set_values_hook */ NULL, /* set_values_almost */ XtInheritSetValuesAlmost, /* get_values_hook */ NULL, /* accept_focus */ NULL, /* version */ XtVersion, /* callback_private */ NULL, /* tm_table */ XtInheritTranslations, /* query_geometry */ XtInheritQueryGeometry, /* display_accelerator */ XtInheritDisplayAccelerator, /* extension */ NULL },/* CoreClass fields initialization */ { /* composite class fields */ /* geometry_manager */ XtInheritGeometryManager, /* change_managed */ XtInheritChangeManaged, /* insert_child */ XtInheritInsertChild, /* delete_child */ XtInheritDeleteChild, /* extension */ NULL },/* CompositeClass fields initialization */ { /* extension */ NULL, },/* TableClass fields initialization */ { /* extension */ NULL, },/* ControlCodeSelectorClass fields initialization */ }; WidgetClass controlCodeSelectorWidgetClass = (WidgetClass) &controlCodeSelectorClassRec; static void ClassInitialize() { CLASS(listTranslations) = XtParseTranslationTable(listTranslations); } /* ARGSUSED */ static void Initialize(req, new, args, num_args) Widget req, new; ArgList args; Cardinal *num_args; { Widget list, enter, cancel; list = PRIVATE(new,list_widget) = XtVaCreateManagedWidget("list", listWidgetClass, new, XtNlist, ctrlCodes, XtNnumberStrings, XtNumber(ctrlCodes), NULL); XtOverrideTranslations(list, CLASS(listTranslations)); XtAddCallback(list, XtNcallback, Selected, (XtPointer) new); PRIVATE(new,code_widget) = XtVaCreateManagedWidget("code", labelWidgetClass, new, NULL); LabelCodeWidget(new); enter = XtVaCreateManagedWidget("enter", commandWidgetClass, new, NULL); XtAddCallback(enter, XtNcallback, Enter, (XtPointer) 0); cancel = XtVaCreateManagedWidget("cancel", commandWidgetClass, new, NULL); XtAddCallback(cancel, XtNcallback, Cancel, (XtPointer) 0); } /* ARGSUSED */ static Boolean SetValues(old, request, new, args, num_args) Widget old, request, new; ArgList args; Cardinal *num_args; { ControlCodeSelectorWidget oldccsw = (ControlCodeSelectorWidget) old; ControlCodeSelectorWidget newccsw = (ControlCodeSelectorWidget) new; XawListReturnStruct *list; int base; #define NE(field) (oldccsw->field != newccsw->field) if (NE(control.base)) { base = PRIVATE(new,base); if (base != 8 && base != 10 && base != 16) { PRIVATE(new,base) = 10; } list = XawListShowCurrent(PRIVATE(new,list_widget)); if (list->list_index != XAW_LIST_NONE) { Selected((XtPointer) 0, (XtPointer) new, (XtPointer) list); } else { LabelCodeWidget(new); } XtFree((char *) list); } #undef NE return False; } static void LabelCodeWidget(ctrl) ControlCodeSelectorWidget ctrl; { XtVaSetValues(PRIVATE(ctrl,code_widget), XtNlabel, " ", NULL); } static void Feed(widget) Widget widget; { Widget ctrl = XtParent(widget); XawListReturnStruct *selection = XawListShowCurrent(PRIVATE(ctrl,list_widget)); if (selection->list_index != XAW_LIST_NONE) { XtCallCallbackList(ctrl, PRIVATE(ctrl,enter_callbacks), (XtPointer) selection->list_index); } XtFree((char *) selection); } /* ARGSUSED */ static void Forward(widget, event, params, num_params) Widget widget; XEvent *event; String *params; Cardinal *num_params; { Feed(widget); } /* ARGSUSED */ static void Selected(widget, client_data, call_data) Widget widget; XtPointer client_data, call_data; { Widget ctrl = (Widget) client_data; XawListReturnStruct *selection = (XawListReturnStruct *) call_data; char based[4]; switch (PRIVATE(ctrl,base)) { case 8:sprintf(based, "%03o", selection->list_index); break; case 10: sprintf(based, "%d", selection->list_index); break; case 16: sprintf(based, "x%02x", selection->list_index); break; } XtVaSetValues(PRIVATE(ctrl,code_widget), XtNlabel, based, NULL); } /* ARGSUSED */ static void Enter(widget, client_data, call_data) Widget widget; XtPointer client_data, call_data; { Feed(widget); } /* ARGSUSED */ static void Cancel(widget, client_data, call_data) Widget widget; XtPointer client_data, call_data; { Widget ctrl = XtParent(widget); XtCallCallbackList(ctrl, PRIVATE(ctrl,cancel_callbacks), (XtPointer) 0); } /************************************************************* * * Public functions * *************************************************************/ void ControlCodeSelectorClear(ccsw) Widget ccsw; { if (!XtIsSubclass(ccsw, controlCodeSelectorWidgetClass)) { return; } XawListUnhighlight(PRIVATE(ccsw,list_widget)); LabelCodeWidget(ccsw); } #undef PRIVATE #undef CLASS axe-6.1.2.orig/Widgets/CtrlCodeSel.h100644 243 144 3635 5550557122 15725 0ustar joostusers/* * Copyright 1992 The University of Newcastle upon Tyne * * Permission to use, copy, modify and distribute this software and its * documentation for any purpose other than its commercial exploitation * is hereby granted without fee, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of The University of Newcastle upon Tyne not be used in * advertising or publicity pertaining to distribution of the software * without specific, written prior permission. The University of * Newcastle upon Tyne makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * THE UNIVERSITY OF NEWCASTLE UPON TYNE DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF * NEWCASTLE UPON TYNE BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. * * Author: Jim Wight (j.k.wight@newcastle.ac.uk) * Department of Computing Science * University of Newcastle upon Tyne, UK */ #ifndef _ControlCodeSelector_h #define _ControlCodeSelector_h #include extern WidgetClass controlCodeSelectorWidgetClass; typedef struct _ControlCodeSelectorClassRec *ControlCodeSelectorWidgetClass; typedef struct _ControlCodeSelectorRec *ControlCodeSelectorWidget; #define XtNbase "base" #define XtCBase "Base" #define XtNenterCallback "enterCallback" #define XtNcancelCallback "cancelCallback" #endif /* _ControlCodeSelector_h */ axe-6.1.2.orig/Widgets/CtrlCodeSelP.h100644 243 144 5130 5550557122 16035 0ustar joostusers/* * Copyright 1992 The University of Newcastle upon Tyne * * Permission to use, copy, modify and distribute this software and its * documentation for any purpose other than its commercial exploitation * is hereby granted without fee, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of The University of Newcastle upon Tyne not be used in * advertising or publicity pertaining to distribution of the software * without specific, written prior permission. The University of * Newcastle upon Tyne makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * THE UNIVERSITY OF NEWCASTLE UPON TYNE DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF * NEWCASTLE UPON TYNE BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. * * Author: Jim Wight (j.k.wight@newcastle.ac.uk) * Department of Computing Science * University of Newcastle upon Tyne, UK */ #ifndef _ControlCodeSelectorP_h #define _ControlCodeSelectorP_h #include #include typedef struct _ControlCodeSelectorClass { XtPointer extension; XtTranslations listTranslations; } ControlCodeSelectorClassPart; typedef struct _ControlCodeSelectorClassRec { CoreClassPart core_class; CompositeClassPart composite_class; XpTableClassPart table_class; ControlCodeSelectorClassPart control_code_selector_class; } ControlCodeSelectorClassRec; extern ControlCodeSelectorClassRec controlCodeSelectorClassRec; typedef struct _ControlCodeSelectorPart { /* resources */ int base; XtCallbackList enter_callbacks; XtCallbackList cancel_callbacks; /* private variables */ Widget list_widget; Widget code_widget; } ControlCodeSelectorPart; typedef struct _ControlCodeSelectorRec { CorePart core; CompositePart composite; XpTablePart table; ControlCodeSelectorPart control; } ControlCodeSelectorRec; #endif /* _ControlCodeSelectorP_h */ axe-6.1.2.orig/Widgets/FileNom.c100644 243 144 114667 5550557114 15157 0ustar joostusers/* * Copyright 1991, 1992, 1993 The University of Newcastle upon Tyne * * Permission to use, copy, modify and distribute this software and its * documentation for any purpose other than its commercial exploitation * is hereby granted without fee, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of The University of Newcastle upon Tyne not be used in * advertising or publicity pertaining to distribution of the software * without specific, written prior permission. The University of * Newcastle upon Tyne makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * THE UNIVERSITY OF NEWCASTLE UPON TYNE DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF * NEWCASTLE UPON TYNE BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. * * Author: Jim Wight (j.k.wight@newcastle.ac.uk) * Department of Computing Science * University of Newcastle upon Tyne, UK */ #include #include #include #include #include #include #include #include #include #include #include #include "tickMark.xbm" #if defined(XtSpecificationRelease) && XtSpecificationRelease > 4 #include #else #include #endif #include #include #include #include #include extern int errno; #include #include #ifdef NODIRENT #include #define dirent direct #else #include #endif #include extern char *getenv(); #include "FileNomP.h" #define Offset(field) XtOffsetOf(FileNominatorRec, fileNominator.field) static XtResource resources[] = { {XtNinitialDirectory, XtCInitialDirectory, XtRString, sizeof(String), Offset(initial_directory), XtRString, (XtPointer) NULL}, {XtNselectCallback, XtCCallback, XtRCallback, sizeof(XtCallbackList), Offset(select_callback), XtRCallback, (XtPointer) NULL}, {XtNpathList, XtCPathList, XtRString, sizeof(String), Offset(path_list), XtRString, (XtPointer) NULL}, {XtNcancelCallback, XtCCallback, XtRCallback, sizeof(XtCallbackList), Offset(cancel_callback), XtRCallback, (XtPointer) NULL}, {XtNmargin, XtCMargin, XtRDimension, sizeof(Dimension), Offset(margin), XtRImmediate, (XtPointer) 10}, {XtNnumberRows, XtCNumberStrings, XtRInt, sizeof(int), Offset(number_rows), XtRImmediate, (XtPointer) 12}, {XtNshowDotFiles, XtCShowDotFiles, XtRBoolean, sizeof(Boolean), Offset(show_dot_files), XtRImmediate, (XtPointer) True}, {XtNbellLevel, XtCBellLevel, XtRInt, sizeof(int), Offset(bell_level), XtRImmediate, (XtPointer) 100}, {XtNfilter, XtCFilter, XtRString, sizeof(String), Offset(filter), XtRImmediate, (XtPointer) "*"}, {XtNfilterDirectoryNames, XtCFilterDirectoryNames, XtRBoolean, sizeof(Boolean), Offset(filter_directory_names), XtRImmediate, (XtPointer) True}, {XtNuserData, XtCUserData, XtRPointer, sizeof(XtPointer), Offset(user_data), XtRPointer, (XtPointer) NULL}, }; #undef Offset #define PRIVATE(w,field) (((FileNominatorWidget) w)->fileNominator.field) #define CLASS(field) fileNominatorClassRec.fileNominator_class.field #ifdef __STDC__ #define Child(w,child) (((FileNominatorWidget) w)->fileNominator.child##_widget) #else #define Child(w,child) (((FileNominatorWidget) w)->fileNominator.child/**/_widget) #endif #define List(w) (((FileNominatorWidget) w)->fileNominator.listList) #define Rows(w) (((FileNominatorWidget) w)->fileNominator.number_rows) #define CurrentDir(w) (((FileNominatorWidget) w)->fileNominator.currentDir) #define WatchingChanges(w) (((FileNominatorWidget) w)->fileNominator.watchingChanges) #define Nomination(w) (((FileNominatorWidget) w)->fileNominator.nomination) #define ShowDotFiles(w) (((FileNominatorWidget) w)->fileNominator.show_dot_files) #define BellLevel(w) (((FileNominatorWidget) w)->fileNominator.bell_level) static char pathTranslations[] = ":reset() MakeMenu() XawPositionSimpleMenu(menu) MenuPopup(menu)"; static char listTranslations[] = "(2): Set() Nominate() Unset()\n\ ,: Set() Notify() \n\ : Set() Notify() Nominate() Unset()"; static char FilterTranslations[] = ": reset() MakeFilterMenu() PopupMenu()"; static char filterTranslations[] = ": FocusToFilter() \n\ : FocusToFilter(False) \n\ Return: Filter()"; static char filenameTranslations[] = "Return: Nominate() \n\ Escape: ToggleDotFiles()"; static char selectTranslations[] = ": Nominate() unset()"; static void MakeMenu(), FocusToFilter(), Filter(), MakeFilterMenu(), Nominate(); static void ToggleDotFiles(), ToggleFilterDirectories(), ScrollOnMove(); static XtActionsRec actions[] = { "scroll-on-movement", ScrollOnMove, }; static XtActionsRec pathActions[] = { "MakeMenu", MakeMenu, "FocusToFilter", FocusToFilter, "Filter", Filter, "MakeFilterMenu", MakeFilterMenu, "Nominate", Nominate, "ToggleDotFiles", ToggleDotFiles, "ToggleFilterDirectories", ToggleFilterDirectories, }; static void CancelCallback(); static void ChangeDir(); static void SelectDir(); static void FillWindow(); static void ReplaceFilename(); static void AsciiSourceChanged(); static void WatchForChanges(); static void DontWatchForChanges(); static void CollapsePath(); static void ClassInitialize(), Initialize(); static void PositionChildren(), Realize(), Destroy(); static Boolean SetValues(); FileNominatorClassRec fileNominatorClassRec = { /* Core class part */ { /* superclass */ (WidgetClass) &widgetClassRec, /* class_name */ "FileNominator", /* widget_size */ sizeof(FileNominatorRec), /* class_initialize */ ClassInitialize, /* class_part_initialize */ NULL, /* class_inited */ FALSE, /* initialize */ Initialize, /* initialize_hook */ NULL, /* realize */ Realize, /* actions */ actions, /* num_actions */ XtNumber(actions), /* resources */ resources, /* num_resources */ XtNumber(resources), /* xrm_class */ NULLQUARK, /* compress_motion */ TRUE, /* compress_exposure */ XtExposeCompressMultiple, /* compress_enterleave */ TRUE, /* visible_interest */ FALSE, /* destroy */ Destroy, /* resize */ PositionChildren, /* expose */ NULL, /* set_values */ SetValues, /* set_values_hook */ NULL, /* set_values_almost */ XtInheritSetValuesAlmost, /* get_values_hook */ NULL, /* accept_focus */ NULL, /* version */ XtVersion, /* callback offsets */ NULL, /* tm_table */ NULL, /* query_geometry */ XtInheritQueryGeometry, /* display_accelerator */ NULL, /* extension */ NULL, }, /* FileNominator class part */ { /* extension */ NULL, } }; WidgetClass fileNominatorWidgetClass = (WidgetClass) &fileNominatorClassRec; static void CalculateSize(fnw, width, height) FileNominatorWidget fnw; Dimension *width, *height; { Dimension max, wide, high; max = 0; wide = Child(fnw,Filter)->core.width + 2 * Child(fnw,Filter)->core.border_width + Child(fnw,filter)->core.width + 2 * Child(fnw,filter)->core.border_width + 3 *fnw->fileNominator.margin; if (wide > max) {max = wide;} wide = Child(fnw,text)->core.width + 2 * Child(fnw,filename)->core.border_width + 2 * fnw->fileNominator.margin; if (wide > max) {max = wide;} wide = Child(fnw,select)->core.width + 2 * Child(fnw,select)->core.border_width + Child(fnw,path)->core.width + 2 * Child(fnw,path)->core.border_width + Child(fnw,cancel)->core.width + 2 * Child(fnw,cancel)->core.border_width + 4 * fnw->fileNominator.margin; if (wide > max) {max = wide;} *width = max; *height = 0; max = 0; high = Child(fnw,Filter)->core.height + 2 * Child(fnw,Filter)->core.border_width; if (high > max) {max = high;}; high = Child(fnw,filter)->core.height + 2 * Child(fnw,filter)->core.border_width; if (high > max) {max = high;}; *height += max; max = 0; high = Child(fnw,select)->core.height + 2 * Child(fnw,select)->core.border_width; if (high > max) {max = high;}; high = Child(fnw,path)->core.height + 2 * Child(fnw,path)->core.border_width; if (high > max) {max = high;}; high = Child(fnw,cancel)->core.height + 2 * Child(fnw,cancel)->core.border_width; if (high > max) {max = high;}; *height += max; *height += Child(fnw,viewport)->core.height + Child(fnw,text)->core.height + 2 * (Child(fnw,viewport)->core.border_width + Child(fnw,filename)->core.border_width) + 5 * fnw->fileNominator.margin; } static void PositionChildren(fnw) FileNominatorWidget fnw; { XtConfigureWidget(Child(fnw,viewport), fnw->fileNominator.margin, fnw->fileNominator.margin, fnw->core.width - 2 * fnw->fileNominator.margin - 2 * Child(fnw,viewport)->core.border_width, fnw->core.height - 2 * Child(fnw,viewport)->core.border_width - Child(fnw,filter)->core.height - 2 * Child(fnw,filter)->core.border_width - Child(fnw,text)->core.height - 2 * Child(fnw,filename)->core.border_width - Child(fnw,select)->core.height - 2 * Child(fnw,select)->core.border_width - 5 * fnw->fileNominator.margin, Child(fnw,viewport)->core.border_width); XtConfigureWidget(Child(fnw,Filter), fnw->fileNominator.margin, fnw->core.height - Child(fnw,select)->core.height - 2 * Child(fnw,select)->core.border_width - Child(fnw,text)->core.height - 2 * Child(fnw,filename)->core.border_width - Child(fnw,Filter)->core.height - 2 * Child(fnw,Filter)->core.border_width - 3 * fnw->fileNominator.margin, Child(fnw,Filter)->core.width, Child(fnw,Filter)->core.height, Child(fnw,Filter)->core.border_width); XtConfigureWidget(Child(fnw,filter), 2 * fnw->fileNominator.margin + Child(fnw,Filter)->core.width + 2 * Child(fnw,Filter)->core.border_width, fnw->core.height - Child(fnw,select)->core.height - 2 * Child(fnw,select)->core.border_width - Child(fnw,text)->core.height - 2 * Child(fnw,filename)->core.border_width - Child(fnw,filter)->core.height - 2 * Child(fnw,filter)->core.border_width - 3 * fnw->fileNominator.margin, fnw->core.width - 3 * fnw->fileNominator.margin - Child(fnw,Filter)->core.width - 2 * Child(fnw,Filter)->core.border_width - 2 * Child(fnw,filter)->core.border_width, Child(fnw,filter)->core.height, Child(fnw,filter)->core.border_width); XtConfigureWidget(Child(fnw,filename), fnw->fileNominator.margin, fnw->core.height - Child(fnw,select)->core.height - 2 * Child(fnw,select)->core.border_width - Child(fnw,text)->core.height - 2 * Child(fnw,filename)->core.border_width - 2 * fnw->fileNominator.margin, fnw->core.width - 2 * fnw->fileNominator.margin - 2 * Child(fnw,filename)->core.border_width, Child(fnw,text)->core.height, Child(fnw,filename)->core.border_width); XtMoveWidget(Child(fnw,select), fnw->fileNominator.margin, fnw->core.height - fnw->fileNominator.margin - 2 * Child(fnw,select)->core.border_width - Child(fnw,select)->core.height); XtMoveWidget(Child(fnw,path), Child(fnw,select)->core.width + 2 * Child(fnw,select)->core.border_width + 2 * fnw->fileNominator.margin, fnw->core.height - fnw->fileNominator.margin - 2 * Child(fnw,select)->core.border_width - Child(fnw,select)->core.height); XtMoveWidget(Child(fnw,cancel), Child(fnw,path)->core.width + 2 * Child(fnw,path)->core.border_width + Child(fnw,select)->core.width + 2 * Child(fnw,select)->core.border_width + 3 * fnw->fileNominator.margin, fnw->core.height - fnw->fileNominator.margin - 2 * Child(fnw,select)->core.border_width - Child(fnw,select)->core.height); } static void ClassInitialize() { CLASS(pathTranslations) = XtParseTranslationTable(pathTranslations); CLASS(listTranslations) = XtParseTranslationTable(listTranslations); CLASS(FilterTranslations) = XtParseTranslationTable(FilterTranslations); CLASS(filterTranslations) = XtParseTranslationTable(filterTranslations); CLASS(filenameTranslations) = XtParseTranslationTable(filenameTranslations); CLASS(selectTranslations) = XtParseTranslationTable(selectTranslations); } /* ARGSUSED */ static void Initialize(req, new, args, num_args) Widget req, new; ArgList args; Cardinal *num_args; { FileNominatorWidget fnw = (FileNominatorWidget) new; struct stat fstats; int status; String dir; Dimension width, height; #if defined(SYSV) || defined(SVR4) extern char *getcwd(); #define getwd(buf) getcwd(buf,MAXPATHLEN) #else extern char *getwd(); #endif List(new) = NULL; Nomination(new).directoryPart = NULL; Nomination(new).filenamePart = NULL; *(CurrentDir(new)) = '\0'; if (PRIVATE(new,initial_directory)) { status = stat(PRIVATE(new,initial_directory), &fstats); if (status != -1 && (fstats.st_mode & S_IFDIR) && access(PRIVATE(new,initial_directory), R_OK) == 0) { strcpy(CurrentDir(new), PRIVATE(new,initial_directory)); } } if (!(*(CurrentDir(new)))) { if (!getwd(CurrentDir(new))) { if ( (dir = getenv("HOME")) ) { strcpy(CurrentDir(new), dir); } else { strcpy(CurrentDir(new), "/"); } } } if (CurrentDir(new)[strlen(CurrentDir(new)) - 1] != '/') { strcat(CurrentDir(new), "/"); } WatchingChanges(new) = False; #if defined(XtSpecificationRelease) && XtSpecificationRelease > 4 Child(fnw,viewport) = XtVaCreateWidget("viewport", viewlistWidgetClass, new, XtNallowVert, True, NULL); XtVaGetValues(Child(fnw,viewport), XtNlistWidget, &(Child(fnw,list)), NULL); #else /* * I haven't a clue why the layout is messed up when a Viewlist is used * instead of a Viewport, and I haven't time to spend investigating it, so * those still at R4 will have to continue to put with the old undesirable * redrawing behaviour that the Viewlist widget improves upon. */ Child(fnw,viewport) = XtVaCreateWidget("list", viewportWidgetClass, new, XtNallowVert, True, NULL); Child(fnw,list) = XtVaCreateManagedWidget("list", listWidgetClass, Child(fnw,viewport), NULL); #endif XtVaSetValues(Child(fnw,list), XtNdefaultColumns, 1, XtNforceColumns, True, NULL); XtOverrideTranslations(Child(fnw,list), CLASS(listTranslations)); XtAddCallback(Child(fnw,list), XtNcallback, ReplaceFilename, NULL); Child(fnw,Filter) = XtVaCreateWidget("Filter", menuButtonWidgetClass, new, NULL); XtOverrideTranslations(Child(fnw,Filter),CLASS(FilterTranslations)); PRIVATE(fnw,filter_menu) = (Widget) 0; Child(fnw,filter) = XtVaCreateWidget("filter", scrollingTextWidgetClass, new, NULL); { Widget text; XtVaGetValues(Child(fnw,filter), XtNtextWidget, &text, NULL); XtVaSetValues(text, XtNeditType, XawtextEdit, XtNstring, PRIVATE(new,filter), XtNdisplayCaret, False, NULL); XtOverrideTranslations(text, CLASS(filterTranslations)); } Child(fnw,filename) = XtVaCreateWidget("filename", scrollingTextWidgetClass, new, NULL); { Widget text; XtVaGetValues(Child(fnw,filename), XtNtextWidget, &text, NULL); XtVaSetValues(text, XtNeditType, XawtextEdit, NULL); Child(fnw,text) = text; } XtOverrideTranslations(Child(fnw,text), CLASS(filenameTranslations)); XtSetKeyboardFocus(new, Child(fnw,text)); WatchForChanges(fnw); Child(fnw,select) = XtVaCreateWidget("select", commandWidgetClass, new, NULL); XtOverrideTranslations(Child(fnw,select), CLASS(selectTranslations)); Child(fnw,path) = XtVaCreateWidget("path", menuButtonWidgetClass, new, NULL); XtOverrideTranslations(Child(fnw,path), CLASS(pathTranslations)); XtAppAddActions(XtWidgetToApplicationContext(new), pathActions, XtNumber(pathActions)); XawSimpleMenuAddGlobalActions(XtWidgetToApplicationContext(new)); Child(fnw,cancel) = XtVaCreateWidget("cancel", commandWidgetClass, new, NULL); XtAddCallback(Child(fnw,cancel), XtNcallback, CancelCallback, NULL); FillWindow(fnw); CalculateSize(fnw, &width, &height); fnw->core.width = fnw->core.width ? fnw->core.width : width; fnw->core.height = fnw->core.height ? fnw->core.height : height; PositionChildren(fnw); } static void Realize(w, valueMask, attributes) Widget w; XtValueMask *valueMask; XSetWindowAttributes *attributes; { (*fileNominatorWidgetClass->core_class.superclass->core_class.realize) (w, valueMask, attributes); XtRealizeWidget(Child(w,viewport)); XtRealizeWidget(Child(w,Filter)); XtRealizeWidget(Child(w,filter)); XtRealizeWidget(Child(w,filename)); XtRealizeWidget(Child(w,select)); XtRealizeWidget(Child(w,path)); XtRealizeWidget(Child(w,cancel)); XMapSubwindows(XtDisplay(w), XtWindow(w)); } static void Destroy(w) Widget w; { int idx; FileNominatorWidget fnw = (FileNominatorWidget) w; XtSetKeyboardFocus(w, (Widget) 0); XtDestroyWidget(Child(fnw,viewport)); XtDestroyWidget(Child(fnw,Filter)); XtDestroyWidget(Child(fnw,filter)); XtDestroyWidget(Child(fnw,filename)); XtDestroyWidget(Child(fnw,select)); XtDestroyWidget(Child(fnw,path)); XtDestroyWidget(Child(fnw,cancel)); idx = 0; while (List(fnw)[idx]) { XtFree((char *) List(fnw)[idx++]); } XtFree((char *) List(fnw)[idx]); XtFree((char *) List(fnw)); XtFree(Nomination(fnw).directoryPart); XtFree(Nomination(fnw).filenamePart); } /* ARGSUSED */ static Boolean SetValues(old, request, new, args, num_args) Widget old, request, new; ArgList args; Cardinal *num_args; { FileNominatorWidget oldfnw = (FileNominatorWidget) old; FileNominatorWidget newfnw = (FileNominatorWidget) new; Widget filter; Boolean redisplay = False, refilter = False; #define NE(field) (oldfnw->field != newfnw->field) XtVaGetValues(Child(new,filter), XtNtextWidget, &filter, NULL); if (NE(fileNominator.filter)) { XtVaSetValues(filter, XtNstring, PRIVATE(new,filter), NULL); refilter = True; } if (NE(fileNominator.filter_directory_names) && PRIVATE(new,filter_menu)) { XtVaSetValues(PRIVATE(new,apply_dirs), XtNleftBitmap, PRIVATE(new,filter_directory_names) ? CLASS(tickMark) : (Pixmap) 0, NULL); refilter = True; } if (NE(fileNominator.show_dot_files)) { if(PRIVATE(new,filter_menu)) { XtVaSetValues(PRIVATE(new,apply_dots), XtNleftBitmap, PRIVATE(new,show_dot_files) ? CLASS(tickMark) : (Pixmap) 0, NULL); } refilter = True; } /* * This doesn't work yet; the list grows in width as margin is changed * if (NE(fileNominator.margin)) { CalculateSize(new, &(new->core.width), &(new->core.height)); PositionChildren(new); redisplay = True; } */ #undef NE if (refilter) { Filter(filter, (XEvent *) 0, (String *) 0, (Cardinal *) 0); } return redisplay; } /* ARGSUSED */ static void ScrollOnMove(widget, event, params, num_params) Widget widget; XEvent *event; String *params; Cardinal *num_params; { XtVaSetValues(Child(widget,filename), XtNscrollOnMovement, *params[0] == 'T' ? True : False, NULL); XtVaSetValues(Child(widget,filter), XtNscrollOnMovement, *params[0] == 'T' ? True : False, NULL); } /* ARGSUSED */ static void CancelCallback(w, client_data, call_data) Widget w; XtPointer client_data, call_data; { XtCallCallbacks(XtParent(w), XtNcancelCallback, NULL); } /* ARGSUSED */ static void MenuFilter(w, client_data, call_data) Widget w; XtPointer client_data, call_data; { Widget fnw; if (!client_data) { return; } for (fnw = XtParent(w); !XtIsSubclass(fnw, fileNominatorWidgetClass); fnw = XtParent(fnw)) ; XtCallActionProc(Child(fnw,Filter), (String) client_data, (XEvent *) 0, (String *) 0, (Cardinal) 0); } /* ARGSUSED */ static void MakeFilterMenu(w, event, params, num_params) Widget w; XEvent *event; String *params; Cardinal *num_params; { FileNominatorWidget fnw = (FileNominatorWidget) XtParent(w); String menuName; Widget menu, menuEntry; if (PRIVATE(fnw,filter_menu)) { return; } if (!CLASS(tickMark)) { Display *display = XtDisplay(w); CLASS(tickMark) = XCreateBitmapFromData(display, XDefaultRootWindow(display), (char *) tickMark_bits, tickMark_width, tickMark_height); } XtVaGetValues(w, XtNmenuName, &menuName, NULL); menu = XtVaCreatePopupShell(menuName,simpleMenuWidgetClass, w, NULL); menuEntry = XtVaCreateManagedWidget("Apply", smeBSBObjectClass, menu, XtNleftMargin, 16, XtNrightMargin, 16, NULL); XtAddCallback(menuEntry, XtNcallback, MenuFilter, (XtPointer) "Filter"); XtVaCreateManagedWidget("line", smeLineObjectClass, menu, NULL); menuEntry = PRIVATE(fnw,apply_dirs) = XtVaCreateManagedWidget("Apply to directories", smeBSBObjectClass, menu, XtNleftMargin, 16, XtNrightMargin, 16, XtNleftBitmap, PRIVATE(fnw,filter_directory_names) ? CLASS(tickMark) : (Pixmap) 0, NULL); XtAddCallback(menuEntry, XtNcallback, MenuFilter, (XtPointer) "ToggleFilterDirectories"); menuEntry = PRIVATE(fnw,apply_dots) = XtVaCreateManagedWidget("Apply to \".\" files", smeBSBObjectClass, menu, XtNleftMargin, 16, XtNrightMargin, 16, XtNleftBitmap, PRIVATE(fnw,show_dot_files) ? CLASS(tickMark) : (Pixmap) 0, NULL); XtAddCallback(menuEntry, XtNcallback, MenuFilter, (XtPointer) "ToggleDotFiles"); PRIVATE(fnw,filter_menu) = menu; } /* ARGSUSED */ static void DestroyMenu(w, client_data, call_data) Widget w; XtPointer client_data, call_data; { XtDestroyWidget(w); } /* ARGSUSED */ static void MakeMenu(w, event, params, num_params) Widget w; XEvent *event; String *params; Cardinal *num_params; { FileNominatorWidget fnw = (FileNominatorWidget) XtParent(w); String menuName, menuList; Widget menu, menuEntry; char *where, *p1, *p2, *p, *q, *TopLevelDir; int menuItem = 1, len; XtVaGetValues(w, XtNmenuName, &menuName, NULL); menu = XtVaCreatePopupShell(menuName, simpleMenuWidgetClass, w, NULL); XtAddCallback(menu, XtNpopdownCallback, DestroyMenu, NULL); where = XtNewString(CurrentDir(fnw)); #ifdef __apollo if (strncmp (where, "//", 2) == 0) { p1 = where + 2; /* leading // on pathname, if there */ TopLevelDir = "//"; } else { p1 = where + 1; /* else skip the single leading slash */ TopLevelDir = "/"; } #else p1 = where + 1; TopLevelDir = "/"; #endif menuEntry = XtVaCreateManagedWidget(TopLevelDir, smeBSBObjectClass, menu, NULL); XtAddCallback(menuEntry, XtNcallback, ChangeDir, (XtPointer) menuItem++); len = strlen(where); while (p1 < &where[len]) { if (!(p2 = index(p1, '/'))) { p2 = &where[len]; } *p2 = '\0'; menuEntry = XtVaCreateManagedWidget(p1, smeBSBObjectClass, menu, NULL); XtAddCallback(menuEntry, XtNcallback, ChangeDir, (XtPointer) menuItem++); p1 = p2 + 1; } if (!fnw->fileNominator.path_list) { XtVaSetValues(menu, XtNpopupOnEntry, menuEntry, NULL); } else { menuEntry = XtVaCreateManagedWidget("sep", smeLineObjectClass, menu, NULL); XtVaSetValues(menu, XtNpopupOnEntry, menuEntry, NULL); menuList = XtNewString(fnw->fileNominator.path_list); for (p = menuList; (q = index(p, ':')); p = q + 1) { *q = '\0'; menuEntry = XtVaCreateManagedWidget(p, smeBSBObjectClass, menu, NULL); XtAddCallback(menuEntry, XtNcallback, SelectDir, NULL); } menuEntry = XtVaCreateManagedWidget(p, smeBSBObjectClass, menu, NULL); XtAddCallback(menuEntry, XtNcallback, SelectDir, NULL); XtFree(menuList); } XtFree(where); } static void ChangeDirectory(fnw, position) FileNominatorWidget fnw; int position; { String p; int m; if (position > 0) { p = CurrentDir(fnw); #ifdef __apollo /* skip first slash, if there of //nodename so we get the right dir */ if (strncmp (p, "//", 2) == 0) p++; #endif for (m = 0; m < position; ++m) { while(*p++ != '/') ; } *p = '\0'; } XtVaSetValues(Child(fnw, text), XtNstring, "", NULL); FillWindow(fnw); PositionChildren(fnw); } /* ARGSUSED */ static void ChangeDir(w, client_data, call_data) Widget w; XtPointer client_data, call_data; { FileNominatorWidget fnw = (FileNominatorWidget) XtParent(XtParent(XtParent(w))); ChangeDirectory(fnw, (int) client_data); } /* ARGSUSED */ static void SelectDir(w, client_data, call_data) Widget w; XtPointer client_data, call_data; { FileNominatorWidget fnw = (FileNominatorWidget) XtParent(XtParent(XtParent(w))); String label; XtVaGetValues(w, XtNlabel, &label, NULL); XtVaSetValues(Child(fnw,text), XtNstring, label, NULL); Nominate(Child(fnw,select), NULL, NULL, NULL); } static char* GetEnv(name) char *name; { char *r, *env, *e; env = XtNewString(name); if ((r = index(env, '/'))) { *r = '\0'; } e = getenv(env); XtFree(env); return e; } static char* GetUser(name) char *name; { char *i, *user, *u; struct passwd *gotUser; user = XtNewString(name); if ((i = index(user, '/'))) { *i = '\0'; } if ((gotUser = getpwnam(user))) { u = gotUser->pw_dir; } else { u = (char *) 0; } XtFree(user); return u; } /* ARGSUSED */ static void Nominate(w, event, params, num_params) Widget w; XEvent *event; String *params; Cardinal *num_params; { Widget fnw; char *nomination, *home, *user, *envVar, selection[MAXPATHLEN], *newPath, *r; struct stat fstats; int status, len; for (fnw = XtParent(w); !XtIsSubclass(fnw, fileNominatorWidgetClass); fnw = XtParent(fnw)) ; XtVaGetValues(Child(fnw,text), XtNstring, &nomination, NULL); selection[0] = '\0'; if (*nomination == '/') { strcpy(selection, nomination); } else if (*nomination == '~') { if ((*(nomination + 1) == '/' || *(nomination + 1) == '\0') && (home = getenv("HOME"))) { strcpy(selection, home); strcat(selection, &nomination[1]); } else if ((user = GetUser(&nomination[1]))) { strcpy(selection, user); if ((r = index(&nomination[1], '/'))) { strcat(selection, r); } } } else if (*nomination == '$' && (envVar = GetEnv(&nomination[1]))) { strcpy(selection, envVar); if ((r = index(&nomination[1], '/'))) { strcat(selection, r); } } #ifdef __apollo else if (*nomination == '`' && (strncmp("`node_data", nomination, 10) == 0)) { strcat(selection, nomination); } #endif if (strlen(selection) == 0) { if (strlen(CurrentDir(fnw)) > 1) { strcpy(selection, CurrentDir(fnw)); } strcat(selection, "/"); strcat(selection, nomination); } len = strlen(selection); if (len != 0) { newPath = (char *) XtMalloc(len + 2); CollapsePath(selection, newPath); status = stat(newPath, &fstats); if (status != -1 && fstats.st_mode & S_IFDIR) { if (access(newPath, R_OK) == 0) { if (newPath[strlen(newPath) - 1] != '/') { strcat(newPath, "/"); } strcpy(CurrentDir(fnw), newPath); ChangeDirectory(fnw, 0); } else { XBell(XtDisplay(fnw), BellLevel(fnw)); } } else if (status == 0 || (status == -1 && errno == ENOENT)) { r = rindex(newPath, '/'); XtFree(Nomination(fnw).filenamePart); Nomination(fnw).filenamePart = XtNewString(r + 1); if (status == 0) { status |= (access(newPath, R_OK) == 0) ? FileNominatorReadable : 0; status |= (access(newPath, W_OK) == 0) ? FileNominatorWritable : 0; status |= (access(newPath, X_OK) == 0) ? FileNominatorExecutable : 0; } else { status = FileNominatorNonexistent; } Nomination(fnw).filenameStatus = status; *(r + 1) = '\0'; XtFree(Nomination(fnw).directoryPart); status = 0; status |= (access(newPath, R_OK) == 0) ? FileNominatorReadable : 0; status |= (access(newPath, W_OK) == 0) ? FileNominatorWritable : 0; status |= (access(newPath, X_OK) == 0) ? FileNominatorExecutable : 0; if (strcmp(newPath, CurrentDir(fnw)) != 0 && (status & FileNominatorReadable)) { strcpy(CurrentDir(fnw), newPath); ChangeDirectory(fnw, 0); Nomination(fnw).directoryPart = XtNewString(CurrentDir(fnw)); } else { Nomination(fnw).directoryPart = XtNewString(newPath); } Nomination(fnw).directoryStatus = status; XtCallCallbacks((Widget) fnw, XtNselectCallback, (XtPointer) &Nomination(fnw)); } else { XBell(XtDisplay(fnw), BellLevel(fnw)); } XtFree(newPath); } } static void FillWindow(fnw) Widget fnw; { XFontStruct *font; Dimension height, internalHeight, rowSpacing; int num, newNum, idx; struct dirent **namelist; extern int alphasort(); char buf[MAXPATHLEN], *bp; String name; struct stat fstats; Widget text, vscroller; float top = 0.0; String p, m, empty = "*"; int i; extern Boolean match(); XtVaGetValues(Child(fnw,filter), XtNtextWidget, &text, NULL); XtVaGetValues(text, XtNstring, &p, NULL); if (!*p) { p = empty; } m = XtNewString(p); for(i=0; p[i]; ++i) { switch (p[i]) { case '?': case '*': case '[': m[i] = 1; break; default: m[i] = 0; } } num = scandir(CurrentDir(fnw), &namelist, (int(*)())0, alphasort); if (num <= 0) { return; } if (List(fnw)) { idx = 0; while (List(fnw)[idx]) { XtFree((char *) List(fnw)[idx++]); } XtFree((char *) List(fnw)[idx]); XtFree((char *) List(fnw)); } List(fnw) = (String *) XtMalloc((num + 1) * sizeof(String)); strcpy(buf, CurrentDir(fnw)); bp = buf + strlen(buf); for(idx = 0, newNum = 0; idx < num; idx++) { name = namelist[idx]->d_name; if (ShowDotFiles(fnw) || (!ShowDotFiles(fnw) && (*name != '.' || ((strcmp(name, ".") == 0) || (strcmp(name, "..") == 0))))) { if (match(p, m, name)) { List(fnw)[newNum] = XtMalloc(strlen(name) + 2); strcpy(List(fnw)[newNum], name); strcpy(bp, name); (void) stat(buf, &fstats); if (fstats.st_mode & S_IFDIR) { strcat(List(fnw)[newNum], "/"); } ++newNum; } else if (!PRIVATE(fnw,filter_directory_names)) { strcpy(bp, name); (void) stat(buf, &fstats); if (fstats.st_mode & S_IFDIR) { List(fnw)[newNum] = XtMalloc(strlen(name) + 2); strcpy(List(fnw)[newNum], name); strcat(List(fnw)[newNum], "/"); ++newNum; } } } } for(idx = 0; idx < num; idx++) { XtFree((char *) namelist[idx]); } XtFree((char *) namelist); XtFree(m); List(fnw)[newNum] = NULL; XtVaGetValues(Child(fnw,list), XtNfont, &font, XtNinternalHeight, &internalHeight, XtNrowSpacing, &rowSpacing, NULL); height = Rows(fnw) * (font->max_bounds.ascent + font->max_bounds.descent + rowSpacing) - rowSpacing + 2 * internalHeight; XtVaSetValues(Child(fnw,viewport), XtNheight, height, NULL); XawListChange(Child(fnw,list), List(fnw), newNum, -1, True); if (XtIsRealized(Child(fnw,viewport))) { #if defined(XtSpecificationRelease) && XtSpecificationRelease > 4 XawViewportSetLocation(Child(fnw,viewport), 0.0, 0.0); #else /* Kludge to force scroll to top of new list */ if ((vscroller = XtNameToWidget(Child(fnw,viewport), "vertical"))) { XtCallCallbacks(vscroller, XtNjumpProc, (XtPointer) &top); } #endif } } /* ARGSUSED */ static void FocusToFilter(w, event, params, num_params) Widget w; XEvent *event; String *params; Cardinal *num_params; { Boolean on = (*num_params == 0); Widget fnw = XtParent(w); while (!XtIsSubclass(fnw, fileNominatorWidgetClass)) { fnw = XtParent(fnw); } XtSetKeyboardFocus(fnw, on ? (Widget) 0 : Child(fnw,text)); XtVaSetValues(w, XtNdisplayCaret, on, NULL); XtVaSetValues(Child(fnw,text), XtNdisplayCaret, !on, NULL); } /* ARGSUSED */ static void Filter(w, event, params, num_params) Widget w; XEvent *event; String *params; Cardinal *num_params; { Widget fnw = XtParent(w); while (!XtIsSubclass(fnw, fileNominatorWidgetClass)) { fnw = XtParent(fnw); } FillWindow(fnw); PositionChildren(fnw); } /* ARGSUSED */ static void ToggleFilterDirectories(w, event, params, num_params) Widget w; XEvent *event; String *params; Cardinal *num_params; { Boolean filterDirs; Widget fnw = XtParent(w); while (!XtIsSubclass(fnw, fileNominatorWidgetClass)) { fnw = XtParent(fnw); } XtVaGetValues(fnw, XtNfilterDirectoryNames, &filterDirs, NULL); XtVaSetValues(fnw, XtNfilterDirectoryNames, !filterDirs, NULL); } /* ARGSUSED */ static void ToggleDotFiles(w, event, params, num_params) Widget w; XEvent *event; String *params; Cardinal *num_params; { Boolean showDotFiles; Widget fnw = XtParent(w); while (!XtIsSubclass(fnw, fileNominatorWidgetClass)) { fnw = XtParent(fnw); } XtVaGetValues(fnw, XtNshowDotFiles, &showDotFiles, NULL); XtVaSetValues(fnw, XtNshowDotFiles, !showDotFiles, NULL); } /* ARGSUSED */ static void ReplaceFilename(w, client_data, call_data) Widget w; XtPointer client_data, call_data; { FileNominatorWidget fnw = (FileNominatorWidget) XtParent(XtParent(w)); XawListReturnStruct *list = XawListShowCurrent(Child(fnw,list)); XtVaSetValues(Child(fnw,text), XtNstring, list->string, NULL); XawTextSetInsertionPoint(Child(fnw,text), (XawTextPosition) strlen(list->string)); XtFree((char *) list); WatchForChanges(fnw); } /* ARGSUSED */ static void AsciiSourceChanged(w, client_data, call_data) Widget w; XtPointer client_data, call_data; { FileNominatorWidget fnw = (FileNominatorWidget) client_data; DontWatchForChanges(fnw); XawListUnhighlight(Child(fnw,list)); } static void WatchForChanges(fnw) Widget fnw; { if (!WatchingChanges(fnw)) { XtAddCallback(XawTextGetSource(Child(fnw,text)), XtNcallback, AsciiSourceChanged, (XtPointer) fnw); WatchingChanges(fnw) = True; } } static void DontWatchForChanges(fnw) Widget fnw; { XtRemoveCallback(XawTextGetSource(Child(fnw,text)), XtNcallback, AsciiSourceChanged, (XtPointer) fnw); WatchingChanges(fnw) = False; } static void CollapsePath(in, out) char *in, *out; { char *p = in, *q = out, *pend = p + strlen(p); #ifdef __apollo int m = 0; #endif while (p < pend) { if (*p != '/') { *q++ = *p++; } else if (p + 1 < pend && *(p + 1) == '/') { #ifdef __apollo if (m == 0) /* copy the // at the beginning of an apollo path */ *q++ = *p++; else #endif ++p; } else if ( (p + 2 == pend && *(p + 1) == '.') || (p + 2 < pend && *(p + 1) == '.' && *(p + 2) == '/') ) { p += 2; } else if ( (p + 3 == pend && *(p + 1) == '.' && *(p + 2) == '.') || (p + 3 < pend && *(p + 1) == '.' && *(p + 2) == '.' && *(p + 3) == '/') ) { while (q > out && *--q != '/') ; p += 3; } else { *q++ = *p++; } #ifdef __apollo m++; #endif } if (q == out) { *q++ = '/'; } while (q > out) { if (*--q != '/') break; } *++q = '\0'; } String FileNominatorGetDirectory(fnw) Widget fnw; { if (XtIsSubclass(fnw, fileNominatorWidgetClass)) { return CurrentDir(fnw); } else { return NULL; } } void FileNominatorSetDirectory(fnw, dir) Widget fnw; String dir; { if (!XtIsSubclass(fnw, fileNominatorWidgetClass)) { return; } /* Should do more checks */ strcpy(CurrentDir(fnw), dir); if (dir[strlen(dir) - 1] != '/') { strcat(CurrentDir(fnw), "/"); } ChangeDirectory(fnw, 0); } void FileNominatorClearName(widget) Widget(widget); { if (!XtIsSubclass(widget, fileNominatorWidgetClass)) { return; } XtVaSetValues(Child(widget,text), XtNstring, "", NULL); XawListUnhighlight(Child(widget,list)); } Widget FileNominatorViewportWidget(widget) Widget(widget); { if (XtIsSubclass(widget, fileNominatorWidgetClass)) { return Child(widget,viewport); } else { return (Widget) 0; } } Widget FileNominatorListWidget(widget) Widget(widget); { if (XtIsSubclass(widget, fileNominatorWidgetClass)) { return Child(widget,list); } else { return (Widget) 0; } } #undef CLASS axe-6.1.2.orig/Widgets/FileNom.h100644 243 144 5356 5550557122 15115 0ustar joostusers/* * Copyright 1991, 1993 The University of Newcastle upon Tyne * * Permission to use, copy, modify and distribute this software and its * documentation for any purpose other than its commercial exploitation * is hereby granted without fee, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of The University of Newcastle upon Tyne not be used in * advertising or publicity pertaining to distribution of the software * without specific, written prior permission. The University of * Newcastle upon Tyne makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * THE UNIVERSITY OF NEWCASTLE UPON TYNE DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF * NEWCASTLE UPON TYNE BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. * * Author: Jim Wight (j.k.wight@newcastle.ac.uk) * Department of Computing Science * University of Newcastle upon Tyne, UK */ #ifndef FileNominator_h #define FileNominator_h #define XtNinitialDirectory "initialDirectory" #define XtNselectCallback "selectCallback" #define XtNpathList "pathList" #define XtNcancelCallback "cancelCallback" #define XtNmargin "margin" #define XtNnumberRows "numberRows" #define XtNshowDotFiles "showDotFiles" #define XtNbellLevel "bellLevel" #define XtNfilter "filter" #define XtNfilterDirectoryNames "filterDirectoryNames" #define XtNuserData "userData" #define XtCInitialDirectory "InitialDirectory" #define XtCPathList "PathList" #define XtCShowDotFiles "ShowDotFiles" #define XtCBellLevel "BellLevel" #define XtCFilter "Filter" #define XtCFilterDirectoryNames "FilterDirectoryNames" #define XtCUserData "UserData" extern WidgetClass fileNominatorWidgetClass; typedef struct _FileNominatorRec *FileNominatorWidget; typedef struct { String directoryPart; int directoryStatus; String filenamePart; int filenameStatus; } FileNominatorStruct; #define FileNominatorNonexistent 8 #define FileNominatorReadable 4 #define FileNominatorWritable 2 #define FileNominatorExecutable 1 String FileNominatorGetDirectory(); void FileNominatorSetDirectory(); void FileNominatorClearName(); Widget FileNominatorViewportWidget(); Widget FileNominatorListWidget(); #endif /* FileNominator_h */ axe-6.1.2.orig/Widgets/FileNom.man100644 243 144 17573 5550557116 15470 0ustar joostusers'\" t .TH "FileNominator" "3n" .SH NAME FileNominator \- A file selector widget .SH DESCRIPTION .LP Application header file .br Class header file .br Class fileNominatorWidgetClass .br Class Name FileNominator .br Superclass Core .LP The FileNominator widget is a directory browser and file selector. It consists of a scrollable list (List widget [instance name = list] inside a Viewlist [R5] or Viewport [R4] widget [viewport]) of directory entries, a button (Command widget) [Filter:], two one-line input areas (ScrollingText widget [filter], and ScrollingText widget [filename]), and three buttons: a Command button [select] for selecting the nominated file or directory, a MenuButton button [path] whose defualt menu contains the elements of the path of the directory whose contents are displayed in the List widget and a Command button [cancel] for cancelling use of the widget. .LP The user may nominate a file by choosing from the list using mouse button 1 (causing the name to be entered into the filename input area), or by typing into the input area, or by doing both. All keyboard input is directed to the filename widget when the FileNominator has the input focus, unless the pointer is in the filter widget, in which case it receives the input. The content of the input area is assumed to be relative to the directory currently displayed if not an absolute pathname. The selection is always taken from the nomination in the input area, and happens when the select button is clicked (button 1) or the Return key is pressed. If no modification is to be made then a choice from the List widget can be selected by double clicking mouse button 1 or by single clicking mouse button 2. Further, an immediate selection of some other directory in the path of the displayed directory can be made by selecting from the "path" button menu. .LP A '~' as the first character in the input area is understood to mean the user's home directory. If a nomination begins with a '$' then the first component will be treated as a possible reference to an environment variable, with the expansion being made if a variable of that name exists. .LP In addition the user may define (see pathList under RESOURCES below) a list of potential nominations - either files or directories - to be added to the "path" button menu. Since selecting an entry from the menu is equivalent to entering the entry in the input area and selecting it in the normal way, i.e it is subject to the checks that would be applied if the user had typed the value as a nomination, then '~' and '$' may feature in the user-added entries. .LP When the selection is a directory the contents of the directory are filtered according to the pattern in the filter input area, so that a reduced subset of interest may be displayed. A new filter can be run on the current directory by hitting Return in the Filter input area or by clicking the Filter: button. .SH RESOURCES .LP When creating a FileNominator widget instance, the following additional resources (to those of Core) are retrieved from the argument list or from the resource database: .LP .TS tab(/) ; lB lB lB lB. NAME/CLASS/TYPE/DEFAULT VALUE .T& lB l l l. bellLevel/bellLevel/int/100 cancelCallback/Callback/XtCallbackList/NULL initialDirectory/InitialDirectory/String/NULL filter/Filter/String/* margin/Margin/Dimension/10 numberRows/NumberStrings/int/12 selectCallback/Callback/XtCallbackList/NULL showDotFiles/ShowDotFiles/Boolean/True pathList/PathList/String/NULL userData/UserData/XtPointer/NULL .TE .IP \fBbellLevel\fP 1.5i How loud the keyboard bell should be rung. The value is passed unchanged to XBell. .IP \fBcancelCallback\fP 1.5i All functions on this list are called whenever the cancel buttons's \fBnotify\fP action is invoked. .IP \fBinitialDirectory\fP 1.5i The initial directory whose contents are to be displayed. The default, or if the supplied value is invalid, is the current working directory. .IP \fBfilter\fP 1.5i An initial filter pattern to be applied to the contents of \fIinitialDirectory\fP. The default is "*", i.e. all filenames are displayed. .IP \fBmargin\fP 1.5i The default distance between component widgets and between the edges of the widget and components. .IP \fBnumberRows\fP 1.5i The number of rows of the List widget to display. .IP \fBselectCallback\fP 1.5i All functions on this list are called whenever the select buttons's \fBnotify\fP action is invoked. .IP \fBshowDotFiles\fP 1.5i This value of this boolean resource determines whether the names of "." files are shown. The default is True. "." and ".." are always shown. .IP \fBpathList\fP 1.5i The value of this resource is a colon separated list of pathnames that are converted into menu entries and added to the path button menu. .IP \fBuserData\fP 1.5i This resource is provided for the programmar to use as they see fit. .SH ACTIONS .sp .LP The FileNominator widget supports the following actions: .IP o 5 Processing file or directory nominations in the List widget with \fBNominate\fP. .IP o 5 Constructing a menu of path elements for the MenuButton widget. .IP o 5 Toggling the display of "." files. .LP The following default translation tables are defined by the FileNominator Widget on its component widgets: .LP List widget default translation table .sp .TS lB. (2): Set() Nominate() Unset() ,: Set() Notify() : Set() Notify() Nominate() Unset() .TE .LP Filter widget default translation table .sp Return: Filter() .LP Filename widget default translation table .sp Return: Nominate() .LP Select button default translation table .sp .TS lB. : Nominate() unset() .TE .LP MenuButton default translation table .sp .TS lB. : reset() MakeMenu() XawPositionSimpleMenu(menu) MenuPopup(menu) .TE .sp .LP The full list of actions supported by FileNominator widget is: .IP \fBNominate\fP(\|) 1.5i \fInominates\fP the text in the text widget as the user's choice. If the nomination is a directory then the contents of the List widget will change. If the nomination is a file - which need not exist - then callbacks on the selectCallback list will be called. .IP \fBMakeMenu\fP(\|) 1.5i \fImakes\fP a SimpleMenu consisting of the path elements of the pathname of the current directory. .IP \fBToggleDotFiles\fP(\|) 1.5i toggles the value of the showDotFiles resource and causes the currently displayed directory to be rescanned with the new value effective. This action is bound to the Escape key by default. .SH CALLBACKS .LP All procedures on the FileNominator widget's selectCallback list will have a \fBFileNominatorStruct\fP passed to them as \fIcall_data\fP. The structure is defined in the FileNominator widget's application header file. .LP typedef struct { String directoryPart; int directoryStatus; String filenamePart; int filenameStatus; .br } FileNominatorStruct; .LP The concatenation of directoryPart and filenamePart yield the pathname of the nominated file. directoryStatus and filenameStatus provide information about the access that the user has to the separate parts. Their values are the symbolic constant FileNominatorNonexistent or logical OR combinations of FileNominatorReadable, FileNominatorWritable and FileNominatorExecutable. .LP Note that the data pointed to by the String fields are owned by the FileNominator and should NOT be freed by the callback routines. .SH CONVENIENCE ROUTINES .LP To change the directory that is displayed, use .LP void FileNominatorSetDirectory(\fIw\fP, \fIdir\fP) .br Widget \fIw\fP; .br String * \fIdir\fP; .IP \fIw\fP 1i Specifies the FileNominator widget. .IP \fIdir\fP 1i Specifies the new directory for the FileNominator widget to display. .LP To get the name of the directory that is displayed, use .LP String FileNominatorGetDirectory() .LP \fBFileNominatorGetDirectory\fP returns the current directory of the FileNominator widget. axe-6.1.2.orig/Widgets/FileNomP.h100644 243 144 6477 5550557123 15243 0ustar joostusers/* * Copyright 1991, 1992, 1993 The University of Newcastle upon Tyne * * Permission to use, copy, modify and distribute this software and its * documentation for any purpose other than its commercial exploitation * is hereby granted without fee, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of The University of Newcastle upon Tyne not be used in * advertising or publicity pertaining to distribution of the software * without specific, written prior permission. The University of * Newcastle upon Tyne makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * THE UNIVERSITY OF NEWCASTLE UPON TYNE DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF * NEWCASTLE UPON TYNE BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. * * Author: Jim Wight (j.k.wight@newcastle.ac.uk) * Department of Computing Science * University of Newcastle upon Tyne, UK */ #ifndef FileNominatorP_h #define FileNominatorP_h #include "FileNom.h" typedef struct { XtPointer extension; XtTranslations pathTranslations; XtTranslations listTranslations; XtTranslations FilterTranslations; XtTranslations filterTranslations; XtTranslations filenameTranslations; XtTranslations selectTranslations; Pixmap tickMark; } FileNominatorClassPart; typedef struct _FileNominatorClassRec { CoreClassPart core_class; FileNominatorClassPart fileNominator_class; } FileNominatorClassRec, *FileNominatorClass; extern FileNominatorClassRec fileNominatorClassRec; typedef struct { /* resources */ String initial_directory; XtCallbackList select_callback; String path_list; XtCallbackList cancel_callback; Dimension margin; int number_rows; Boolean show_dot_files; int bell_level; String filter; Boolean filter_directory_names; /* private data */ Widget viewport_widget; Widget list_widget; Widget Filter_widget; Widget filter_menu; Widget apply_dirs; Widget apply_dots; Widget filter_widget; Widget filename_widget; Widget text_widget; Widget select_widget; Widget path_widget; Widget cancel_widget; String *listList; char currentDir[MAXPATHLEN]; Boolean watchingChanges; FileNominatorStruct nomination; XtPointer user_data; } FileNominatorPart; typedef struct _FileNominatorRec { CorePart core; FileNominatorPart fileNominator; } FileNominatorRec; #endif /* FileNominatorP_h */ axe-6.1.2.orig/Widgets/Imakefile100644 243 144 2605 5550557125 15221 0ustar joostusers#include "../Axe.tmpl" #include "../Axe.rules" SRCS = ${TABLE_SRCS} ${EXTN_SRCS} \ AxeWindow.c AxeEditor.c AxeMenuBtn.c AxeSimMenu.c \ AxeSmeBSB.c AxeCommand.c AxeTextDeck.c AxeText.c \ AxeiiText.c AxeiiUndo.c AxeiiSink.c \ FileNomWin.c FileNom.c ${R5ONLY_SRCS} ${R4ONLY_SRCS} ScrollText.c \ NumericPad.c CtrlCodeSel.c Preference.c Confirmer.c \ ${SCANDIR_SRCS} regexp.c insertfile.c match.c util.c OBJS = ${TABLE_OBJS} ${EXTN_OBJS} \ AxeWindow.o AxeEditor.o AxeMenuBtn.o AxeSimMenu.o \ AxeSmeBSB.o AxeTextDeck.o AxeCommand.o AxeText.o \ AxeiiText.o AxeiiUndo.o AxeiiSink.o \ FileNomWin.o FileNom.o ${R5ONLY_OBJS} ${R4ONLY_OBJS} ScrollText.o \ NumericPad.o CtrlCodeSel.o Preference.o Confirmer.o \ ${SCANDIR_OBJS} regexp.o insertfile.o match.o util.o /* * -I. comes after TABLE_INCLUDES to ensure that Table headers in ./X11/Xp * are not accessed instead of the locally installed ones, and before * EXTN_INCLUDES to ensure that the local regexp.h is used rather than * the one provided by Tcl, or any other. */ EXTRA_INCLUDES = ${TABLE_INCLUDES} -I. -I.. ${EXTN_INCLUDES} ${XAW3D_INCLUDES} NormalLibraryObjectRule() NormalLibraryTarget(axe,$(OBJS)) DependTarget() #ifdef NODIRENT SpecialObjectRule(FileNom.o,,-DNODIRENT) #ifdef NOSCANDIR SpecialObjectRule(scandir.o,,-DNODIRENT) #endif #endif MakeXaw3d($(XAW3D_DEPS)) axe-6.1.2.orig/Widgets/FileNomWin.c100644 243 144 17025 5550557114 15603 0ustar joostusers/* * Copyright 1992 The University of Newcastle upon Tyne * * Permission to use, copy, modify and distribute this software and its * documentation for any purpose other than its commercial exploitation * is hereby granted without fee, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of The University of Newcastle upon Tyne not be used in * advertising or publicity pertaining to distribution of the software * without specific, written prior permission. The University of * Newcastle upon Tyne makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * * * THE UNIVERSITY OF NEWCASTLE UPON TYNE DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF * NEWCASTLE UPON TYNE BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. * * Author: Jim Wight (j.k.wight@newcastle.ac.uk) * Department of Computing Science * University of Newcastle upon Tyne, UK */ #include #include #include #include #include "FileNomWinP.h" #define Offset(field) XtOffsetOf(FileNominatorWindowRec, fileNominatorWindow.field) static XtResource resources[] = { {XtNinitialDirectory, XtCInitialDirectory, XtRString, sizeof(String), Offset(initial_directory), XtRString, (XtPointer) NULL}, }; #undef Offset #define CLASS(field) fileNominatorWindowClassRec.fileNominatorWindow_class.field #define PRIVATE(w,field) (((FileNominatorWindowWidget) w)->fileNominatorWindow.field) static char nominatorTranslations[] = ":scroll-on-movement(True) \n\ :scroll-on-movement(False)"; static void ClassInitialize(), Initialize(), Resize(); static XtGeometryResult GeometryManager(); static void SetWMHints(); FileNominatorWindowClassRec fileNominatorWindowClassRec = { { /* superclass */ (WidgetClass) &transientShellClassRec, /* class_name */ "FileNominatorWindow", /* size */ sizeof(FileNominatorWindowRec), /* Class Initializer */ ClassInitialize, /* class_part_initialize*/ NULL, /* Class init'ed ? */ FALSE, /* initialize */ Initialize, /* initialize_notify */ NULL, /* realize */ XtInheritRealize, /* actions */ NULL, /* num_actions */ 0, /* resources */ resources, /* resource_count */ XtNumber(resources), /* xrm_class */ NULLQUARK, /* compress_motion */ FALSE, /* compress_exposure */ TRUE, /* compress_enterleave*/ FALSE, /* visible_interest */ FALSE, /* destroy */ NULL, /* resize */ Resize, /* expose */ NULL, /* set_values */ NULL, /* set_values_hook */ NULL, /* set_values_almost */ XtInheritSetValuesAlmost, /* get_values_hook */ NULL, /* accept_focus */ NULL, /* intrinsics version */ XtVersion, /* callback offsets */ NULL, /* tm_table */ XtInheritTranslations, /* query_geometry */ NULL, /* display_accelerator */ NULL, /* extension */ NULL },{ /* geometry_manager */ GeometryManager, /* change_managed */ XtInheritChangeManaged, /* insert_child */ XtInheritInsertChild, /* delete_child */ XtInheritDeleteChild, /* extension */ NULL },{ /* extension */ NULL },{ /* extension */ NULL },{ /* extension */ NULL },{ /* extension */ NULL },{ /* extension */ NULL } }; WidgetClass fileNominatorWindowWidgetClass = (WidgetClass) &fileNominatorWindowClassRec; static void ClassInitialize() { CLASS(nominatorTranslations) = XtParseTranslationTable(nominatorTranslations); } /* ARGSUSED */ static void Initialize(req, new, args, num_args) Widget req, new; ArgList args; Cardinal *num_args; { char *off = "False"; Widget fileNom = PRIVATE(new,nominator) = XtVaCreateManagedWidget("filenom", fileNominatorWidgetClass, new, XtNinitialDirectory, PRIVATE(new,initial_directory), NULL); XtOverrideTranslations(fileNom, CLASS(nominatorTranslations)); XtCallActionProc(fileNom, "scroll-on-movement", (XEvent *) 0, &off, 1); } static void Resize(w) Widget w; { (*((TransientShellWidgetClass) (fileNominatorWindowWidgetClass-> core_class.superclass))->core_class.resize) (w); SetWMHints(w); } static XtGeometryResult GeometryManager(w, desired, allowed) Widget w; XtWidgetGeometry *desired, *allowed; { XtGeometryResult result; result = (*((TransientShellWidgetClass) (fileNominatorWindowWidgetClass-> core_class.superclass))-> composite_class.geometry_manager) (w, desired, allowed); if (result == XtGeometryYes) { SetWMHints(XtParent(w)); } return result; } static void SetWMHints(fnww) Widget fnww; { Widget viewport, vscroller; XSizeHints hints; long supp; XFontStruct *font; Dimension vpWidth, vpHeight, inWidth, inHeight, rowSpacing, thickness; Atom wm_delete_window; Window window = XtWindow(fnww); Display *display = XtDisplay(fnww); if (!XtIsRealized(fnww)) { return; } XtVaGetValues(FileNominatorListWidget(PRIVATE(fnww,nominator)), XtNfont, &font, XtNrowSpacing, &rowSpacing, XtNinternalWidth, &inWidth, XtNinternalHeight, &inHeight, NULL); viewport = FileNominatorViewportWidget(PRIVATE(fnww,nominator)); XtVaGetValues(viewport, XtNwidth, &vpWidth, XtNheight, &vpHeight, NULL); if (!XGetWMNormalHints(display, window, &hints, &supp)) { hints.flags = 0; } hints.flags |= PResizeInc | PBaseSize; hints.height_inc = font->max_bounds.ascent + font->max_bounds.descent + rowSpacing; hints.base_height = fnww->core.height - (vpHeight - 2 * inHeight) - rowSpacing; /* Monospaaced or character cell font? */ if (font->min_bounds.width == font->max_bounds.width) { if ((vscroller = XtNameToWidget(viewport, "vertical"))) { XtVaGetValues(vscroller, XtNthickness, &thickness, NULL); vpWidth -= thickness; } hints.width_inc = font->min_bounds.width; hints.base_width = fnww->core.width - (vpWidth - 2 * inWidth); } XSetWMNormalHints(display, window, &hints); wm_delete_window = XInternAtom (display, "WM_DELETE_WINDOW", False); (void) XSetWMProtocols(display, window, &wm_delete_window, 1); } /************************************************************* * * Public functions * *************************************************************/ Widget FileNominatorWindowFileNominatorWidget(fnww) Widget fnww; { if (XtIsSubclass(fnww, fileNominatorWindowWidgetClass)) { return PRIVATE(fnww,nominator); } else { return (Widget) 0; } } axe-6.1.2.orig/Widgets/FileNomWin.h100644 243 144 3566 5550557123 15575 0ustar joostusers/* * Copyright 1992 The University of Newcastle upon Tyne * * Permission to use, copy, modify and distribute this software and its * documentation for any purpose other than its commercial exploitation * is hereby granted without fee, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of The University of Newcastle upon Tyne not be used in * advertising or publicity pertaining to distribution of the software * without specific, written prior permission. The University of * Newcastle upon Tyne makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * THE UNIVERSITY OF NEWCASTLE UPON TYNE DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF * NEWCASTLE UPON TYNE BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. * * Author: Jim Wight (j.k.wight@newcastle.ac.uk) * Department of Computing Science * University of Newcastle upon Tyne, UK */ #ifndef FileNominatorWindow_h #define FileNominatorWindow_h typedef struct _FileNominatorWindowClassRec *FileNominatorWindowWidgetClass; typedef struct _FileNominatorWindowRec *FileNominatorWindowWidget; extern WidgetClass fileNominatorWindowWidgetClass; Widget FileNominatorWindowFileNominatorWidget(); #define XtNinitialDirectory "initialDirectory" #define XtCInitialDirectory "InitialDirectory" #endif /* FileNominatorWindow_h */ axe-6.1.2.orig/Widgets/FileNomWinP.h100644 243 144 5250 5550557123 15705 0ustar joostusers/* * Copyright 1992 The University of Newcastle upon Tyne * * Permission to use, copy, modify and distribute this software and its * documentation for any purpose other than its commercial exploitation * is hereby granted without fee, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of The University of Newcastle upon Tyne not be used in * advertising or publicity pertaining to distribution of the software * without specific, written prior permission. The University of * Newcastle upon Tyne makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * THE UNIVERSITY OF NEWCASTLE UPON TYNE DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF * NEWCASTLE UPON TYNE BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. * * Author: Jim Wight (j.k.wight@newcastle.ac.uk) * Department of Computing Science * University of Newcastle upon Tyne, UK */ #ifndef FileNominatorWindowP_h #define FileNominatorWindowP_h #include #include "FileNomWin.h" typedef struct { XtPointer extension; XtTranslations nominatorTranslations; } FileNominatorWindowClassPart; typedef struct _FileNominatorWindowClassRec { CoreClassPart core_class; CompositeClassPart composite_class; ShellClassPart shell_class; WMShellClassPart wm_shell_class; VendorShellClassPart vendor_shell_class; TransientShellClassPart transient_shell_class; FileNominatorWindowClassPart fileNominatorWindow_class; } FileNominatorWindowClassRec; extern FileNominatorWindowClassRec fileNominatorWindowClassRec; typedef struct { /* Resources */ String initial_directory; /* Private variables */ Widget nominator; } FileNominatorWindowPart; typedef struct _FileNominatorWindowRec { CorePart core; CompositePart composite; ShellPart shell; WMShellPart wm; VendorShellPart vendor; TransientShellPart transient; FileNominatorWindowPart fileNominatorWindow; } FileNominatorWindowRec; #endif /* FileNominatorWindowP_h */ axe-6.1.2.orig/Widgets/Language.c100644 243 144 20100 5550743677 15316 0ustar joostusers#include #include #include #include #include extern char *getenv(); #include "Language.h" static void InterpFocus(), Execute(); static XtActionsRec actions[] = { "interp-focus", InterpFocus, "execute", Execute, }; /*ARGSUSED*/ static void InterpFocus(widget, event, params, num_params) Widget widget; XEvent *event; String *params; Cardinal *num_params; { if (!XtIsSubclass(widget, axeEditorWidgetClass)) { return; } interpreter.SetBuffer(AxeEditorEdWidget(widget)); } /*ARGSUSED*/ static void Execute(widget, event, params, num_params) Widget widget; XEvent *event; String *params; Cardinal *num_params; { #if TCL_MAJOR_VERSION < 7 Tcl_CmdBuf assembley; Cardinal param; char *cmd; if (*num_params == 0) { return; } assembley = Tcl_CreateCmdBuf(); for (param = 0; param < *num_params; ++param) { cmd = Tcl_AssembleCmd(assembley, params[param]); cmd = Tcl_AssembleCmd(assembley, " "); } cmd = Tcl_AssembleCmd(assembley, ""); (void) Tcl_Eval(interpreter.interp, cmd, 0, NULL); Tcl_DeleteCmdBuf(assembley); #else Tcl_DString assembley; Cardinal param; if (*num_params == 0) { return; } Tcl_DStringInit(&assembley); for (param = 0; param < *num_params; ++param) { (void) Tcl_DStringAppendElement(&assembley, params[param]); } (void) Tcl_Eval(interpreter.interp, assembley.string); Tcl_DStringFree(&assembley); #endif } /*ARGSUSED*/ static int Action(clientData, interp, argc, argv) ClientData clientData; Tcl_Interp *interp; int argc; char *argv[]; { Window root, child; unsigned int mask; XEvent event; if (argc < 2) { interpreter.interp->result = "Usage: action arg [arg]"; return TCL_ERROR; } XQueryPointer(XtDisplay(interpreter.buffer), XtWindow(interpreter.buffer), &root, &child, &event.xbutton.x_root, &event.xbutton.y_root, &event.xbutton.x, &event.xbutton.y, &mask); event.type = ButtonPress; XtCallActionProc(interpreter.buffer, argv[1], &event, &argv[2], argc - 2); return TCL_OK; } /*ARGSUSED*/ static int GetPosition(clientData, interp, argc, argv) ClientData clientData; Tcl_Interp *interp; int argc; char *argv[]; { sprintf(interpreter.interp->result, "%d", XawTextGetInsertionPoint(interpreter.buffer)); return TCL_OK; } /*ARGSUSED*/ static int SetPosition(clientData, interp, argc, argv) ClientData clientData; Tcl_Interp *interp; int argc; char *argv[]; { if (argc < 2) { interpreter.interp->result = "Usage: set-position arg"; return TCL_ERROR; } XawTextSetInsertionPoint(interpreter.buffer, (XawTextPosition) atoi(argv[1])); return TCL_OK; } /*ARGSUSED*/ static int GetSelection(clientData, interp, argc, argv) ClientData clientData; Tcl_Interp *interp; int argc; char *argv[]; { Widget source = XawTextGetSource(interpreter.buffer); String selection, s; XawTextPosition start, finish; int lines = 0; XawTextGetSelectionPos(interpreter.buffer, &start, &finish); selection = AxeiiTextRead(interpreter.buffer, start, finish); for (s = selection; *s != 0; ++s) { if (*s == '\n') { ++lines; } } if (*(s - 1) != '\n') { ++lines; } sprintf(interpreter.interp->result, "%d %d %d ", start, finish, lines); Tcl_AppendElement(interpreter.interp, selection); XtFree(selection); return TCL_OK; } /*ARGSUSED*/ static int SetSelection(clientData, interp, argc, argv) ClientData clientData; Tcl_Interp *interp; int argc; char *argv[]; { Widget source = XawTextGetSource(interpreter.buffer); if (argc < 3) { interpreter.interp->result = "Usage: set-selection arg arg"; return TCL_ERROR; } XawTextSetSelection(interpreter.buffer, (XawTextPosition) atoi(argv[1]), (XawTextPosition) atoi(argv[2])); return TCL_OK; } /*ARGSUSED*/ static int EvalBuffer(clientData, interp, argc, argv) ClientData clientData; Tcl_Interp *interp; int argc; char *argv[]; { int result; String script = AxeiiTextRead(interpreter.buffer, (XawTextPosition) 0, XawTextSourceScan(XawTextGetSource(interpreter.buffer), (XawTextPosition) 0, XawstAll, XawsdRight, 1, True)); #if TCL_MAJOR_VERSION < 7 result = Tcl_Eval(interpreter.interp, script, 0, NULL); #else result = Tcl_Eval(interpreter.interp, script); #endif XtFree(script); return result; } static int SetOneValue(widget, argc, argv) Widget widget; int argc; char *argv[]; { if (argc < 3) { interpreter.interp->result = "Usage: set-value arg arg"; return TCL_ERROR; } XtVaSetValues(widget, XtVaTypedArg, argv[1], XtRString, argv[2], strlen(argv[2]), NULL); return TCL_OK; } /*ARGSUSED*/ static int SetValue(clientData, interp, argc, argv) ClientData clientData; Tcl_Interp *interp; int argc; char *argv[]; { return SetOneValue(interpreter.buffer, argc, argv); } /*ARGSUSED*/ static int SetSourceValue(clientData, interp, argc, argv) ClientData clientData; Tcl_Interp *interp; int argc; char *argv[]; { return SetOneValue(XawTextGetSource(interpreter.buffer), argc, argv); } /*ARGSUSED*/ static int SetSinkValue(clientData, interp, argc, argv) ClientData clientData; Tcl_Interp *interp; int argc; char *argv[]; { Widget sink; XtVaGetValues(interpreter.buffer, XtNtextSink, &sink, NULL); return SetOneValue(sink, argc, argv); } static void SetBuffer(buffer) Widget buffer; { interpreter.buffer = buffer; } static XtResource resources[] = { { "axeLibDir", "AxeLibDir", XtRString, sizeof(String), (Cardinal) 0, XtRImmediate, (XtPointer) 0 } }; static void Initialize(widget) Widget widget; { XtAppContext app = XtWidgetToApplicationContext(widget); char tclFile[MAXPATHLEN], *home, *tcl; Tcl_Interp *interp = interpreter.interp = Tcl_CreateInterp(); Tcl_CreateCommand(interp, "action", Action, (ClientData) 0, (Tcl_CmdDeleteProc *) NULL); Tcl_CreateCommand(interp, "get-selection", GetSelection, (ClientData) 0, (Tcl_CmdDeleteProc *) NULL); Tcl_CreateCommand(interp, "set-selection", SetSelection, (ClientData) 0, (Tcl_CmdDeleteProc *) NULL); Tcl_CreateCommand(interp, "get-position", GetPosition, (ClientData) 0, (Tcl_CmdDeleteProc *) NULL); Tcl_CreateCommand(interp, "set-position", SetPosition, (ClientData) 0, (Tcl_CmdDeleteProc *) NULL); Tcl_CreateCommand(interp, "eval-buffer", EvalBuffer, (ClientData) 0, (Tcl_CmdDeleteProc *) NULL); Tcl_CreateCommand(interp, "set-value", SetValue, (ClientData) 0, (Tcl_CmdDeleteProc *) NULL); Tcl_CreateCommand(interp, "set-source-value", SetSourceValue, (ClientData) 0, (Tcl_CmdDeleteProc *) NULL); Tcl_CreateCommand(interp, "set-sink-value", SetSinkValue, (ClientData) 0, (Tcl_CmdDeleteProc *) NULL); XtVaGetApplicationResources(widget, (XtPointer) &tcl, resources, XtNumber(resources), NULL); strcpy(tclFile, tcl); strcat(tclFile, "/axe.tcl"); (void) Tcl_EvalFile(interp, tclFile); home = getenv("HOME"); strcpy(tclFile, home); strcat(tclFile, "/axe.tcl"); (void) Tcl_EvalFile(interp, tclFile); XtAppAddActions(app, actions, XtNumber(actions)); } InterpRec interpreter = { Initialize, (Tcl_Interp *) 0, SetBuffer, (Widget) 0, }; axe-6.1.2.orig/Widgets/Language.h100644 243 144 405 5550557123 15256 0ustar joostusers#ifndef Interp_h #define Interp_h #include #include typedef struct { void (* Initialize)(); Tcl_Interp *interp; void (* SetBuffer)(); Widget buffer; } InterpRec; extern InterpRec interpreter; #endif axe-6.1.2.orig/Widgets/NumericPad.c100644 243 144 31553 5550557114 15625 0ustar joostusers/* * Copyright 1992 The University of Newcastle upon Tyne * * Permission to use, copy, modify and distribute this software and its * documentation for any purpose other than its commercial exploitation * is hereby granted without fee, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of The University of Newcastle upon Tyne not be used in * advertising or publicity pertaining to distribution of the software * without specific, written prior permission. The University of * Newcastle upon Tyne makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * THE UNIVERSITY OF NEWCASTLE UPON TYNE DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF * NEWCASTLE UPON TYNE BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. * * Author: Jim Wight (j.k.wight@newcastle.ac.uk) * Department of Computing Science * University of Newcastle upon Tyne, UK */ #include #include #include #include #include #include #define OCT 8 #define DEC 10 #define HEX 16 #define CLASS(field) numericPadClassRec.pad_class.field #define PRIVATE(w,field) (((NumericPadWidget) w)->pad.field) #define TableOffset(field) XtOffsetOf(NumericPadRec, table.field) #define Offset(field) XtOffsetOf(NumericPadRec, pad.field) static char layout[] = "oct 0 0 4; dec 4 0 4; hex 8 0 4; \ c 0 1 3; d 3 1 3; e 6 1 3; f 9 1 3; \ a 0 2 3; 8 3 2 3; 9 6 2 3; b 9 2 3; \ 4 0 3 3; 5 3 3 3; 6 6 3 3; 7 9 3 3; \ 0 0 4 3; 1 3 4 3; 2 6 4 3; 3 9 4 3; \ text 0 5 12; \ enter 0 6 6; cancel 6 6 6;"; static XtResource resources[] = { /* Table Widget Resources */ { XtNlayout, XtCLayout, XtRXpTableLoc, sizeof(XpTableLoc), TableOffset(default_layout), XtRString, (XtPointer) layout }, { XtNmarginWidth, XtCMargins, XtRInt, sizeof(int), TableOffset(margin_width), XtRImmediate, (XtPointer) 5 }, { XtNmarginHeight, XtCMargins, XtRInt, sizeof(int), TableOffset(margin_height), XtRImmediate, (XtPointer) 5 }, { XtNcolumnSpacing, XtCSpacing, XtRInt, sizeof(int), TableOffset(col_spacing), XtRImmediate, (XtPointer) 5 }, { XtNrowSpacing, XtCSpacing, XtRInt, sizeof(int), TableOffset(row_spacing), XtRImmediate, (XtPointer) 5 }, /* NumericPad Widget Resources */ {XtNbase, XtCBase, XtRInt, sizeof(int), Offset(base), XtRImmediate, (XtPointer) DEC}, {XtNenterCallback, XtCCallback, XtRCallback, sizeof(XtCallbackList), Offset(enter_callbacks), XtRCallback, (XtPointer) NULL}, {XtNcancelCallback, XtCCallback, XtRCallback, sizeof(XtCallbackList), Offset(cancel_callbacks), XtRCallback, (XtPointer) NULL}, }; #undef Offset static char digits[] = "0123456789abcdef"; static char textTranslations[] = "Return: Forward() \n\ KP_Enter: Forward()"; static void ClassInitialize(), Initialize(); static Boolean SetValues(); static void SetSensitivity(), ModeChange(), Type(), Enter(), Cancel(), Forward(); static XtActionsRec actions[] = { "Forward", Forward, }; NumericPadClassRec numericPadClassRec = { { /* superclass */ (WidgetClass) &xpTableClassRec, /* class_name */ "NumericPad", /* size */ sizeof(NumericPadRec), /* class_initialize */ ClassInitialize, /* class_part_initialize */ NULL, /* class_inited */ FALSE, /* initialize */ Initialize, /* initialize_hook */ NULL, /* realize */ XtInheritRealize, /* actions */ actions, /* num_actions */ XtNumber(actions), /* resources */ resources, /* resource_count */ XtNumber(resources), /* xrm_class */ NULLQUARK, /* compress_motion */ FALSE, /* compress_exposure */ TRUE, /* compress_enterleave */ TRUE, /* visible_interest */ FALSE, /* destroy */ NULL, /* resize */ XtInheritResize, /* expose */ XtInheritExpose, /* set_values */ SetValues, /* set_values_hook */ NULL, /* set_values_almost */ XtInheritSetValuesAlmost, /* get_values_hook */ NULL, /* accept_focus */ NULL, /* version */ XtVersion, /* callback_private */ NULL, /* tm_table */ XtInheritTranslations, /* query_geometry */ XtInheritQueryGeometry, /* display_accelerator */ XtInheritDisplayAccelerator, /* extension */ NULL },/* CoreClass fields initialization */ { /* composite class fields */ /* geometry_manager */ XtInheritGeometryManager, /* change_managed */ XtInheritChangeManaged, /* insert_child */ XtInheritInsertChild, /* delete_child */ XtInheritDeleteChild, /* extension */ NULL },/* CompositeClass fields initialization */ { /* extension */ NULL, },/* TableClass fields initialization */ { /* extension */ NULL, },/* NumericPadClass fields initialization */ }; WidgetClass numericPadWidgetClass = (WidgetClass) &numericPadClassRec; static void ClassInitialize() { CLASS(textTranslations) = XtParseTranslationTable(textTranslations); } /* ARGSUSED */ static void Initialize(req, new, args, num_args) Widget req, new; ArgList args; Cardinal *num_args; { Widget dec, oct, hex, button, text, enter, cancel; int digit; char label[2]; dec = PRIVATE(new,dec_widget) = XtVaCreateManagedWidget("dec", toggleWidgetClass, new, XtNstate, PRIVATE(new,base) == DEC, NULL); XtAddCallback(dec, XtNcallback, ModeChange, (XtPointer) new); XtVaSetValues(dec, XtNradioData, dec, NULL); oct = PRIVATE(new,oct_widget) = XtVaCreateManagedWidget("oct", toggleWidgetClass, new, XtNstate, PRIVATE(new,base) == OCT, XtNradioGroup, dec, NULL); XtAddCallback(oct, XtNcallback, ModeChange, (XtPointer) new); XtVaSetValues(oct, XtNradioData, oct, NULL); hex = PRIVATE(new,hex_widget) = XtVaCreateManagedWidget("hex", toggleWidgetClass, new, XtNstate, PRIVATE(new,base) == HEX, XtNradioGroup, dec, NULL); XtAddCallback(hex, XtNcallback, ModeChange, (XtPointer) new); XtVaSetValues(hex, XtNradioData, hex, NULL); for (digit = 0; digit < 16; ++digit) { sprintf(label, "%c", digits[digit]); button = XtVaCreateManagedWidget(label, commandWidgetClass, new, XtNsensitive, digit < 10 ? True : False, NULL); XtAddCallback(button, XtNcallback, Type, (XtPointer) ((int) digits[digit])); } SetSensitivity(new); text = PRIVATE(new,text_widget) = XtVaCreateManagedWidget("text", asciiTextWidgetClass, new, XtNeditType, XawtextEdit, NULL); XtOverrideTranslations(text, CLASS(textTranslations)); enter = XtVaCreateManagedWidget("enter", commandWidgetClass, new, NULL); XtAddCallback(enter, XtNcallback, Enter, (XtPointer) text); cancel = XtVaCreateManagedWidget("cancel", commandWidgetClass, new, NULL); XtAddCallback(cancel, XtNcallback, Cancel, NULL); XtSetKeyboardFocus(new, text); } /* ARGSUSED */ static Boolean SetValues(old, request, new, args, num_args) Widget old, request, new; ArgList args; Cardinal *num_args; { NumericPadWidget oldnpw = (NumericPadWidget) old; NumericPadWidget newnpw = (NumericPadWidget) new; int base; #define NE(field) (oldnpw->field != newnpw->field) if (NE(pad.base)) { base = PRIVATE(new,base); if (base != OCT && base != DEC && base != HEX) { base = PRIVATE(new,base) = DEC; } XtVaSetValues(PRIVATE(new,oct_widget), XtNstate, base == OCT, NULL); XtVaSetValues(PRIVATE(new,dec_widget), XtNstate, base == DEC, NULL); XtVaSetValues(PRIVATE(new,hex_widget), XtNstate, base == HEX, NULL); SetSensitivity(new); } #undef NE return False; } static void SetSensitivity(widget) Widget widget; { WidgetList children; Cardinal numChildren, child; int ch, base = PRIVATE(widget,base); XtVaGetValues(widget, XtNchildren, &children, XtNnumChildren, &numChildren, NULL); /* Making assumptions about order children added */ for (child = 0; child < numChildren; ++child) { if (!XtIsSubclass(children[child], toggleWidgetClass)) { break; } } for (ch = 0; ch < HEX; ++ch) { XtVaSetValues(children[child++], XtNsensitive, ch < base ? True : False, NULL); } } /* ARGSUSED */ static void ModeChange(widget, client_data, call_data) Widget widget; XtPointer client_data, call_data; { Widget pad = (Widget) client_data; int base; if (XawToggleGetCurrent(widget) != (XtPointer) widget) { return; } if (widget == PRIVATE(pad,oct_widget)) { base = OCT; } else if (widget == PRIVATE(pad,dec_widget)) { base = DEC; } else { base = HEX; } PRIVATE(pad,base) = base; SetSensitivity(pad); } /* ARGSUSED */ static void Type(widget, client_data, call_data) Widget widget; XtPointer client_data, call_data; { char digit = (char) ((int) client_data); Widget text = ((NumericPadWidget) XtParent(widget))->pad.text_widget; XawTextBlock textBlock; XawTextPosition insertPos; insertPos = XawTextGetInsertionPoint(text); textBlock.firstPos = 0; textBlock.length = 1; textBlock.ptr = &digit; textBlock.format = FMT8BIT; XawTextReplace(text, insertPos, insertPos, &textBlock); XawTextSetInsertionPoint(text, insertPos + 1); } static void Feed(widget) Widget widget; { Widget pad = XtParent(widget); Widget text = PRIVATE(pad,text_widget); int c, base = PRIVATE(pad,base), value = 0; NumericPadReturnStruct result; String p; Boolean error = False; XtVaGetValues(text, XtNstring, &result.value, NULL); for (p = result.value; *p; ++p) { for (c = 0; c < HEX; ++c) { if (*p == digits[c]) { if (c >= base) { error = True; } break; } } if (error) { break; } else { value = (base * value) + c; } } if (!error) { result.base = PRIVATE(pad,base); result.conversion = value; XtCallCallbackList(pad, PRIVATE(pad,enter_callbacks), (XtPointer) &result); } else { XawTextSetSelection(text, p - result.value, p - result.value + 1); XawTextSetInsertionPoint(text, (XawTextPosition) (p - result.value + 1)); XBell(XtDisplay(text), 100); } } /* ARGSUSED */ static void Forward(widget, event, params, num_params) Widget widget; XEvent *event; String *params; Cardinal *num_params; { Feed(widget); } /* ARGSUSED */ static void Enter(widget, client_data, call_data) Widget widget; XtPointer client_data, call_data; { Feed(widget); } /* ARGSUSED */ static void Cancel(widget, client_data, call_data) Widget widget; XtPointer client_data, call_data; { Widget pad = XtParent(widget); XtCallCallbackList(pad, PRIVATE(pad,cancel_callbacks), (XtPointer) 0); } /************************************************************* * * Public functions * *************************************************************/ void NumericPadClear(npw) Widget npw; { if (!XtIsSubclass(npw, numericPadWidgetClass)) { return; } XtVaSetValues(PRIVATE(npw,text_widget), XtNstring, "", NULL); } axe-6.1.2.orig/Widgets/NumericPad.h100644 243 144 3733 5550557123 15611 0ustar joostusers/* * Copyright 1992 The University of Newcastle upon Tyne * * Permission to use, copy, modify and distribute this software and its * documentation for any purpose other than its commercial exploitation * is hereby granted without fee, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of The University of Newcastle upon Tyne not be used in * advertising or publicity pertaining to distribution of the software * without specific, written prior permission. The University of * Newcastle upon Tyne makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * THE UNIVERSITY OF NEWCASTLE UPON TYNE DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF * NEWCASTLE UPON TYNE BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. * * Author: Jim Wight (j.k.wight@newcastle.ac.uk) * Department of Computing Science * University of Newcastle upon Tyne, UK */ #ifndef _NumericPad_h #define _NumericPad_h #include extern WidgetClass numericPadWidgetClass; typedef struct _NumericPadClassRec *NumericPadWidgetClass; typedef struct _NumericPadRec *NumericPadWidget; typedef struct { String value; int base; int conversion; } NumericPadReturnStruct; #define XtNbase "base" #define XtCBase "Base" #define XtNenterCallback "enterCallback" #define XtNcancelCallback "cancelCallback" extern void NumericPadClear(); #endif /* _NumericPad_h */ axe-6.1.2.orig/Widgets/NumericPadP.h100644 243 144 5001 5550557123 15717 0ustar joostusers/* * Copyright 1992 The University of Newcastle upon Tyne * * Permission to use, copy, modify and distribute this software and its * documentation for any purpose other than its commercial exploitation * is hereby granted without fee, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of The University of Newcastle upon Tyne not be used in * advertising or publicity pertaining to distribution of the software * without specific, written prior permission. The University of * Newcastle upon Tyne makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * THE UNIVERSITY OF NEWCASTLE UPON TYNE DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF * NEWCASTLE UPON TYNE BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. * * Author: Jim Wight (j.k.wight@newcastle.ac.uk) * Department of Computing Science * University of Newcastle upon Tyne, UK */ #ifndef _NumericPadP_h #define _NumericPadP_h #include #include typedef struct _NumericPadClass { XtPointer extension; XtTranslations textTranslations; } NumericPadClassPart; typedef struct _NumericPadClassRec { CoreClassPart core_class; CompositeClassPart composite_class; XpTableClassPart table_class; NumericPadClassPart pad_class; } NumericPadClassRec; extern NumericPadClassRec numericPadClassRec; typedef struct _NumericPadPart { /* resources */ int base; XtCallbackList enter_callbacks; XtCallbackList cancel_callbacks; /* private variables */ Widget oct_widget; Widget dec_widget; Widget hex_widget; Widget text_widget; } NumericPadPart; typedef struct _NumericPadRec { CorePart core; CompositePart composite; XpTablePart table; NumericPadPart pad; } NumericPadRec; #endif /* _NumericPadP_h */ axe-6.1.2.orig/Widgets/Porthole.c100644 243 144 26214 5550557114 15370 0ustar joostusers/* * $XConsortium: Porthole.c,v 1.14 91/03/14 16:48:01 converse Exp $ * * Copyright 1990 Massachusetts Institute of Technology * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that * the above copyright notice appear in all copies and that both that * copyright notice and this permission notice appear in supporting * documentation, and that the name of M.I.T. not be used in advertising or * publicity pertaining to distribution of the software without specific, * written prior permission. M.I.T. makes no representations about the * suitability of this software for any purpose. It is provided "as is" * without express or implied warranty. * * M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL M.I.T. * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * * Author: Jim Fulton, MIT X Consortium * * This widget is a trivial clipping widget. It is typically used with a * panner or scrollbar to navigate. */ #include /* get basic toolkit stuff */ #include /* get XtN and XtC defines */ #include /* get Xaw initialize stuff */ #include /* get porthole structs */ #include /* for MAX */ /* * resources for the porthole */ static XtResource resources[] = { #define poff(field) XtOffsetOf(PortholeRec, porthole.field) { XtNreportCallback, XtCReportCallback, XtRCallback, sizeof(XtPointer), poff(report_callbacks), XtRCallback, (XtPointer) NULL }, #undef poff }; /* * widget class methods used below */ static void Realize(); /* set gravity and upcall */ static void Resize(); /* report new size */ static XtGeometryResult GeometryManager(); /* deal with child requests */ static void ChangeManaged(); /* somebody added a new widget */ static XtGeometryResult QueryGeometry(); /* say how big would like to be */ PortholeClassRec portholeClassRec = { { /* core fields */ /* superclass */ (WidgetClass) &compositeClassRec, /* class_name */ "Porthole", /* widget_size */ sizeof(PortholeRec), /* class_initialize */ XawInitializeWidgetSet, /* class_part_initialize */ NULL, /* class_inited */ FALSE, /* initialize */ NULL, /* initialize_hook */ NULL, /* realize */ Realize, /* actions */ NULL, /* num_actions */ 0, /* resources */ resources, /* num_resources */ XtNumber(resources), /* xrm_class */ NULLQUARK, /* compress_motion */ TRUE, /* compress_exposure */ TRUE, /* compress_enterleave */ TRUE, /* visible_interest */ FALSE, /* destroy */ NULL, /* resize */ Resize, /* expose */ NULL, /* set_values */ NULL, /* set_values_hook */ NULL, /* set_values_almost */ XtInheritSetValuesAlmost, /* get_values_hook */ NULL, /* accept_focus */ NULL, /* version */ XtVersion, /* callback_private */ NULL, /* tm_table */ NULL, /* query_geometry */ QueryGeometry, /* display_accelerator */ XtInheritDisplayAccelerator, /* extension */ NULL }, { /* composite fields */ /* geometry_manager */ GeometryManager, /* change_managed */ ChangeManaged, /* insert_child */ XtInheritInsertChild, /* delete_child */ XtInheritDeleteChild, /* extension */ NULL }, { /* porthole fields */ /* ignore */ 0 } }; WidgetClass portholeWidgetClass = (WidgetClass) &portholeClassRec; /***************************************************************************** * * * utility routines * * * *****************************************************************************/ static Widget find_child (pw) register PortholeWidget pw; { register Widget *children; register int i; /* * Find the managed child on which we should operate. Ignore multiple * managed children. */ for (i = 0, children = pw->composite.children; i < pw->composite.num_children; i++, children++) { if (XtIsManaged(*children)) return *children; } return (Widget) NULL; } static void SendReport (pw, changed) PortholeWidget pw; unsigned int changed; { Widget child = find_child (pw); if (pw->porthole.report_callbacks && child) { XawPannerReport prep; prep.changed = changed; prep.slider_x = -child->core.x; /* porthole is "inner" */ prep.slider_y = -child->core.y; /* child is outer since it is larger */ prep.slider_width = pw->core.width; prep.slider_height = pw->core.height; prep.canvas_width = child->core.width; prep.canvas_height = child->core.height; XtCallCallbackList ((Widget)pw, pw->porthole.report_callbacks, (XtPointer) &prep); } } static void layout_child (pw, child, geomp, xp, yp, widthp, heightp) PortholeWidget pw; Widget child; XtWidgetGeometry *geomp; Position *xp, *yp; Dimension *widthp, *heightp; { Position minx, miny; *xp = child->core.x; /* default to current values */ *yp = child->core.y; *widthp = child->core.width; *heightp = child->core.height; if (geomp) { /* mix in any requested changes */ if (geomp->request_mode & CWX) *xp = geomp->x; if (geomp->request_mode & CWY) *yp = geomp->y; if (geomp->request_mode & CWWidth) *widthp = geomp->width; if (geomp->request_mode & CWHeight) *heightp = geomp->height; } /* * Make sure that the child is at least as large as the porthole; there * is no maximum size. */ if (*widthp < pw->core.width) *widthp = pw->core.width; if (*heightp < pw->core.height) *heightp = pw->core.height; /* * Make sure that the child is still on the screen. Note that this must * be done *after* the size computation so that we know where to put it. */ minx = ((Position) pw->core.width) - ((Position) *widthp); miny = ((Position) pw->core.height) - ((Position) *heightp); if (*xp < minx) *xp = minx; /* keep at lower right corner */ if (*yp < miny) *yp = miny; if (*xp > 0) *xp = 0; /* keep at upper left corner */ if (*yp > 0) *yp = 0; } /***************************************************************************** * * * Porthole Widget Class Methods * * * *****************************************************************************/ static void Realize (gw, valueMask, attributes) register Widget gw; Mask *valueMask; XSetWindowAttributes *attributes; { attributes->bit_gravity = NorthWestGravity; *valueMask |= CWBitGravity; if (gw->core.width < 1) gw->core.width = 1; if (gw->core.height < 1) gw->core.height = 1; (*portholeWidgetClass->core_class.superclass->core_class.realize) (gw, valueMask, attributes); } static void Resize (gw) Widget gw; { PortholeWidget pw = (PortholeWidget) gw; Widget child = find_child (pw); /* * If we have a child, we need to make sure that it is at least as big * as we are and in the right place. */ if (child) { Position x, y; Dimension width, height; layout_child (pw, child, NULL, &x, &y, &width, &height); XtConfigureWidget (child, x, y, width, height, (Dimension) 0); } SendReport (pw, (unsigned int) (XawPRCanvasWidth | XawPRCanvasHeight)); } static XtGeometryResult QueryGeometry (gw, intended, preferred) Widget gw; XtWidgetGeometry *intended, *preferred; { register PortholeWidget pw = (PortholeWidget) gw; Widget child = find_child (pw); if (child) { #define SIZEONLY (CWWidth | CWHeight) preferred->request_mode = SIZEONLY; preferred->width = child->core.width; preferred->height = child->core.height; if (((intended->request_mode & SIZEONLY) == SIZEONLY) && intended->width == preferred->width && intended->height == preferred->height) return XtGeometryYes; else if (preferred->width == pw->core.width && preferred->height == pw->core.height) return XtGeometryNo; else return XtGeometryAlmost; #undef SIZEONLY } return XtGeometryNo; } static XtGeometryResult GeometryManager (w, req, reply) Widget w; XtWidgetGeometry *req, *reply; { PortholeWidget pw = (PortholeWidget) w->core.parent; Widget child = find_child (pw); Boolean okay = TRUE; if (child != w) return XtGeometryNo; /* unknown child */ *reply = *req; /* assume we'll grant everything */ if ((req->request_mode & CWBorderWidth) && req->border_width != 0) { reply->border_width = 0; /* require border width of 0 */ okay = FALSE; } layout_child (pw, child, req, &reply->x, &reply->y, &reply->width, &reply->height); if ((req->request_mode & CWX) && req->x != reply->x) okay = FALSE; if ((req->request_mode & CWY) && req->x != reply->x) okay = FALSE; if ((req->request_mode & CWWidth) && req->width != reply->width) okay = FALSE; if ((req->request_mode & CWHeight) && req->height != reply->height) okay = FALSE; /* * If we failed on anything, simply return without touching widget */ if (!okay) return XtGeometryAlmost; /* * If not just doing a query, update widget and send report. Note that * we will often set fields that weren't requested because we want to keep * the child visible. */ if (!(req->request_mode & XtCWQueryOnly)) { unsigned int changed = 0; if (child->core.x != reply->x) { changed |= XawPRSliderX; child->core.x = reply->x; } if (child->core.y != reply->y) { changed |= XawPRSliderY; child->core.y = reply->y; } if (child->core.width != reply->width) { changed |= XawPRSliderWidth; child->core.width = reply->width; } if (child->core.height != reply->height) { changed |= XawPRSliderHeight; child->core.height = reply->height; } if (changed) SendReport (pw, changed); } return XtGeometryYes; /* success! */ } static void ChangeManaged (gw) Widget gw; { PortholeWidget pw = (PortholeWidget) gw; Widget child = find_child (pw); /* ignore extra children */ if (child) { if (!XtIsRealized (gw)) { XtWidgetGeometry geom, retgeom; geom.request_mode = 0; if (pw->core.width == 0) { geom.width = child->core.width; geom.request_mode |= CWWidth; } if (pw->core.height == 0) { geom.height = child->core.height; geom.request_mode |= CWHeight; } if (geom.request_mode && XtMakeGeometryRequest (gw, &geom, &retgeom) == XtGeometryAlmost) { (void) XtMakeGeometryRequest (gw, &retgeom, NULL); } } XtResizeWidget (child, Max (child->core.width, pw->core.width), Max (child->core.height, pw->core.height), 0); SendReport (pw, (unsigned int) XawPRAll); } } axe-6.1.2.orig/Widgets/Preference.c100644 243 144 31613 5600335246 15645 0ustar joostusers/* * Copyright 1992, 1994 The University of Newcastle upon Tyne * * Permission to use, copy, modify and distribute this software and its * documentation for any purpose other than its commercial exploitation * is hereby granted without fee, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of The University of Newcastle upon Tyne not be used in * advertising or publicity pertaining to distribution of the software * without specific, written prior permission. The University of * Newcastle upon Tyne makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * THE UNIVERSITY OF NEWCASTLE UPON TYNE DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF * NEWCASTLE UPON TYNE BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. * * Author: Jim Wight (j.k.wight@newcastle.ac.uk) * Department of Computing Science * University of Newcastle upon Tyne, UK */ #include #include #include #include #include #include #include #include #define PRIVATE(w,field) (((PreferenceWidget) w)->preference.field) #define TableOffset(field) XtOffsetOf(PreferenceRec, table.field) #define Offset(field) XtOffsetOf(PreferenceRec, preference.field) static char layout[] = "lscroll 0 0; bscroll 1 0; \ lwrap 0 1; bwrap 1 1; \ ledmode 0 2; bedmode 1 2; \ ltabs 0 3; btabs 1 3; \ lapply 0 5; bapply 1 5; \ accept 0 6;"; static XtResource resources[] = { /* Table Widget Resources */ { XtNlayout, XtCLayout, XtRXpTableLoc, sizeof(XpTableLoc), TableOffset(default_layout), XtRString, (XtPointer) layout }, /* Preference Widget Resources */ {XtNenterCallback, XtCCallback, XtRCallback, sizeof(XtCallbackList), Offset(enter_callbacks), XtRCallback, (XtPointer) NULL}, {XtNcancelCallback, XtCCallback, XtRCallback, sizeof(XtCallbackList), Offset(cancel_callbacks), XtRCallback, (XtPointer) NULL}, }; #undef Offset static void Initialize(); static void AutoFill(), NoAutoFill(), Ready(), Accept(), Cancel(); PreferenceClassRec preferenceClassRec = { { /* superclass */ (WidgetClass) &xpTableClassRec, /* class_name */ "Preference", /* size */ sizeof(PreferenceRec), /* class_initialize */ NULL, /* class_part_initialize */ NULL, /* class_inited */ FALSE, /* initialize */ Initialize, /* initialize_hook */ NULL, /* realize */ XtInheritRealize, /* actions */ NULL, /* num_actions */ 0, /* resources */ resources, /* resource_count */ XtNumber(resources), /* xrm_class */ NULLQUARK, /* compress_motion */ FALSE, /* compress_exposure */ TRUE, /* compress_enterleave */ TRUE, /* visible_interest */ FALSE, /* destroy */ NULL, /* resize */ XtInheritResize, /* expose */ XtInheritExpose, /* set_values */ NULL, /* set_values_hook */ NULL, /* set_values_almost */ XtInheritSetValuesAlmost, /* get_values_hook */ NULL, /* accept_focus */ NULL, /* version */ XtVersion, /* callback_private */ NULL, /* tm_table */ XtInheritTranslations, /* query_geometry */ XtInheritQueryGeometry, /* display_accelerator */ XtInheritDisplayAccelerator, /* extension */ NULL },/* CoreClass fields initialization */ { /* composite class fields */ /* geometry_manager */ XtInheritGeometryManager, /* change_managed */ XtInheritChangeManaged, /* insert_child */ XtInheritInsertChild, /* delete_child */ XtInheritDeleteChild, /* extension */ NULL },/* CompositeClass fields initialization */ { /* extension */ NULL, },/* TableClass fields initialization */ { /* extension */ NULL, },/* PreferenceClass fields initialization */ }; WidgetClass preferenceWidgetClass = (WidgetClass) &preferenceClassRec; /* ARGSUSED */ static void Initialize(req, new, args, num_args) Widget req, new; ArgList args; Cardinal *num_args; { Widget bscroll, bwrap, bedmode, btabs; Widget bapply, accept, enter, cancel; /* The parent is a popup and its parent is an AxeText widget */; XtAddCallback(XtParent(new), XtNpopupCallback, Ready, (XtPointer) new); XtVaCreateManagedWidget("lscroll", labelWidgetClass, new, NULL); bscroll = XtVaCreateManagedWidget("bscroll", boxWidgetClass, new, NULL); PRIVATE(new,alwaysScroll) = XtVaCreateManagedWidget("Always", toggleWidgetClass, bscroll, NULL); PRIVATE(new,neededScroll) = XtVaCreateManagedWidget("When Needed", toggleWidgetClass, bscroll, XtNradioGroup, PRIVATE(new,alwaysScroll), NULL); PRIVATE(new,neverScroll) = XtVaCreateManagedWidget("Never", toggleWidgetClass, bscroll, XtNradioGroup, PRIVATE(new,alwaysScroll), NULL); XtVaCreateManagedWidget("lwrap", labelWidgetClass, new, NULL); bwrap = XtVaCreateManagedWidget("bwrap", boxWidgetClass, new, NULL); PRIVATE(new,lineWrap) = XtVaCreateManagedWidget("Line", toggleWidgetClass, bwrap, NULL); XtAddCallback(PRIVATE(new,lineWrap), XtNcallback, NoAutoFill, (XtPointer) new); PRIVATE(new,wordWrap) = XtVaCreateManagedWidget("Word", toggleWidgetClass, bwrap, XtNradioGroup, PRIVATE(new,lineWrap), NULL); XtAddCallback(PRIVATE(new,wordWrap), XtNcallback, NoAutoFill, (XtPointer) new); PRIVATE(new,noWrap) = XtVaCreateManagedWidget("No Wrap", toggleWidgetClass, bwrap, XtNradioGroup, PRIVATE(new,lineWrap), NULL); PRIVATE(new,autoFill) = XtVaCreateManagedWidget("autoFill", toggleWidgetClass, bwrap, NULL); XtAddCallback(PRIVATE(new,autoFill), XtNcallback, AutoFill, (XtPointer) new); XtVaCreateManagedWidget("ledmode", labelWidgetClass, new, NULL); bedmode = XtVaCreateManagedWidget("bedmode", boxWidgetClass, new, NULL); PRIVATE(new,write) = XtVaCreateManagedWidget("Write", toggleWidgetClass, bedmode, NULL); PRIVATE(new,read) = XtVaCreateManagedWidget("Read", toggleWidgetClass, bedmode, XtNradioGroup, PRIVATE(new,write), NULL); XtVaCreateManagedWidget("ltabs", labelWidgetClass, new, NULL); btabs = XtVaCreateManagedWidget("btabs", boxWidgetClass, new, NULL); PRIVATE(new,tabEvery) = XtVaCreateManagedWidget("tabEvery", axeiiTextWidgetClass, btabs, XtNrows, 1, XtNcolumns, 2, XtNeditType, XawtextEdit, NULL); XtSetKeyboardFocus(new, PRIVATE(new,tabEvery)); XtVaCreateManagedWidget("lapply", labelWidgetClass, new, NULL); bapply = XtVaCreateManagedWidget("bapply", boxWidgetClass, new, NULL); PRIVATE(new,thisBuffer) = XtVaCreateManagedWidget("This Buffer", toggleWidgetClass, bapply, NULL); PRIVATE(new,thisWindow) = XtVaCreateManagedWidget("This Window", toggleWidgetClass, bapply, XtNradioGroup, PRIVATE(new,thisBuffer), XtNsensitive, False, NULL); PRIVATE(new,allWindows) = XtVaCreateManagedWidget("All Windows", toggleWidgetClass, bapply, XtNradioGroup, PRIVATE(new,thisBuffer), XtNsensitive, False, NULL); accept = XtVaCreateManagedWidget("accept", boxWidgetClass, new, NULL); enter = XtVaCreateManagedWidget("Enter", commandWidgetClass, accept, NULL); XtAddCallback(enter, XtNcallback, Accept, (XtPointer) new); cancel = XtVaCreateManagedWidget("Cancel", commandWidgetClass, accept, NULL); XtAddCallback(cancel, XtNcallback, Cancel, (XtPointer) new); } /* ARGSUSED */ static void AutoFill(widget, client_data, call_data) Widget widget; XtPointer client_data, call_data; { Widget noWrap = PRIVATE((Widget) client_data,noWrap); Boolean autoFill; XtPointer radioData; XtVaGetValues(widget, XtNstate, &autoFill, NULL); if (autoFill) { XtVaGetValues(noWrap, XtNradioData, &radioData, NULL); XawToggleSetCurrent(noWrap, radioData); } } /* ARGSUSED */ static void NoAutoFill(widget, client_data, call_data) Widget widget; XtPointer client_data, call_data; { Boolean state; XtVaGetValues(widget, XtNstate, &state, NULL); if (state) { XtVaSetValues(PRIVATE(((Widget) client_data),autoFill), XtNstate, False, NULL); } } /* ARGSUSED */ static void Ready(widget, client_data, call_data) Widget widget; XtPointer client_data, call_data; { Widget axeText = AxeTextWidgetParentOf(widget), nominator; Widget pref = (Widget) client_data; XawTextScrollMode scroll; XawTextWrapMode wrap; Boolean fill; XawTextEditType edit; int every; char buf[8]; XtVaGetValues(axeText, XtNscrollVertical, &scroll, XtNwrap, &wrap, XtNautoFill, &fill, XtNeditType, &edit, XtNtabEvery, &every, NULL); XtVaSetValues(scroll == XawtextScrollAlways ? PRIVATE(pref,alwaysScroll) : scroll == XawtextScrollWhenNeeded ? PRIVATE(pref,neededScroll) : PRIVATE(pref,neverScroll), XtNstate, True, NULL); XtVaSetValues(wrap == XawtextWrapLine ? PRIVATE(pref,lineWrap) : wrap == XawtextWrapWord? PRIVATE(pref,wordWrap) : PRIVATE(pref,noWrap), XtNstate, True, NULL); XtVaSetValues(PRIVATE(pref,autoFill), XtNstate, fill, NULL); XtVaSetValues(edit == XawtextEdit ? PRIVATE(pref,write) : PRIVATE(pref,read), XtNstate, True, NULL); sprintf(buf, "%d", every); XtVaSetValues(PRIVATE(pref,tabEvery), XtNstring, buf, NULL); XtVaSetValues(PRIVATE(pref,thisBuffer), XtNstate, True, NULL); } /* ARGSUSED */ static void Accept(widget, client_data, call_data) Widget widget; XtPointer client_data, call_data; { Widget pref; PreferenceReturnStruct preferences; String scroll, wrap, edit, tabs; pref = (Widget) client_data; scroll = XawToggleGetCurrent(PRIVATE(pref,alwaysScroll)); if (strcmp(scroll, "Always") == 0) { preferences.scrollMode = XawtextScrollAlways; } else if(strcmp(scroll, "When Needed") == 0) { preferences.scrollMode = XawtextScrollWhenNeeded; } else { preferences.scrollMode = XawtextScrollNever; } wrap = (String) XawToggleGetCurrent(PRIVATE(pref,lineWrap)); if (strcmp(wrap, "Line") == 0) { preferences.wrapMode = XawtextWrapLine; } else if (strcmp(wrap, "Word") == 0) { preferences.wrapMode = XawtextWrapWord; } else { preferences.wrapMode = XawtextWrapNever; } XtVaGetValues(PRIVATE(pref,autoFill), XtNstate, &preferences.autoFill, NULL); edit = XawToggleGetCurrent(PRIVATE(pref,write)); if (strcmp(edit, "Write") == 0) { preferences.editType = XawtextEdit; } else { preferences.editType = XawtextRead; } XtVaGetValues(PRIVATE(pref,tabEvery), XtNstring, &tabs, NULL); preferences.tabEvery = atoi(tabs); XtCallCallbackList(pref, PRIVATE(pref,enter_callbacks), (XtPointer) &preferences); } /* ARGSUSED */ static void Cancel(widget, client_data, call_data) Widget widget; XtPointer client_data, call_data; { Widget pref = XtParent(XtParent(widget)); XtCallCallbackList(pref, PRIVATE(pref,cancel_callbacks), (XtPointer) 0); } axe-6.1.2.orig/Widgets/Preference.h100644 243 144 4026 5550557123 15634 0ustar joostusers/* * Copyright 1992 The University of Newcastle upon Tyne * * Permission to use, copy, modify and distribute this software and its * documentation for any purpose other than its commercial exploitation * is hereby granted without fee, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of The University of Newcastle upon Tyne not be used in * advertising or publicity pertaining to distribution of the software * without specific, written prior permission. The University of * Newcastle upon Tyne makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * THE UNIVERSITY OF NEWCASTLE UPON TYNE DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF * NEWCASTLE UPON TYNE BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. * * Author: Jim Wight (j.k.wight@newcastle.ac.uk) * Department of Computing Science * University of Newcastle upon Tyne, UK */ #ifndef _Preference_h #define _Preference_h #include #include extern WidgetClass preferenceWidgetClass; typedef struct _PreferenceClassRec *PreferenceWidgetClass; typedef struct _PreferenceRec *PreferenceWidget; typedef struct { XawTextScrollMode scrollMode; XawTextWrapMode wrapMode; Boolean autoFill; XawTextEditType editType; int tabEvery; } PreferenceReturnStruct; #define XtNenterCallback "enterCallback" #define XtNcancelCallback "cancelCallback" #endif /* _Preference_h */ axe-6.1.2.orig/Widgets/PreferenceP.h100644 243 144 5070 5550557123 15754 0ustar joostusers/* * Copyright 1992 The University of Newcastle upon Tyne * * Permission to use, copy, modify and distribute this software and its * documentation for any purpose other than its commercial exploitation * is hereby granted without fee, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of The University of Newcastle upon Tyne not be used in * advertising or publicity pertaining to distribution of the software * without specific, written prior permission. The University of * Newcastle upon Tyne makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * THE UNIVERSITY OF NEWCASTLE UPON TYNE DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF * NEWCASTLE UPON TYNE BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. * * Author: Jim Wight (j.k.wight@newcastle.ac.uk) * Department of Computing Science * University of Newcastle upon Tyne, UK */ #ifndef _PreferenceP_h #define _PreferenceP_h #include #include typedef struct _PreferenceClass { XtPointer extension; } PreferenceClassPart; typedef struct _PreferenceClassRec { CoreClassPart core_class; CompositeClassPart composite_class; XpTableClassPart table_class; PreferenceClassPart preference_class; } PreferenceClassRec; extern PreferenceClassRec preferenceClassRec; typedef struct _PreferencePart { /* resources */ XtCallbackList enter_callbacks; XtCallbackList cancel_callbacks; /* private variables */ Widget alwaysScroll, neededScroll, neverScroll; Widget lineWrap, wordWrap, noWrap, autoFill; Widget read, write; Widget tabEvery; Widget thisBuffer, thisWindow, allWindows; } PreferencePart; typedef struct _PreferenceRec { CorePart core; CompositePart composite; XpTablePart table; PreferencePart preference; } PreferenceRec; #endif /* _PreferenceP_h */ axe-6.1.2.orig/Widgets/ScrollText.c100644 243 144 21213 5550557115 15672 0ustar joostusers/* * Copyright 1992, 1994 The University of Newcastle upon Tyne * * Permission to use, copy, modify and distribute this software and its * documentation for any purpose other than its commercial exploitation * is hereby granted without fee, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of The University of Newcastle upon Tyne not be used in * advertising or publicity pertaining to distribution of the software * without specific, written prior permission. The University of * Newcastle upon Tyne makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * THE UNIVERSITY OF NEWCASTLE UPON TYNE DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF * NEWCASTLE UPON TYNE BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. * * Author: Jim Wight (j.k.wight@newcastle.ac.uk) * Department of Computing Science * University of Newcastle upon Tyne, UK */ #include #include #include #include #define CLASS(field) scrollingTextClassRec.scrolling_text_class.field #define PRIVATE(w,field) (((ScrollingTextWidget) w)->scrollingText.field) static XtResource resources[] = { #define Offset(field) XtOffsetOf(ScrollingTextRec, scrollingText.field) { XtNscrollOnMovement, XtCScrollOnMovement, XtRBoolean, sizeof(Boolean), Offset(scroll_on_movement), XtRImmediate, (XtPointer) True }, { XtNtextWidget, XtCTextWidget, XtRWidget, sizeof(Widget), Offset(text_widget), XtRImmediate, (XtPointer) NULL }, #undef Offset }; static void ClassInitialize(), Initialize(), Destroy(); static Boolean SetValues(); static void AdjustForMovement(), AdjustForChange(); static Boolean AfterAction(); static char translations[] = "Return:no-op() \n Linefeed:no-op()"; ScrollingTextClassRec scrollingTextClassRec = { { /* core fields */ /* superclass */ (WidgetClass) &portholeClassRec, /* class_name */ "ScrollingText", /* widget_size */ sizeof(ScrollingTextRec), /* class_initialize */ ClassInitialize, /* class_part_initialize */ NULL, /* class_inited */ FALSE, /* initialize */ Initialize, /* initialize_hook */ NULL, /* realize */ XtInheritRealize, /* actions */ NULL, /* num_actions */ 0, /* resources */ resources, /* num_resources */ XtNumber(resources), /* xrm_class */ NULLQUARK, /* compress_motion */ TRUE, /* compress_exposure */ TRUE, /* compress_enterleave */ TRUE, /* visible_interest */ FALSE, /* destroy */ Destroy, /* resize */ XtInheritResize, /* expose */ NULL, /* set_values */ SetValues, /* set_values_hook */ NULL, /* set_values_almost */ XtInheritSetValuesAlmost, /* get_values_hook */ NULL, /* accept_focus */ NULL, /* version */ XtVersion, /* callback_private */ NULL, /* tm_table */ NULL, /* query_geometry */ XtInheritQueryGeometry, /* display_accelerator */ XtInheritDisplayAccelerator, /* extension */ NULL }, { /* composite fields */ /* geometry_manager */ XtInheritGeometryManager, /* change_managed */ XtInheritChangeManaged, /* insert_child */ XtInheritInsertChild, /* delete_child */ XtInheritDeleteChild, /* extension */ NULL }, { /* porthole fields */ /* ignore */ 0 }, { /* scrollingText fields */ /* extension */ NULL }, }; WidgetClass scrollingTextWidgetClass = (WidgetClass) &scrollingTextClassRec; static void ClassInitialize() { CLASS(translations) = XtParseTranslationTable(translations); } /* ARGSUSED */ static void Initialize(req, new, args, num_args) Widget req, new; ArgList args; Cardinal *num_args; { XFontStruct *font; Dimension width, height; Widget text = PRIVATE(new,text_widget) = XtVaCreateManagedWidget("text", asciiTextWidgetClass, new, NULL); XtOverrideTranslations(text, CLASS(translations)); XtAddCallback(XawTextGetSource(text), XtNcallback, AdjustForChange, NULL); if (PRIVATE(new,scroll_on_movement)) { PRIVATE(new,action_hook) = XtAppAddActionHook(XtWidgetToApplicationContext(new), AdjustForMovement, (XtPointer) text); } else { PRIVATE(new,action_hook) = (XtActionHookId) 0; } XtVaGetValues(text, XtNfont, &font, XtNwidth, &width, XtNheight, &height, NULL); PRIVATE(new,font_width) = font->max_bounds.width; if (!new->core.width) { new->core.width = width; } if (!new->core.height) { new->core.height = height; } PRIVATE(new,work_proc) = (XtWorkProcId) 0; } /* ARGSUSED */ static Boolean SetValues(old, request, new, args, num_args) Widget old, request, new; ArgList args; Cardinal *num_args; { if (PRIVATE(old,scroll_on_movement) != PRIVATE(new,scroll_on_movement)) { if (PRIVATE(new,scroll_on_movement)) { PRIVATE(new,action_hook) = XtAppAddActionHook (XtWidgetToApplicationContext(new), AdjustForMovement, (XtPointer) PRIVATE(new,text_widget)); } else { XtRemoveActionHook(PRIVATE(new,action_hook)); PRIVATE(new,action_hook) = (XtActionHookId) 0; } } return False; } static void Destroy(w) Widget w; { if (PRIVATE(w,action_hook)) { XtRemoveActionHook(PRIVATE(w,action_hook)); } } /* ARGSUSED */ static void AdjustForMovement(widget, client_data, action, event, params, num_params) Widget widget; XtPointer client_data; String action; XEvent *event; String *params; Cardinal *num_params; { Widget text = (Widget) client_data; if (widget != text) { return; } /* * This routine gets called before the action takes place so set * up a work proc to do the work after the action has taken place */ if (strcmp(action, "forward-character") == 0 || strcmp(action, "backward-character") == 0 || strcmp(action, "forward-word") == 0 || strcmp(action, "backward-word") == 0 || strcmp(action, "beginning-of-line") == 0 || strcmp(action, "end-of-line") == 0) { /* * Positioning with the mouse results in work_proc being corrupted with * the result that the test fails and scrolling stops happening. I don't * understand what is going on. Therefore, for the time being always * register a work proc. It is probably unlikely that events will come * in fast enough anyway for there to be an unexecuted one still around. if (!PRIVATE(text,work_proc)) { */ PRIVATE(text,work_proc) = XtAppAddWorkProc(XtWidgetToApplicationContext(widget), AfterAction, (XtPointer) widget); /* } */ } } static Boolean AfterAction(client_data) XtPointer client_data; { Widget text = (Widget) client_data; AdjustForChange(XawTextGetSource(text), (XtPointer) 0, (XtPointer) 0); PRIVATE(text,work_proc) = (XtWorkProcId) 0; return True; } /* ARGSUSED */ static void AdjustForChange(widget, client_data, call_data) Widget widget; XtPointer client_data, call_data; { Widget source, sink, text = XtParent(widget), porthole = XtParent(text); Position x, prevx, top; Dimension lm, width, phwidth, fwidth = PRIVATE(porthole,font_width); XawTextPosition pos, eol, junk; int pd, ed, pc, ec, morejunk; XtVaGetValues(text, XtNtextSource, &source, XtNtextSink, &sink, XtNleftMargin, &lm, XtNx, &prevx, NULL); XtVaGetValues(porthole, XtNwidth, &phwidth, NULL); top = phwidth - fwidth - fwidth; pos = XawTextGetInsertionPoint(text); eol = XawTextSourceScan(source, pos, XawstAll, XawsdRight, 1, True); /* Calculations of pd and ed take tabs into account */ XawTextSinkFindDistance(sink, 0, lm, pos, &pd, &junk, &morejunk); XawTextSinkFindDistance(sink, 0, lm, eol, &ed, &junk, &morejunk); if (pd > top - prevx) { x = top - pd; } else if (pd < fwidth - prevx) { x = fwidth - pd; } else { x = prevx; } /* Stretch widget to eliminate solid block at end of line */ width = ed + fwidth; XtVaSetValues(text, XtNx, x, XtNwidth, width, NULL); } #undef PRIVATE #undef CLASS axe-6.1.2.orig/Widgets/ScrollText.h100644 243 144 3616 5550557124 15666 0ustar joostusers/* * Copyright 1992 The University of Newcastle upon Tyne * * Permission to use, copy, modify and distribute this software and its * documentation for any purpose other than its commercial exploitation * is hereby granted without fee, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of The University of Newcastle upon Tyne not be used in * advertising or publicity pertaining to distribution of the software * without specific, written prior permission. The University of * Newcastle upon Tyne makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * THE UNIVERSITY OF NEWCASTLE UPON TYNE DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF * NEWCASTLE UPON TYNE BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. * * Author: Jim Wight (j.k.wight@newcastle.ac.uk) * Department of Computing Science * University of Newcastle upon Tyne, UK */ #ifndef _XawScrollingText_h #define _XawScrollingText_h #include extern WidgetClass scrollingTextWidgetClass; typedef struct _ScrollingTextClassRec *ScrollingTextWidgetClass; typedef struct _ScrollingTextRec *ScrollingTextWidget; #define XtNscrollOnMovement "scrollOnMovement" #define XtCScrollOnMovement "ScrollOnMovement" #define XtNtextWidget "textWidget" #define XtCTextWidget "TextWidget" #endif /* _ScrollingText_h */ axe-6.1.2.orig/Widgets/ScrollTextP.h100644 243 144 4663 5550557124 16011 0ustar joostusers/* * Copyright 1992 The University of Newcastle upon Tyne * * Permission to use, copy, modify and distribute this software and its * documentation for any purpose other than its commercial exploitation * is hereby granted without fee, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of The University of Newcastle upon Tyne not be used in * advertising or publicity pertaining to distribution of the software * without specific, written prior permission. The University of * Newcastle upon Tyne makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * THE UNIVERSITY OF NEWCASTLE UPON TYNE DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF * NEWCASTLE UPON TYNE BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. * * Author: Jim Wight (j.k.wight@newcastle.ac.uk) * Department of Computing Science * University of Newcastle upon Tyne, UK */ #ifndef _ScrollingTextP_h #define _ScrollingTextP_h #include #include typedef struct { XtPointer extension; XtTranslations translations; } ScrollingTextClassPart; typedef struct _ScrollingTextClassRec { CoreClassPart core_class; CompositeClassPart composite_class; PortholeClassPart porthole_class; ScrollingTextClassPart scrolling_text_class; } ScrollingTextClassRec; extern ScrollingTextClassRec scrollingTextClassRec; typedef struct { /* new fields in widget */ /* resources... */ Boolean scroll_on_movement; Widget text_widget; /* private data... */ int font_width; XtActionHookId action_hook; XtWorkProcId work_proc; } ScrollingTextPart; typedef struct _ScrollingTextRec { CorePart core; CompositePart composite; PortholePart porthole; ScrollingTextPart scrollingText; } ScrollingTextRec; #endif /* _ScrollingTextP_h */ axe-6.1.2.orig/Widgets/Table.c100644 243 144 210530 5550557115 14640 0ustar joostusers/*LINTLIBRARY*/ /* * SCCS_data: %Z% %M% %I% %E% %U% * * XpTable - Forms-based composite widget/geometry manager * Class heirarchy: * Core * Composite * XpTable * * Originally implemented by: * David Harrison * University of California, Berkeley * 1989 * * Completely re-implemented by: * David.Smyth@SniAp.MchP.SNI.De */ /* Edit History 25Oct92 david Geometry management re-work 01Feb92 david Re-Implementation */ #include #include #ifdef sun #include /* why don't they just use X from mit!?! */ #include #endif #include #include /* For backward compatibility with old Xt releases **=================================================** */ #ifndef XtIsWidget #ifdef XtSpecificationRelease #define XtIsWidget(obj) XtIsSubclass(obj,(WidgetClass)coreWidgetClass) #else #define XtIsWidget(obj) XtIsSubclass(obj,(WidgetClass)widgetClass) #endif #endif #ifndef XtSpecificationRelease #if NeedFunctionPrototypes typedef void* XtPointer; #else typedef char* XtPointer; #endif #endif /* Resources **===========** */ #ifdef XtOffsetOf #define OFFSET(field) XtOffsetOf(XpTableRec,table.field) #else #define OFFSET(field) XtOffset(XpTableWidget,table.field) #endif static XtResource resources[] = { { XtNdefaultOptions, XtCDefaultOptions, XtRXpTableOpts, sizeof(XpTableOpts), OFFSET(default_options), XtRImmediate, (XtPointer)0 }, { XtNlayout, XtCLayout, XtRXpTableLoc, sizeof(XpTableLoc), OFFSET(default_layout), XtRXpTableLoc, (XtPointer)0 }, { XtNsameWidth, XtCSameSize, XtRXrmNameListLists, sizeof(XrmNameListLists), OFFSET(same_width), XtRXrmNameListLists, (XtPointer)0 }, { XtNsameHeight, XtCSameSize, XtRXrmNameListLists, sizeof(XrmNameListLists), OFFSET(same_height), XtRXrmNameListLists, (XtPointer)0 }, { XtNsameBorder, XtCSameSize, XtRXrmNameListLists, sizeof(XrmNameListLists), OFFSET(same_border), XtRXrmNameListLists, (XtPointer)0 }, { XtNforceShrink, XtCForceShrink, XtRBoolean, sizeof(Boolean), OFFSET(force_shrink), XtRImmediate, (XtPointer)True }, { XtNshrinkSimple, XtCShrinkSimple, XtRBoolean, sizeof(Boolean), /*OBS*/ OFFSET(shrink_simple), XtRImmediate, (XtPointer)True }, /*OBS*/ { XtNcolumnSpacing, XtCSpacing, XtRInt, sizeof(int), OFFSET(col_spacing), XtRImmediate, (XtPointer)0 }, { XtNrowSpacing, XtCSpacing, XtRInt, sizeof(int), OFFSET(row_spacing), XtRImmediate, (XtPointer)0 }, { XtNmarginWidth, XtCMargins, XtRInt, sizeof(int), OFFSET(margin_width), XtRImmediate, (XtPointer)0 }, { XtNmarginHeight, XtCMargins, XtRInt, sizeof(int), OFFSET(margin_height), XtRImmediate, (XtPointer)0 }, }; #undef OFFSET /* Core Class Methods **====================** */ static void XpTableClassInitialize (); static void XpTableInitialize _(( Widget, Widget, ArgList, Cardinal* )); static void XpTableDestroy _(( Widget )); static void XpTableResize _(( Widget )); #ifdef XtSpecificationRelease static Boolean XpTableSetValues _(( Widget, Widget, Widget, ArgList, Cardinal* )); #else static Boolean XpTableSetValues _(( Widget, Widget, Widget )); #endif static XtGeometryResult XpTableQueryGeometry _(( Widget, XtWidgetGeometry*, XtWidgetGeometry* )); /* Composite class methods **=========================** */ static XtGeometryResult XpTableGeometryManager _(( Widget /*child*/, XtWidgetGeometry*, XtWidgetGeometry* )); static void XpTableChangeManaged _(( Widget )); XpTableClassRec xpTableClassRec = { { /* core_class fields */ /* superclass */ (WidgetClass)&compositeClassRec, /* class_name */ "XpTable", /* widget_size */ sizeof(XpTableRec), /* class_initialize */ XpTableClassInitialize, /* class_part_initialize */ NULL, /* class_inited */ FALSE, /* initialize */ XpTableInitialize, /* initialize_hook */ NULL, /* realize */ XtInheritRealize, /* actions */ NULL, /* num_actions */ 0, /* resources */ resources, /* num_resources */ XtNumber(resources), /* xrm_class */ NULLQUARK, /* compress_motion */ False, /* compress_exposure */ TRUE, /* compress_enterleave */ False, /* visible_interest */ FALSE, /* destroy */ XpTableDestroy, /* resize */ XpTableResize, /* expose */ XtInheritExpose, /* set_values */ XpTableSetValues, /* set_values_hook */ NULL, /* set_values_almost */ XtInheritSetValuesAlmost, /* get_values_hook */ NULL, /* accept_focus */ NULL, /* version */ XtVersion, /* callback_private */ NULL, /* tm_table */ XtInheritTranslations, /* query_geometry */ XpTableQueryGeometry, /* display_accelerator */ NULL, /* extension */ NULL }, { /* composite_class fields */ /* geometry_manager */ XpTableGeometryManager, /* change_managed */ XpTableChangeManaged, /* insert_child */ XtInheritInsertChild, /* delete_child */ XtInheritDeleteChild, /* extension */ NULL }, { /* table_class fields */ /* extension */ NULL } }; WidgetClass xpTableWidgetClass = (WidgetClass) &xpTableClassRec; /* Converters **============** */ /* Convert String to TableOpts **=============================** Converts a string representation into a TableOpts, which is small enough to fit entirely into the to->addr. */ /*ARGSUSED*/ void XpCvtStrToXpTableOpts( args, num_args, from, to ) XrmValue* args; /* Arguments to converter */ Cardinal* num_args; /* Number of arguments */ XrmValue* from; /* From type */ XrmValue* to; /* To type */ { static XpTableOpts opts; if (*num_args != 0) { XtErrorMsg("XpCvtStrToXpTableOpts", "wrongParameters", "XtToolkitError", "String to options takes no additional arguments", (String*)0, (Cardinal*)0); } opts = XpTableOptsParse( (String) from->addr ); if (opts == (XpTableOpts)0) XtStringConversionWarning( (String) from->addr, XtRXpTableOpts ); to->addr = (caddr_t) &opts; to->size = sizeof( XpTableOpts ); } /* Convert String to TableLocRec Array **=====================================** Converts a string representation into an array of TableLocRec structures (ie., TableLocRec*). This XtCalloc'd array is kept by the resource database: a COPY must be made by the widget. */ /*ARGSUSED*/ void XpCvtStrToXpTableLoc( args, num_args, from, to ) XrmValue* args; /* Arguments to converter */ Cardinal* num_args; /* Number of arguments */ XrmValue* from; /* From type */ XrmValue* to; /* To type */ { static XpTableLoc defLocs; if (*num_args != 0) { XtErrorMsg("XpCvtStrToXpTableLoc", "wrongParameters", "XtToolkitError", "String to layout takes no additional arguments", (String*)0, (Cardinal*)0); } defLocs = XpTableLocParse( (String) from->addr ); if (defLocs == (XpTableOpts)0) XtStringConversionWarning( (String) from->addr, XtRXpTableLoc ); to->addr = (caddr_t) &defLocs; to->size = sizeof(caddr_t); } /* Convert String to XrmNameList **===============================** Converts a string representation into a null-terminated array of XrmQuarks which will presumably name children widgets. This XtCalloc'd array is kept by the resource database: a COPY must be made by the widget. */ static XrmNameList XrmNameListParse _(( char*, char* )); static XrmNameListLists XrmNameListListsCopy _((XrmNameListLists)); /*ARGSUSED*/ void XpCvtStrToXrmNameListLists( args, num_args, from, to ) XrmValue* args; /* Arguments to converter */ Cardinal* num_args; /* Number of arguments */ XrmValue* from; /* From type */ XrmValue* to; /* To type */ { static XrmNameListLists listOfNameLists; if (*num_args != 0) { XtErrorMsg("XpCvtStrToXrmNameListLists", "wrongParameters", "XtToolkitError", "String to XrmNameListLists takes no additional arguments", (String*)0, (Cardinal*)0); } listOfNameLists = XrmNameListListsParse( (String) from->addr ); if (listOfNameLists == (XrmNameListLists)0) XtStringConversionWarning( (String) from->addr, XtRXrmNameListLists ); to->addr = (caddr_t) &listOfNameLists; to->size = sizeof(caddr_t); } #define LT_PAREN '(' #define RT_PAREN ')' XrmNameListLists XrmNameListListsParse( cp ) char* cp; { XrmNameList tempLists[1024]; /* lotsa possible lists... */ int numLists = 0; char* start; char* end; while ( *cp && isspace(*cp) ) ++cp; if ( *cp == LT_PAREN ) { /* More than one list */ while ( *cp == LT_PAREN ) { start = cp; /* start is LT_PAREN */ while ( *cp && *cp != RT_PAREN ) ++cp; end = cp; /* end is RT_PAREN or NUL */ tempLists[numLists++] = XrmNameListParse( start, end ); while ( *cp && *cp != LT_PAREN ) ++cp; } } else { /* exactly one list */ start = cp; /* start is not space, not LT_PAREN */ while (*cp) ++cp; end = cp; /* end is NUL */ tempLists[numLists++] = XrmNameListParse( start, end ); } if ( numLists > 0 ) { int i; XrmNameListLists retVal; retVal = (XrmNameListLists)XtCalloc( numLists+1, sizeof(XrmNameList) ); for ( i = 0 ; i < numLists ; ++i ) retVal[i] = tempLists[i]; return retVal; } return (XrmNameListLists)0; } #undef LT_PAREN #undef RT_PAREN /* Parse into an XtCalloc'd array of XrmNames ************************************************************************ start points to a LT_PAREN or to the 1st char of a name. end points to a RT_PAREN of a NUL. */ #define isname(c) (isalnum(c) || c == '_') static XrmNameList XrmNameListParse( start, end ) char* start; char* end; { XrmName tempList[1024]; /* may be lotsa kids */ int numNames = 0; char* cp = start; /* Get to first character of first name */ while ( cp < end && !isname(*cp) ) ++cp; while ( cp < end ) { char nameBuf[1024]; char* np = nameBuf; /* Get to first character of name */ while ( cp < end && !isname(*cp) ) ++cp; /* Collect name into buffer */ while ( cp < end && isname(*cp) ) *np++ = *cp++; *np = '\0'; tempList[numNames++] = XrmStringToQuark( nameBuf ); } if ( numNames > 0 ) { int i; XrmNameList retVal; retVal = (XrmNameList)XtCalloc( numNames+1, sizeof(XrmName) ); for ( i = 0 ; i < numNames ; ++i ) retVal[i] = tempList[i]; return retVal; } return (XrmNameList)0; } #undef isname static XrmNameListLists XrmNameListListsCopy( orig ) XrmNameListLists orig; { int list, name; XrmNameListLists copy; if ( orig == (XrmNameListLists)0 ) return (XrmNameListLists)0; for ( list = 0 ; orig[list] != (XrmNameList)0 ; ++list ) /*EMPTY*/; copy = (XrmNameListLists)XtCalloc( list+1, sizeof(XrmNameList) ); for ( list = 0 ; orig[list] != (XrmNameList)0 ; ++list ) { for ( name = 0 ; orig[list][name] != (XrmName)0 ; ++name ) /*EMPTY*/; copy[list] = (XrmNameList)XtCalloc( name+1, sizeof(XrmName) ); for ( name = 0 ; orig[list][name] != (XrmName)0 ; ++name ) copy[list][name] = orig[list][name]; } return copy; } void XrmNameListListsFree( old ) XrmNameListLists old; { int list; if ( old == (XrmNameListLists)0 ) return; for ( list = 0 ; old[list] != (XrmNameList)0 ; ++list ) XtFree( (char*)old[list] ); XtFree( (char*)old ); } /* Initialization Methods **========================** Note that no class part initialization is needed, as there are no inherited methods (yet?). */ static void XpTableClassInitialize() { XtAddConverter( XtRString, XtRXpTableOpts, XpCvtStrToXpTableOpts, (XtConvertArgList)0, 0 ); XtAddConverter( XtRString, XtRXpTableLoc, XpCvtStrToXpTableLoc, (XtConvertArgList)0, 0 ); XtAddConverter( XtRString, XtRXrmNameListLists, XpCvtStrToXrmNameListLists, (XtConvertArgList)0, 0 ); } /*ARGSUSED*/ static void XpTableInitialize( requestWidget, newWidget, args, num_args ) Widget requestWidget; /* as already set by Xt */ Widget newWidget; /* set up by this method */ ArgList args; Cardinal* num_args; { XpTableWidget tw = (XpTableWidget) newWidget; /* Copy resource values specified by pointer */ tw->table.default_layout = XpTableLocCopy( tw->table.default_layout); tw->table.same_width = XrmNameListListsCopy(tw->table.same_width); tw->table.same_height = XrmNameListListsCopy(tw->table.same_height); tw->table.same_border = XrmNameListListsCopy(tw->table.same_border); /* Initialize internally computed members */ tw->table.real_layout = (XpTableLoc)0; tw->table.num_cols = 0; tw->table.cols = (XpTableVector)0; tw->table.num_rows = 0; tw->table.rows = (XpTableVector)0; tw->table.resize_status = RSinit; tw->table.requesting_resize = False; tw->table.requesting_width = (Dimension)0; tw->table.requesting_height = (Dimension)0; tw->table.resize_child = (Widget)0; tw->table.resize_mode = (XtGeometryMask)0; tw->table.resize_width = (Dimension)0; tw->table.resize_height = (Dimension)0; tw->table.resize_border_width = (Dimension)0; tw->table.approved_child = (Widget)0; tw->table.approved_mode = (XtGeometryMask)0; tw->table.approved_width = (Dimension)0; tw->table.approved_height = (Dimension)0; tw->table.approved_border_width = (Dimension)0; tw->table.approved_cols = (XpTableVector)0; tw->table.approved_rows = (XpTableVector)0; tw->table.current_cols = (XpTableVector)0; tw->table.current_rows = (XpTableVector)0; tw->table.query_mode = (XtGeometryMask)0; tw->table.query_width = (Dimension)0; tw->table.query_height = (Dimension)0; tw->table.resize_table_to_size_pre_approved_by_parent = False; } /* Destroy Method **================** Free any instance data allocated for the TablePart members. */ static void XpTableDestroy( w ) Widget w; /* Widget to destroy */ { XpTableWidget tw = (XpTableWidget) w; XpTableLocFree( tw->table.default_layout ); XpTableLocFree( tw->table.real_layout ); XrmNameListListsFree( tw->table.same_width ); XrmNameListListsFree( tw->table.same_height ); XrmNameListListsFree( tw->table.same_border ); XpTableVectorFree( tw->table.cols ); XpTableVectorFree( tw->table.rows ); XpTableVectorFree( tw->table.approved_cols ); XpTableVectorFree( tw->table.approved_rows ); XpTableVectorFree( tw->table.current_cols ); XpTableVectorFree( tw->table.current_rows ); } /* Geometry Management and Negotiation **=====================================** The following methods are involved in geometry management and negotiation: TableResize() method: The parent can issue a resize demand by invoking TableResize() via XtResizeWidget(). This can be due to the parent being resized from above (perhaps the user changed the shell size via the window manager) or it may be due to the Table itself asking to be made a different size for any of several reasons. TableSetValues() method: Geometry management gets involved when a change occurs to any Table resource, or any of several superclass resources (width, height, margin_width). TableQueryGeometry() method: A parent of a Table asks the table for its preferred geometry using this method, invoked via XtQueryGeometry(). Usually generates a proposed layout which is valid only if the next geometry management and negotiation method invoked is TableQueryGeometry() for the same child asking for approved sizes. All other geometry management and negotiation methods must clear the proposed layout. TableGeometryManager() method: This method is invoked when a child wishes to become a different size. TableChangeManaged() method: this method is invoked when the set of managed children changes. This triggers the initial layout of the Table widget, and causes the existing layout to be re-computed. */ /* Recompute Layout Due To Parent Demand **=======================================** This gets called when a parent tells the table it must re-size. We certainly have real_layout, rows, cols, already done (or null if no managed children). If we are being resized due to the initial resize request from a child, then we will have alot of the work done IFF the size the table is now the size the parent *said* is would change the table to become. We cannot really trust this, because all this geometry negotiation stuff is so goddamn complex that one is amazed when anything actually DOES work... Therefore, if the table is being resized, and the size is as we expect, then we just resize and the optimizations work as planned. This means we can use the proposed column and row vectors which have already been adjusted to fit the pre-approved size, but we still size and position all the children, and redisplay. If we are being resized for any other reason, or if we are being resized to a size different from that previously approved by this tables's parent, then we need to flush the proposed layout stuff, and do a full resize: adjust the cols and rows to fit the table, size and position all the children, and redisplay. Cause the background of the Table widget to be re-displayed. */ static void XpTableResize( w ) Widget w; { XpTableWidget tw = (XpTableWidget)w; if ( tw->table.resize_table_to_size_pre_approved_by_parent && tw->core.width == tw->table.query_width && tw->core.height == tw->table.query_height ) { XpTableResizeLayout( tw ); } else { tw->table.resize_table_to_size_pre_approved_by_parent = False; XpTableForgetProposedLayout( tw ); XpTableResizeLayout( tw ); } } /* Set Values **============** This method gets called via XtSetValues(). If any table members or margin width have been changed, then geometry management must be done. We do not have to worry about geometry changes (core.width etc) because Xt takes care of invoking TableResize directly. */ #ifdef XtSpecificationRelease /*ARGSUSED*/ static Boolean XpTableSetValues( currentWidget, ignoreRequestWidget, newWidget, ignored, notUsed ) Widget currentWidget; /* Before call to XtSetValues */ Widget ignoreRequestWidget; /* After call to XtSetValues */ Widget newWidget; /* Final version of widget */ ArgList ignored; Cardinal* notUsed; #else static Boolean XpTableSetValues( currentWidget, ignoreRequestWidget, newWidget) Widget currentWidget; /* Before call to XtSetValues */ Widget ignoreRequestWidget; /* After call to XtSetValues */ Widget newWidget; /* Final version of widget */ #endif { XpTableWidget current = (XpTableWidget) currentWidget; XpTableWidget new = (XpTableWidget) newWidget; if ( current->table.force_shrink != new->table.force_shrink || current->table.col_spacing != new->table.col_spacing || current->table.row_spacing != new->table.row_spacing || current->table.default_options != new->table.default_options || current->table.default_layout != new->table.default_layout || current->table.same_width != new->table.same_width || current->table.same_height != new->table.same_height || current->table.same_border != new->table.same_border || current->table.margin_width != new->table.margin_width || current->table.margin_height != new->table.margin_height) { /* We need to do some re-layout */ XpTableForgetProposedLayout( new ); /* values set by pointers require special handling: * free old value, copy and alloc new value. */ if ( current->table.same_width != new->table.same_width ) { XrmNameListListsFree( current->table.same_width ); new->table.same_width = XrmNameListListsCopy( new->table.same_width ); } if ( current->table.same_height != new->table.same_height ) { XrmNameListListsFree( current->table.same_height ); new->table.same_height = XrmNameListListsCopy( new->table.same_height ); } if ( current->table.same_border != new->table.same_border ) { XrmNameListListsFree( current->table.same_border ); new->table.same_border = XrmNameListListsCopy( new->table.same_border ); } if ( current->table.default_layout != new->table.default_layout ) { XpTableLocFree( current->table.default_layout ); new->table.default_layout = XpTableLocCopy( new->table.default_layout ); /* We need to do a complete recomputation and placement */ XpTableNewLayout( new ); } else { /* we only need to change some things in the existing real_layout */ XpTableRecomputeLayout( new ); } /* Let Xt know exposure is needed */ return True; } /* No exposure needed due to Table resources */ return False; } /* Provide Preferred Geometry To Parent **======================================** If the parent asks if the table can grow, the answer is always yes. If the parent asks for the table to shrink to a size smaller than the preferred width or height, then the answer is almost, with the preferred width and height provided. */ static XtGeometryResult XpTableQueryGeometry( w, request, geo_return) Widget w; /* XpTable widget */ XtWidgetGeometry *request; /* Parent intended size */ XtWidgetGeometry *geo_return; /* preferred size */ { XpTableWidget tw = (XpTableWidget) w; int pref; /* First check for queries which would not result in a resize. * According to the spec, "No" means "Don't bother." */ if ( request->request_mode & CWWidth && request->width == tw->core.width && request->request_mode & CWHeight && request->height == tw->core.height ) return XtGeometryNo; if ( request->request_mode & CWWidth && request->width == tw->core.width ) return XtGeometryNo; if ( request->request_mode & CWHeight && request->height == tw->core.height ) return XtGeometryNo; /* Note that this table may be in the process of asking the parent for a * resize, and the parent may (from within the parent's GeometryManager * method) ask the table for its preferred size. TablePreferredWidth() * and TablePreferredHeight() can tell this is happening, because * TableMakeResizeRequest() sets the flag tw->table.requesting_resize. * In such a case, the preferred size returned is the size the table is * asking to become. */ if ( request->request_mode == (XtGeometryMask)0 ) { /* Parent is asking for all preferred dimensions */ geo_return->request_mode = CWWidth|CWHeight; geo_return->width = XpTablePreferredWidth( tw ); geo_return->height = XpTablePreferredHeight( tw ); } if ( request->request_mode & CWWidth ) { pref = XpTablePreferredWidth( tw ); if ( request->width < (Dimension)pref ) { geo_return->width = (Dimension)pref; geo_return->request_mode |= CWWidth; } else { geo_return->width = request->width; } } if ( request->request_mode & CWHeight ) { pref = XpTablePreferredHeight( tw ); if ( request->height < (Dimension)pref ) { geo_return->height = (Dimension)pref; geo_return->request_mode |= CWHeight; } else { geo_return->height = request->height; } } /* XtGeometryNo means already at preferred (minimum) size (dont't bother) */ if ( geo_return->width == tw->core.width && geo_return->height == tw->core.height ) return XtGeometryNo; /* XtGeometryAlmost means has a preferred size different from current size */ if ( geo_return->request_mode & (CWWidth|CWHeight) ) return XtGeometryAlmost; /* XtGeometryYes is only returned if request is to change geometry in ways * which do not matter to the table layout: x&y position, border_width, * sibling, and stack_mode. */ return XtGeometryYes; } /* Handle Geometry Requests from Children **========================================** Only called by Xt if the child is managed. Therefore, we can trust that the table already has valid row and column vectors. Position changes are always rejected. Size changes are processed as followed: We store the child and the child's requested size in the Table. We also save the current row and column vectors. Then we "pretend" that we are going to accept the requested child size: create new row and column vectors, make them fit the Table's width and height. Then, instead of changing the geometries of all the children, we see what the size of the requesting child would be. If (by some miracle) the resulatant size is the requested size, then we really do the layout. In reality, the size will almost ALWAYS be different from the requested, so we return XtGeometryAlmost, save the newly computed row and column vectors, and remember the approved size of the child. In most cases, the child will simply immediately re-invoke this method, passing the approved sizes. We can then use the pre-computed column and row vectors, and set the geometries of all the children (including the requesting child) and return XtGeometryDone (XtGeometryYes). If, however, ANY other geometry method is invoked (due to set values, change managed, or resize command from parent) then the pre-computed vectors are invalid, and the approved size is invalid. */ static XtGeometryResult XpTableGeometryManager( child, request, reply ) Widget child; /* Widget */ XtWidgetGeometry *request; /* Requested geometry change */ XtWidgetGeometry *reply; /* Actual reply to request */ { Widget parent = child->core.parent; XpTableWidget tw = (XpTableWidget) parent; Dimension width, height, border_width; if ( !parent || !XpIsTable( parent ) ) XtErrorMsg("XpTableGeometryManager", "badParent", "XtToolkitError", "Parent of widget is not an XpTableWidget", (String*)0, (Cardinal*)0); /* If request is only for geometry things ignored by table, do nothing. */ if ( 0 == request->request_mode & (CWWidth|CWHeight|CWBorderWidth)) return XtGeometryNo; /* Get the relevent dimensions of child: request or current. */ if ( request->request_mode & CWWidth ) width = request->width; else width = child->core.width; if ( request->request_mode & CWHeight ) height = request->height; else height = child->core.height; if ( request->request_mode & CWBorderWidth ) border_width = request->border_width; else border_width = child->core.border_width; /* Some widgets are really stupid: they ask to be resized to their * current size. Silly, but more common than you may think! */ if ( width == child->core.width && height == child->core.height && border_width == child->core.border_width ) { reply->width = width; reply->height = height; reply->border_width = border_width; reply->request_mode = ( request->request_mode & CWWidth ? CWWidth : 0 ) | ( request->request_mode & CWHeight ? CWHeight : 0 ) | ( request->request_mode & CWBorderWidth ? CWBorderWidth : 0 ); if ( request->request_mode & !(XtCWQueryOnly|CWWidth|CWHeight|CWBorderWidth) ) { /* There are some flags set which are not respected by Table */ return XtGeometryAlmost; } else if ( request->request_mode & XtCWQueryOnly ) { /* We will honor actual resize request for width, height, border */ return XtGeometryYes; } else { /* It is already the queried size. */ return XtGeometryDone; } } /* We can use the pre-computed proposed layout ONLY if the same child is * requesting pre-approved sizes. Note: approved_mode does NOT have * XtCWQueryOnly set! */ if ( tw->table.approved_child == child && tw->table.approved_mode == request->request_mode && tw->table.approved_width == width && tw->table.approved_height == height && tw->table.approved_border_width == border_width ) { /* Request is exactly as approved. */ XpTableUseProposedLayout( tw ); return XtGeometryDone; } /* No pre-approved layout, or something is different. Need to * re-compute proposed layout. */ XpTableForgetProposedLayout( tw ); /* Pretend we re-size the child, and go through table layout logic. Then * look at the resulting size of the child, and that will be the size we * approve for the child. If by some fluke the approved size is the size * requested, then we do the change, otherwise return Almost. */ tw->table.resize_child = child; tw->table.resize_mode = request->request_mode; tw->table.resize_width = width; tw->table.resize_height = height; tw->table.resize_border_width = border_width; XpTableNewProposedLayout( tw ); XpTableForgetResizeChild( tw ); reply->request_mode = tw->table.approved_mode; reply->width = tw->table.approved_width; reply->height = tw->table.approved_height; reply->border_width = tw->table.approved_border_width; /* Note: TableNewProposedLayout() will only set CWWidth or CWHeight or * CWBorderWidth into approved_mode. Therefore, if request_mode has * XtCWQueryOnly or any of the flags ignored by table (like CWStackMode) * then approved_mode will be different from request_mode */ if ( ( !(request->request_mode & CWWidth) || (tw->table.approved_width == width) ) && ( !(request->request_mode & CWHeight) || (tw->table.approved_height == height) ) && ( !(request->request_mode & CWBorderWidth) || (tw->table.approved_border_width == border_width) ) ) { /* Everything which is asked to change matched the approved changes. */ if ( (tw->table.approved_mode|XtCWQueryOnly) == request->request_mode ) { /* child only queried: we would grant child's request exactly */ return XtGeometryYes; } else if ( tw->table.approved_mode == request->request_mode ) { /* Request is exactly as approved. */ XpTableUseProposedLayout( tw ); return XtGeometryDone; } } if ( tw->table.approved_mode && ( tw->table.approved_width != child->core.width || tw->table.approved_height != child->core.height || tw->table.approved_border_width != child->core.border_width ) ) { /* Something is approved, and some approved size is different from * existing size, so some of the child's geometry would change. * approved_mode as provided by TableNewProposedLayout() already * reflects those fields which would actually change. */ return XtGeometryAlmost; } else { /* Approved size is exactly the same as current size. */ return XtGeometryNo; } } /* Handle Increase or Decrease in Managed Children **=================================================** Called when a child or when children are managed or unmanaged via XtManageChild(), XtUnmanageChild() etc. */ static void XpTableChangeManaged( w ) Widget w; { XpTableWidget tw = (XpTableWidget) w; XpTableNewLayout( tw ); } /*===========================** ** End Of Xt Invoked Methods ** **===========================*/ /* Internal Table Methods **========================** There are these ways the Table may need to be recomputed: o ChangedManage: Compute new layout, ask parent for new size. o SetValues: Compute new layout or recompute layout, ask parent for new size. o Child change: Recompute layout, ask parent for new size. o Initial GeometryRequest from child: Compute proposed layout. o Approved GeometryRequest from child: Use proposed layout, ask parent for new size. o Resize Method: Command to change to specific size from above. */ void XpTableNewLayout( tw ) XpTableWidget tw; { XpTableNewRealLayout( tw ); XpTableConsiderSameSize( tw ); XpTableNewColsAndRows( tw ); XpTableRequestResize( tw ); } void XpTableRecomputeLayout( tw ) XpTableWidget tw; { XpTableConsiderSameSize( tw ); XpTableNewColsAndRows( tw ); XpTableRequestResize( tw ); } void XpTableNewProposedLayout( tw ) XpTableWidget tw; { XpTableConsiderSameSize( tw ); XpTableProposedColsAndRows( tw ); XpTableQueryParentForResize( tw ); /* query only, no resize */ XpTableMakeColsFitQueryWidth( tw ); XpTableMakeRowsFitQueryHeight( tw ); XpTableGetProposedChildSize( tw ); XpTableSaveProposedLayout( tw ); } void XpTableUseProposedLayout( tw ) XpTableWidget tw; { XpTableGetProposedLayout( tw ); tw->table.resize_table_to_size_pre_approved_by_parent = True; XpTableRequestResize( tw ); tw->table.resize_table_to_size_pre_approved_by_parent = False; } /* Called due to TableRequestResize() */ void XpTableResizeLayout( tw ) XpTableWidget tw; { if ( !tw->table.resize_table_to_size_pre_approved_by_parent ) { XpTableMakeColsFitWidth( tw ); XpTableMakeRowsFitHeight( tw ); } XpTableSetGeometryOfChildren( tw ); /* I have to do this in case someone is using those goddamn gadgets. * Normally, a manager should not need to redisplay itself, right!?! */ if ( XtIsRealized( (Widget)tw ) ) { XClearArea( XtDisplay( (Widget)tw ), XtWindow( (Widget)tw ), 0, 0, 0, 0, /* clears entire window */ True ); /* we need Expose events */ } tw->table.resize_status = RSdone; } /* Proposed Layout Methods **=========================** A resize request from a child is virtually NEVER granted straight away: Instead, a proposed layout must be computed, and the resultant size of the child is then returned. If the child can accept this size (nearly always yes in actual existing widgets), then it immediately returns these approved sizes, and the table can detect this and use the proposed layout. If any other geometry method is invoked in the meantime, the proposed layout must be cleared and forgotten. */ void XpTableSaveProposedLayout( tw ) XpTableWidget tw; { tw->table.approved_cols = tw->table.cols; tw->table.approved_rows = tw->table.rows; tw->table.cols = tw->table.current_cols; tw->table.rows = tw->table.current_rows; } void XpTableGetProposedLayout( tw ) XpTableWidget tw; { XpTableVectorFree( tw->table.cols ); XpTableVectorFree( tw->table.rows ); tw->table.cols = tw->table.approved_cols; tw->table.rows = tw->table.approved_rows; tw->table.approved_child = (Widget)0; tw->table.approved_mode = (XtGeometryMask)0; tw->table.approved_width = (Dimension)0; tw->table.approved_height = (Dimension)0; tw->table.approved_border_width = (Dimension)0; tw->table.approved_cols = (XpTableVector)0; tw->table.approved_rows = (XpTableVector)0; } void XpTableForgetProposedLayout( tw ) XpTableWidget tw; { XpTableVectorFree( tw->table.approved_cols ); XpTableVectorFree( tw->table.approved_rows ); tw->table.approved_child = (Widget)0; tw->table.approved_mode = (XtGeometryMask)0; tw->table.approved_width = (Dimension)0; tw->table.approved_height = (Dimension)0; tw->table.approved_border_width = (Dimension)0; tw->table.approved_cols = (XpTableVector)0; tw->table.approved_rows = (XpTableVector)0; tw->table.current_cols = (XpTableVector)0; tw->table.current_rows = (XpTableVector)0; tw->table.query_mode = (XtGeometryMask)0; tw->table.query_width = (Dimension)0; tw->table.query_height = (Dimension)0; tw->table.resize_table_to_size_pre_approved_by_parent = False; } void XpTableForgetResizeChild( tw ) XpTableWidget tw; { tw->table.resize_child = (Widget)0; tw->table.resize_mode = (XtGeometryMask)0; tw->table.resize_width = (Dimension)0; tw->table.resize_height = (Dimension)0; tw->table.resize_border_width = (Dimension)0; } /* Build a new real_layout for all managed children. **==================================================** Each location is a function of the real_layout, default_layout, default_options, and automatic positioning. The list of managed children in traversed: if a managed child already appears in the current real_layout, that layout is copied. Otherwise, location data comes from default_layout, default_options, and automatic positioning members of the parent table widget. Since both the default_layout and real_layout are changed by TablePosition(), TableResize(), TableOptions(), and TableConfig(), changes to the children remain in effect when the table layout is re-computed, and when children become managed and unmanaged multiple times. However, if the default_layout is changed by a XtSetValues, all the positioning stuff in default_layout is lost. OK, since both are done by the client program: if the programmer wants to change the layout, the programmer will also need to reposition children. */ void XpTableNewRealLayout( tw ) XpTableWidget tw; { int num_children = tw->composite.num_children; WidgetList children = tw->composite.children; XpTableLoc result = XpTableLocNew( num_children ); XpTableLoc loc = result; XpTableLoc found; int child = 0; /* index into list of all children */ for ( ; child < num_children ; child++ ) { Widget w = children[child]; if ( XtIsManaged( w ) ) { /*ASSIGN_IN_IF*/ if ( found = XpTableLocFind( tw->table.real_layout, w ) ) { /* This widget was in previous layout, copy all fields */ *loc = *found; } /*ASSIGN_IN_IF*/ else if ( found = XpTableLocFind( tw->table.default_layout, w ) ) { /* This child has been laid out before, so copy everything. */ *loc = *found; } /*ASSIGN_IN_IF*/ else if ( found = XpTableLocFindDefault( tw->table.default_layout, w ) ) { /* Never laid out this child, but default layout provides * some information. Copy everything, fill in the blanks * (col,row,col_span,row_span already have defaults). * No problem if tw->table.default_options is zero. */ *loc = *found; loc->w = w; loc->orig_width = w->core.width; loc->orig_height = w->core.height; loc->orig_border_width = w->core.border_width; if ( !loc->options ) loc->options = tw->table.default_options; XpTableAppendToDefaultLayout( tw, loc ); } else { /* Never laid out this child, not in default layout. Fill * in everything with default values. */ loc->w = w; loc->w_quark = w->core.xrm_name; loc->col = loc->row = 0; loc->col_span = loc->row_span = 1; loc->orig_width = w->core.width; loc->orig_height = w->core.height; loc->orig_border_width = w->core.border_width; if ( !loc->options ) loc->options = tw->table.default_options; XpTableAppendToDefaultLayout( tw, loc ); } loc++; /* loc only incremented for MANAGED children */ } } XpTableLocFree( tw->table.real_layout ); tw->table.real_layout = result; } /* Append loc to default_layout **==============================** The loc points to a Widget child. When that child is destroyed, we must clear out that pointer, as it will point to deallocated data. */ static void XpTableRemoveFromDefaultLayoutCB _((Widget,XtPointer,XtPointer)); void XpTableAppendToDefaultLayout( tw, loc ) XpTableWidget tw; XpTableLoc loc; { int inx; tw->table.default_layout = XpTableLocGrow( tw->table.default_layout ); inx = XpTableLocLen( tw->table.default_layout ); tw->table.default_layout[inx] = *loc; XtAddCallback( loc->w, XtNdestroyCallback, XpTableRemoveFromDefaultLayoutCB, (XtPointer)tw ); } /* Remove Destroyed Widget from default_layout **=============================================** */ /*ARGSUSED*/ static void XpTableRemoveFromDefaultLayoutCB( w, client, call ) Widget w; XtPointer client, call; { XpTableWidget tw = (XpTableWidget)client; XpTableLoc loc = XpTableLocFind( tw->table.default_layout, w ); if ( loc ) loc->w = (Widget)0; } /* Consider Same Size constraints on all children in real_layout **===============================================================** ALWAYS do this BEFORE creating new or proposed columns and rows. New TableVectors need this information to determine the `preferred' sizes of children. This MAY happen when we are responding to a resize request from a child: in this case, we need to consider the resize request size instead of that specific child's current size. */ void XpTableConsiderSameSize( tw ) XpTableWidget tw; { XpTableLoc loc, real_layout; int same_what; real_layout = tw->table.real_layout; for ( loc = real_layout ; loc->w_quark != NULLQUARK ; loc++ ) { loc->same_width = 0; loc->same_height = 0; loc->same_border = 0; } for ( same_what = 1 ; same_what <= 3 ; ++same_what ) { XrmNameListLists lists; int list; switch ( same_what ) { case 1: lists = tw->table.same_width; break; case 2: lists = tw->table.same_height; break; case 3: lists = tw->table.same_border; break; } /* Go down all the lists of lists of names ... */ for ( list = 0 ; lists != NULL && lists[list] != NULL ; ++list ) { /* Go down all the names on each list to determine the max dimension */ XrmNameList names = lists[list]; int name; Dimension max; for ( max = name = 0 ; names[name] != (XrmName)0 ; ++name ) { /* Go down entire list of children, and for each kid * with this name get the maximum size. */ for ( loc = real_layout ; loc->w_quark != NULLQUARK ; loc++) { Widget kid = loc->w; if ( kid != (Widget)0 && kid->core.xrm_name == names[name] ) { #define MAXX(v) (max>v?max:v) if ( kid == tw->table.resize_child ) { switch ( same_what ) { case 1: max = MAXX( tw->table.resize_width ); break; case 2: max = MAXX( tw->table.resize_height ); break; case 3: max = MAXX( tw->table.resize_border_width ); break; } } else { switch ( same_what ) { case 1: max = MAXX( kid->core.width ); break; case 2: max = MAXX( kid->core.height ); break; case 3: max = MAXX( kid->core.border_width ); break; } } #undef MAXX } } } /* OK, we now have the maximum dimension. Apply to all * kids with names on this list. */ for ( name = 0 ; names[name] != (XrmName)0 ; ++name ) { for ( loc = real_layout ; loc->w_quark != NULLQUARK ; loc++) { Widget kid = loc->w; if ( kid != (Widget)0 && kid->core.xrm_name == names[name] ) { switch ( same_what ) { case 1: loc->same_width = max; break; case 2: loc->same_height = max; break; case 3: loc->same_border = max; break; } } } } } } } /* Create New Cols and Rows Vectors **==================================** This must be done whenever a new real_layout is created, or when the existing real_layout has been changed. */ void XpTableNewColsAndRows( tw ) XpTableWidget tw; { XpTableVectorFree( tw->table.cols ); XpTableVectorFree( tw->table.rows ); tw->table.num_cols = XpTableLocNumCols( tw->table.real_layout ); tw->table.num_rows = XpTableLocNumRows( tw->table.real_layout ); if ( tw->table.num_cols && tw->table.num_rows ) { tw->table.cols = XpTableVectorNew( tw->table.num_cols, tw, DO_COL ); tw->table.rows = XpTableVectorNew( tw->table.num_rows, tw, DO_ROW ); } else { tw->table.num_cols = tw->table.num_rows = 0; tw->table.cols = tw->table.rows = (XpTableVector)0; } } /* Create New Cols and Rows Vectors for Proposed Layout **======================================================** Save the "real" valid vectors for later. Note that we CERTAINLY have rows and columns, because this is only invoked due to a child's request to resize, and only managed children will be processed, and the existence of managed children implies the existence of non-null row and column vectors. */ void XpTableProposedColsAndRows( tw ) XpTableWidget tw; { tw->table.current_cols = tw->table.cols; tw->table.current_rows = tw->table.rows; tw->table.cols = XpTableVectorNew( tw->table.num_cols, tw, DO_COL ); tw->table.rows = XpTableVectorNew( tw->table.num_rows, tw, DO_ROW ); } /* Adjust rows and columns to fit **================================** These procedures are called when the Table's parent changes the size of the Table. The TableRecomputeLayout() procedure computes the preferred size of the table based on the layout and the children, with the assumption that the table could be any size. Now, we have a specific size, so we will need to adjust everything to fit. If the new size is larger, then its easy: just expand the space available to each row and/or column, and change the geometries of all the children. If the new size is smaller and force_shrink is true (the new default), then adjust all children to fit the new size. If the new size is smaller and force_shrink is false then we must do something like a better behaved version of the old behavior: Shrink to the preferred size but no smaller. */ void XpTableMakeColsFitWidth( tw ) XpTableWidget tw; { XpTableFitThis( tw, DO_COL, tw->core.width ); } void XpTableMakeColsFitQueryWidth( tw ) XpTableWidget tw; { XpTableFitThis( tw, DO_COL, tw->table.query_width ); } void XpTableMakeRowsFitHeight( tw ) XpTableWidget tw; { XpTableFitThis( tw, DO_ROW, tw->core.height ); } void XpTableMakeRowsFitQueryHeight( tw ) XpTableWidget tw; { XpTableFitThis( tw, DO_ROW, tw->table.query_height ); } void XpTableFitThis( tw, do_col, to_fit ) XpTableWidget tw; int do_col, to_fit; { int change, current, prefer, num; XpTableVector vec; if ( do_col ) { vec = tw->table.cols; num = tw->table.num_cols; } else { vec = tw->table.rows; num = tw->table.num_rows; } current = XpTableVectorTotalSize( vec, num, tw, do_col ); prefer = XpTableVectorPreferredSize( vec, num, tw, do_col ); if ( to_fit < prefer && tw->table.force_shrink == False ) { /* Smallest size is preferred size. Excess clipped. */ change = prefer - current; } else { change = to_fit - current; } if ( change != 0 ) XpTableVectorAdjust( vec, num, change ); } /* Determine Preferred (Minimum) Size of Table **=============================================** */ int XpTablePreferredWidth( tw ) XpTableWidget tw; { if ( tw->table.requesting_resize ) { return tw->table.requesting_width; } else { XpTableVector vec = tw->table.cols; int num = tw->table.num_cols; return XpTableVectorPreferredSize( vec, num, tw, DO_COL ); } } int XpTablePreferredHeight( tw ) XpTableWidget tw; { if ( tw->table.requesting_resize ) { return tw->table.requesting_height; } else { XpTableVector vec = tw->table.rows; int num = tw->table.num_rows; return XpTableVectorPreferredSize( vec, num, tw, DO_ROW ); } } /* Request Resize from Parent **============================** This procedure gets called by other Table methods when the Table instance wants to grow or shrink. Since we cannot yet tell if the desired size is OK, the children of the Table have NOT been sized or positioned: this is only done by the TableResize method. Here is when the wonders of Xt Geometry Management come into play. We cannot tell a priori what the hell is going to happen here. We can ask the parent to allow the table to resize based on the computed width and height of the cols and rows. If the parent says yes, then TableResize may, or then again, may not, have been called. Since we don't know, we must keep a bogus little flag in the instance to indicate what really happened. */ void XpTableRequestResize( tw ) XpTableWidget tw; { XtGeometryResult result; XtWidgetGeometry desired, approved; /* If this is RSdone after the call to XtMakeResizeRequest(), then we know * that TableResize() has been invoked. Otherwise, we must invoke * TableResize() directly. */ tw->table.resize_status = RSdueToRequest; /* We may be requesting a resize after a child asked for a resize. * In this case, we already have a size pre-approved by the parent. * Otherwise, we want to become our preferred size. */ if ( tw->table.resize_table_to_size_pre_approved_by_parent ) { desired.width = tw->table.query_width; desired.height = tw->table.query_height; desired.request_mode = tw->table.query_mode; } else { desired.width = XpTablePreferredWidth( tw ); desired.height = XpTablePreferredHeight( tw ); desired.request_mode = (XtGeometryMask)0; if ( desired.width != tw->core.width ) desired.request_mode |= CWWidth; if ( desired.width != tw->core.height ) desired.request_mode |= CWHeight; } /* XtMakeResizeRequest() asks the parent to allow this table to resize. * The parent, a Composite widget, will often need to query all of its * children (including this table) to see what sizes they want to be. * Therefore, there is a very good chance that the QueryGeometry method of * this table widget will be invoked in a few microseconds, and this table * will need to compute its desired size. So, for efficiency we remember * our desired size. */ tw->table.requesting_resize = True; tw->table.requesting_width = desired.width; tw->table.requesting_height = desired.height; /* If desired size is current size, then do NOT ask parent, act like its OK. */ if ( desired.width == tw->core.width && desired.height == tw->core.height ) result = XtGeometryYes; else result = XtMakeGeometryRequest( (Widget)tw, &desired, &approved ); /* Nothing special to do if XtGeometryYes or XtGeometryNo */ if ( result == XtGeometryAlmost ) { /* Now the desired size is the size our parent will allow. */ result = XtMakeGeometryRequest( (Widget)tw, &approved, &approved ); } tw->table.requesting_resize = False; /* No matter what the outcome, the Table must be "resized", as this is * where the table looks at its actual width/height and sizes and positions * the children widgets. */ if ( tw->table.resize_status == RSdueToRequest ) XpTableResize( (Widget)tw ); } /* Query parent for hypothetical resize. **======================================** This is called when a child has asked to be resized, and such a request, if granted, would cause the table to ask its parent for a resize. We ask the parent to tell us what size the parent would resize the table, if the table really asked for a resize to its "proposed" size. Note that we DO NOT ask the parent to resize us, because we are not COMPLETELY certain the child will want the size we will propose for it: the child may withdraw its resize. Unfortunately, the GeometryManager method of the parent may not in fact treat this as a simple query, but it may treat it as a request, and the table may well have its size changed by a call to its Resize method! Yes, this is a common deficiency in GeometryManager methods of composite widgets. It is VERY difficult to get all this &$%?%$!?! right. */ void XpTableQueryParentForResize( tw ) XpTableWidget tw; { XtGeometryResult result; XtWidgetGeometry desired, query; /* If this is RSdone after the call to XtMakeGeometryRequest(), then we * know that TableResize() has been invoked - UNFORTUNATELY! */ tw->table.resize_status = RSdueToRequest; /* Query only for width and height */ desired.request_mode = (XtCWQueryOnly|CWWidth|CWHeight); /* Desired dimensions reflect change due to resize_child's resize request */ desired.width = XpTablePreferredWidth( tw ); desired.height = XpTablePreferredHeight( tw ); /* XtMakeGeometryRequest() asks the parent for the result of a hypothetical * resize request from the table. The parent, a Composite widget, will * often need to query all of its children (including this table) to see * what sizes they want to be. Therefore, there is a very good chance that * the QueryGeometry method of this table widget will be invoked in a few * microseconds, and this table will need to compute its desired size. So, * for efficiency we remember our desired size. */ tw->table.requesting_resize = True; tw->table.requesting_width = desired.width; tw->table.requesting_height = desired.height; /* If desired size is current size, then do NOT ask parent, act like its OK. */ if ( desired.width == tw->core.width && desired.height == tw->core.height ) result = XtGeometryYes; else result = XtMakeGeometryRequest( (Widget)tw, &desired, &query ); tw->table.requesting_resize = False; switch ( result ) { case XtGeometryYes: tw->table.query_mode = CWWidth | CWHeight; tw->table.query_width = desired.width; tw->table.query_height = desired.height; break; case XtGeometryAlmost: tw->table.query_mode = ( query.request_mode & CWWidth ? CWWidth : 0 ) |( query.request_mode & CWHeight? CWWidth : 0 ); tw->table.query_width = query.width; tw->table.query_height = query.height; break; case XtGeometryNo: default: /* Cannot resize. */ tw->table.query_mode = (XtGeometryMask)0; tw->table.query_width = tw->core.width; tw->table.query_height = tw->core.height; break; } if ( result == XtGeometryYes && tw->table.resize_status != RSdueToRequest ) { /* Oh Shit! The parent did not notice this was just a QUERY, and * it went ahead and did the change. Oh Shit! */ Widget parent = XtParent( (Widget)tw ); char* class = parent->core.widget_class->core_class.class_name; String args[3]; Cardinal two = 2; args[0] = XtName(parent); args[1] = class; args[2] = NULL; XtWarningMsg( "brokenParent", "XpTableQueryParentForResize", "Widget Library Error", "Widget %s of class %s\nhas a GeometryManager method which ignores XtCWQueryOnly!", args, &two ); /* Already resized. */ tw->table.query_mode = (XtGeometryMask)0; tw->table.query_width = tw->core.width; tw->table.query_height = tw->core.height; } } /* Get Approved Size of Child **============================** A child has asked to be resized. We need to compute the size which the table would make the child if the table itself was resized (from above). Assume we will grant the border width request UNLESS the width or height goes to zero or negative. The child is managed (or else it could not make the resize request), so the child is in the real_layout. */ void XpTableGetProposedChildSize( tw ) XpTableWidget tw; { int width, height, bw, x, y; XpTableLoc loc = tw->table.real_layout; while ( loc->w && loc->w != tw->table.resize_child ) ++loc; if ( loc->w != tw->table.resize_child ) { String args[3]; Cardinal two = 2; args[0] = XtName(tw->table.resize_child); args[1] = XtName((Widget)tw); args[2] = NULL; XtWarningMsg( "unmanagedChildMadeResizeRequest", "XpTableGetProposedChildSize", "Xt Implementation Bug", "XtMakeGeometryRequest passed request from unmanaged child %s to table %s\n", args, &two ); XpTableForgetProposedLayout( tw ); return; } /* This loc is for the child requesting the resize. * * First, try to use all the dimensions: width, height, requested border. * If the width and height are not minimums, we are done. */ width = height = 0; /* need to compute these */ bw = tw->table.resize_border_width; /* assume we grant this */ XpTableComputeChildSize( tw, loc, &width, &height, &bw, &x, &y ); if ( 1 < width && 1 < height ) { XpTableApproveGeometryChanges( tw, loc->w, width, height, bw ); return; } /* Try again, this time using the current border width */ width = height = 0; bw = loc->w->core.border_width; XpTableComputeChildSize( tw, loc, &width, &height, &bw, &x, &y ); if ( width < 1 ) width = 1; if ( height < 1 ) height = 1; XpTableApproveGeometryChanges( tw, loc->w, width, height, bw ); } void XpTableApproveGeometryChanges( tw, child, width, height, bw ) XpTableWidget tw; Widget child; int width, height, bw; { tw->table.approved_child = child; tw->table.approved_mode = (XtGeometryMask)0; if ( tw->table.resize_mode&CWBorderWidth && bw != child->core.border_width ) tw->table.approved_mode |= CWBorderWidth; if ( tw->table.resize_mode&CWWidth && width != child->core.width ) tw->table.approved_mode |= CWWidth; if ( tw->table.resize_mode&CWHeight && height != child->core.height ) tw->table.approved_mode |= CWHeight; tw->table.approved_border_width = bw; tw->table.approved_width = width; tw->table.approved_height = height; } /* Set Geometry Of Children **==========================** Children are placed according to the real_layout, cols, rows, and row and column spacing. */ void XpTableSetGeometryOfChildren( tw ) XpTableWidget tw; { XpTableLoc loc; if ( tw->table.real_layout == (XpTableLoc)0 || tw->table.cols == (XpTableVector)0 || tw->table.num_cols == 0 || tw->table.rows == (XpTableVector)0 || tw->table.num_rows == 0 ) return; XpTableVectorComputeOffsets( tw->table.cols, tw->table.num_cols, tw->table.margin_width, tw->table.col_spacing ); XpTableVectorComputeOffsets( tw->table.rows, tw->table.num_rows, tw->table.margin_height, tw->table.row_spacing ); for ( loc = tw->table.real_layout ; loc->w ; loc++ ) { int width, height, bw, x, y; /* This can be invoked due to a child size change request, in which * case the child has not yet been changed in size, but this size * has been guaranteed to be OK. */ if ( loc->w == tw->table.approved_child ) { width = tw->table.approved_width; height = tw->table.approved_height; bw = tw->table.approved_border_width; } else { width = 0; height = 0; bw = loc->w->core.border_width; } XpTableComputeChildSize( tw, loc, &width, &height, &bw, &x, &y ); if ( width != loc->w->core.width || height != loc->w->core.height || bw != loc->w->core.border_width ) XtResizeWidget( loc->w, width, height, bw ); if ( x != loc->w->core.x || y != loc->w->core.y ) XtMoveWidget( loc->w, x, y ); } } void XpTableComputeChildSize( tw, loc, wP, hP, bwP, xP, yP ) XpTableWidget tw; XpTableLoc loc; int *wP, *hP; /* in-out, USE if != 0 */ int *bwP; /* in */ int *xP, *yP; /* out */ { int cell_x, cell_y, cell_w, cell_h; int new_x, new_y, new_w, new_h, prefer; int total_w, total_h; int pad, i; int init_w = *wP; /* non-zero means use it */ int init_h = *hP; /* non-zero means use it */ int bw = *bwP; /* Upper left corner of where we will place the widget */ cell_x = tw->table.cols[ loc->col ].offset; cell_y = tw->table.rows[ loc->row ].offset; /* cell width and height may well span cols and rows and spacing */ pad = tw->table.col_spacing; cell_w = -pad; for ( i = 0 ; i < loc->col_span ; i++ ) cell_w += tw->table.cols[ loc->col + i ].value + pad; pad = tw->table.row_spacing; cell_h = -pad; for ( i = 0 ; i < loc->row_span ; i++ ) cell_h += tw->table.rows[ loc->row + i ].value + pad; /* If the width or height was given, then use it. This given dimension * has already been approved by the table in geometry negotiation (by * the GeometryManager method). * * Otherwise, If size growth is prevented due to TBL_SM_(WIDTH | HEIGHT), * then use the lesser of the cell size or the preferred size. * * Otherwise, use the cell size. */ if (init_w) { new_w = init_w; } else if (loc->options & TBL_SM_WIDTH && cell_w > (prefer = XpTableLocPreferredWidth( loc, tw )) ) { new_w = prefer - 2 * bw; } else { new_w = cell_w - 2 * bw; } if (init_h) { new_h = init_h; } else if (loc->options & TBL_SM_HEIGHT && cell_h > (prefer = XpTableLocPreferredHeight( loc, tw )) ) { new_h = prefer - 2 * bw; } else { new_h = cell_h - 2 * bw; } /* Be certain that the size does not go to zero, or negative! */ if ( new_w <= 0 ) new_w = 1; /* value ready for XtResize */ if ( new_h <= 0 ) new_h = 1; /* value ready for XtResize */ total_w = new_w + 2 * bw; total_h = new_h + 2 * bw; if ( loc->options & TBL_LEFT ) new_x = cell_x; /* left justify in cell */ else if ( loc->options & TBL_RIGHT ) new_x = cell_x + cell_w - total_w; /* right justify in cell */ else new_x = cell_x + (cell_w - total_w)/2; /* center in cell */ if ( loc->options & TBL_TOP ) new_y = cell_y; /* top justify in cell */ else if ( loc->options & TBL_BOTTOM ) new_y = cell_y + cell_h - total_h; /* bottom justify in cell */ else new_y = cell_y + (cell_h - new_h)/2; /* center in cell */ *wP = new_w; *hP = new_h; *xP = new_x; *yP = new_y; } /* TableOpts methods **===================** */ XpTableOpts XpTableOptsParse( optString ) String optString; { XpTableOpts opt = 0; for ( ; *optString; optString++) { switch (*optString) { case 'l': opt |= TBL_LEFT; break; case 'r': opt |= TBL_RIGHT; break; case 't': opt |= TBL_TOP; break; case 'b': opt |= TBL_BOTTOM; break; case 'w': opt |= TBL_LK_WIDTH; break; case 'h': opt |= TBL_LK_HEIGHT; break; case 'W': opt |= TBL_SM_WIDTH; break; case 'H': opt |= TBL_SM_HEIGHT; default: break; } } return opt; } /* Client Utility Functions **==========================** The following functions are used to reconfigure children of Table widgets */ /* Position Child in Col,Row of Table **====================================** */ #define CHG_POS 0x1 #define CHG_SPAN 0x2 #define CHG_OPTS 0x4 #define CHG_ALL 0x7 static void Change( loc, what, col, row, col_span, row_span, opts ) XpTableLoc loc; /* specific loc to change */ int what; /* What to change */ int col, row; /* New position in table */ int col_span, row_span; /* New spans of child in table */ XpTableOpts opts; /* New size/justification opts */ { if ( what & CHG_POS ) { if ( 0 <= col ) loc->col = col; if ( 0 <= row ) loc->row = row; } if ( what & CHG_SPAN ) { if ( 1 <= col_span ) loc->col_span = col_span; if ( 1 <= row_span ) loc->row_span = row_span; } if ( what & CHG_OPTS ) { loc->options = opts; } } static void XpTableChildChange( child, what, col, row, col_span, row_span, opts) Widget child; /* Child widget to change */ int what; /* What to change */ int col, row; /* New position in table */ int col_span, row_span; /* New spans of child in table */ XpTableOpts opts; /* New size/justification opts */ { if ( !XpIsTable( child->core.parent ) ) { Cardinal one = 1; char* name = XtName( child ); XtWarningMsg( "notChildOfTable", "XpTableChildChange", "XpLibError", "Widget %s is not a child of an XpTable widget.", &name, &one); return; } else { XpTableWidget tw = (XpTableWidget)child->core.parent; XpTableLoc def = XpTableLocFind( tw->table.default_layout,child); XpTableLoc real = XpTableLocFind( tw->table.real_layout, child); if ( def == (XpTableLoc)0 ) { /* Never laid out this child before. */ static XpTableLocRec nullRec; XpTableLocRec newRec; XpTableLoc initDef; newRec = nullRec; def = &newRec; /* Find the initial default for this name, copy what we can. */ initDef = XpTableLocFindDefault( tw->table.default_layout, child ); if ( initDef != (XpTableLoc)0 ) *def = *initDef; /* Set up default fields. */ def->w_quark = child->core.xrm_name; def->w = child; if ( def->col_span <= 0 ) def->col_span = 1; if ( def->row_span <= 0 ) def->row_span = 1; if ( def->options == 0 ) def->options = tw->table.default_options; def->orig_width = child->core.width; def->orig_height = child->core.height; def->orig_border_width = child->core.border_width; /* Append to default_layout, then get pointer to that loc */ XpTableAppendToDefaultLayout( tw, def ); def = XpTableLocFind( tw->table.default_layout,child ); } /* Change loc in default_layout to reflect widget position etc. */ Change( def, what, col, row, col_span, row_span, opts ); if ( real != (XpTableLoc)0 ) { /* In real_layout: Change child's actual position/span/opt */ Change( real, what, col, row, col_span, row_span, opts ); /* We do not have to create a new real_layout. Also, we know ** child is managed, since it is in the real_layout. Therefore: */ XpTableRecomputeLayout( tw ); } /* If the child is not managed, no re-layout needs to be done: it ** will be done when the child becomes managed (see ChangeManaged) */ } } /* Change Position of Child **==========================** */ void XpTableChildPosition( child, col, row ) Widget child; /* Child widget to move */ int col, row; /* New position in table */ { XpTableChildChange( child, CHG_POS, col, row, 0, 0, 0); } /* Change Size (Span) of Child **=============================** */ void XpTableChildResize( child, col_span, row_span) Widget child; /* Child widget to resize */ int col_span, row_span; /* New widget span */ { XpTableChildChange( child, CHG_SPAN, 0, 0, col_span, row_span, 0); } void XpTableChildOptions( child, opts ) Widget child; /* Child widget to get new options */ XpTableOpts opts; /* New option mask */ { XpTableChildChange( child, CHG_OPTS, 0, 0, 0, 0, opts ); } void XpTableChildConfig( child, col, row, col_span, row_span, opts ) Widget child; /* Child widget to change */ int col, row; /* New position in table */ int col_span, row_span; /* New spans of child in table */ XpTableOpts opts; /* New size/justification opts */ { XpTableChildChange( child, CHG_ALL , col, row, col_span, row_span, opts); } /* Constructors **==============** */ Widget XpCreateTable( parent, name, arglist, argcount ) Widget parent; char* name; ArgList arglist; Cardinal argcount; { return XtCreateWidget(name, xpTableWidgetClass, parent, arglist, argcount); } /* Table Dialog Constructor ** Date: Fri, 8 Feb 91 12:23:39 EST ** From: pastor@PRC.Unisys.COM (Jon A. Pastor) */ #ifndef DIALOG_SUFFIX #define DIALOG_SUFFIX "_popup" #define DIALOG_SUFFIX_SIZE strlen(DIALOG_SUFFIX) #endif /* Destroy parent dialog shell when the child is destroyed. */ /*ARGSUSED*/ static void XpDestroyParentCallback( w, ignored, unused ) Widget w; XtPointer ignored, unused; { XtDestroyWidget( XtParent( w ) ); } Widget XpCreateTableDialog( parent, name, arglist, argcount ) Widget parent; char* name; ArgList arglist; Cardinal argcount; { return XpCreateTableTransient( parent, name, arglist, argcount ); } Widget XpCreateTableTransient( parent, name, arglist, argcount ) Widget parent; char* name; ArgList arglist; Cardinal argcount; { char* dsName; int i; Arg shellArgs[2]; Widget tableShell, table; /* Fabricate a name for the dialog shell using Motif 1.1 naming */ dsName = (char*)XtCalloc( strlen(name)+DIALOG_SUFFIX_SIZE+1, sizeof(char) ); strcpy( dsName, name ); strcat( dsName, DIALOG_SUFFIX ); /* Create a Transient Shell widget */ i = 0; XtSetArg( shellArgs[i], XtNallowShellResize, True); i++; #ifdef XtTransientForBugIsFixed #ifdef XtSpecificationRelease XtSetArg( shellArgs[i], XtNtransientFor, parent); i++; #endif #endif tableShell = XtCreatePopupShell( dsName, transientShellWidgetClass, parent, shellArgs, i ); XtFree( dsName ); /* Create the Table widget */ table = XtCreateWidget( name, xpTableWidgetClass, tableShell, arglist, argcount ); XtManageChild( table ); XtAddCallback( table, XtNdestroyCallback, XpDestroyParentCallback, (XtPointer)0 ); return table; } axe-6.1.2.orig/Widgets/TableLoc.c100644 243 144 31341 5550557116 15260 0ustar joostusers/*LINTLIBRARY*/ /* * SCCS_data: %Z% %M% %I% %E% %U% */ #include #include #ifdef sun #include /* why don't they just use X from mit!?! */ #include #endif #include /* TableLoc methods **==================** An Table widget keeps its default_layout and real_layout as two TableLoc's, which are pointers to the first element of a null terminated array of TableLocRecs. Each TableLocRec defines a Table widget child's location information (the row, col, spans, and layout options like justification and sizing controls). The default_layout describes where widgets may be placed if and when they become managed. The real_layout describes where managed children are actually placed. The default_layout differs slightly from the real_layout: Initially, it knows only the names of widgets (their quarks) as specified by the layout resource. As time goes on and widgets become managed or are placed, then the default_layout may also learn the actual identities of widgets. Note that it is possible and sometimes very useful to have multiple children with the same name, but different positions and/or options and/or sizes. If a table has multiple children of the same name, then there may be multiple default_layout and real_layout locs with the same quark but different widgets. The default_layout is created from a string by the TableLocParse function which is usually called via the converter. It is changed due to positioning and XtSetValues calls. The real_layout is calculated by the table's layout method, triggered by its ChangeManaged method and by the Positioning or SetValues methods. */ /* Allocate, Grow, and Free Arrays of TableLocRec's **==================================================** */ XpTableLoc XpTableLocNew( n ) int n; { return (XpTableLoc) XtCalloc( n+1, sizeof(XpTableLocRec) ); } XpTableLoc XpTableLocGrow( loc ) XpTableLoc loc; { static XpTableLocRec nullLoc; /* all zeros, as if XtCalloc'd */ int len = XpTableLocLen( loc ); /* XtRealloc leaves additional loc + terminating loc as garbage... */ XpTableLoc new = (XpTableLoc) XtRealloc( (char*)loc, (len+2)*sizeof(XpTableLocRec) ); /* ... so initialize the additional and terminating loc to NULLs */ new[len] = nullLoc; new[len+1] = nullLoc; /* Now new[TableLocLen(new)] is the additional location */ return new; } XpTableLoc XpTableLocCopy( loc ) XpTableLoc loc; { int len = XpTableLocLen( loc ); XpTableLoc copy = XpTableLocNew( len ); while (len--) copy[len] = loc[len]; return copy; } void XpTableLocFree( loc ) XpTableLoc loc; { XtFree( (char*)loc ); } /* Parse Layout String **=====================** Parse a layout string, allocating and setting the values. Return pointer to first element, or NULL if parse fails for any reason. The result is suitable for use in a call to XtSetValues(). A layout is a list of location specifications separated by semi-colons. Each location specification has the form: widget_name column row col_span row_span opt_list where the meaning of each field is: widget_name Name of the widget as given to XtCreateWidget(). column Integer >= 0 descibing column in array row Row >= 0 describing row in array col_span Integer >= 1 describing horizontal widget span row_span Integer >= 1 describing vertical widget span opt_list Series of characters each representing an option: l: TBL_LEFT r: TBL_RIGHT t: TBL_TOP b: TBL_BOTTOM w: TBL_LK_WIDTH h: TBL_LK_HEIGHT W: TBL_SM_WIDTH H: TBL_SM_HEIGHT The options are interpreted in the TableChildPosition() method. */ XpTableLoc XpTableLocParse( layout ) char* layout; { #ifndef CHILD_NAME_LEN #define CHILD_NAME_LEN 127 #endif char buf[CHILD_NAME_LEN+1]; int numLocs; XpTableLoc locs; /* array XtCalloc'd and returned */ XpTableLoc loc; /* current location being parsed */ int thisLoc; /* index of current loc */ int i; char* cp; if ( layout == (char*)0 || *layout == '\0' ) return (XpTableLoc)0; /* Figure out how many location specification there are in the layout. ** Each location specifier may be semi-colon SEPARATED, so we may ** have one more than the number of semi-colons. Space for null ** termination is provided by TableLocNew(). */ for ( numLocs = 1, cp = layout ; *cp ; cp++ ) if (*cp == ';') numLocs++; /* TableLocNew() provides additional NULL location so we do not ** need logic to null terminate array. */ locs = XpTableLocNew( numLocs ); loc = locs; thisLoc = 0; cp = layout; #define EAT_WHITESPACE(cp) while (*cp && *cp <= ' ') cp++; EAT_WHITESPACE(cp) while ( *cp && ++thisLoc <= numLocs ) { /* Parse a location specification from the layout string */ for (i = 0 ; ' ' < *cp && i < CHILD_NAME_LEN ; i++, cp++ ) buf[i] = *cp; buf[i] = '\0'; if ( i ) loc->w_quark = XrmStringToQuark(buf); /* widget name */ EAT_WHITESPACE(cp) while ('0' <= *cp && *cp <= '9') loc->col = loc->col * 10 + *cp++ - '0'; EAT_WHITESPACE(cp) while ('0' <= *cp && *cp <= '9') loc->row = loc->row * 10 + *cp++ - '0'; EAT_WHITESPACE(cp) while ('0' <= *cp && *cp <= '9') loc->col_span = loc->col_span * 10 + *cp++ - '0'; if (loc->col_span == 0) loc->col_span = 1; /* default span */ EAT_WHITESPACE(cp) while ('0' <= *cp && *cp <= '9') loc->row_span = loc->row_span * 10 + *cp++ - '0'; if (loc->row_span == 0) loc->row_span = 1; /* default span */ EAT_WHITESPACE(cp) i = 0; while ( *cp && i < CHILD_NAME_LEN && *cp == 'l' || *cp == 'r' || *cp == 't' || *cp == 'b' || *cp == 'w' || *cp == 'h' || *cp == 'W' || *cp == 'H' ) buf[i++] = *cp++; buf[i] = '\0'; if ( i ) loc->options = XpTableOptsParse( buf); while (*cp && *cp <= ' ' || *cp == ';' ) cp++; loc++; } if (*cp ) { /* Something went wrong. */ XpTableLocFree( locs ); locs = (XpTableLoc)0; } return locs; } int XpTableLocLen( loc) XpTableLoc loc; { int i = 0; for ( i = 0 ; loc && loc->w_quark != NULLQUARK ; loc++ ) i++; return i; } /* Find things in TableLocs **==========================** Linear search of TableLoc array looking for various parameters */ XpTableLoc XpTableLocFind( loc, w ) XpTableLoc loc; /* Table Locations to examine */ Widget w; /* Widget to find */ { if ( loc && w ) { for ( ; loc->w_quark != NULLQUARK ; loc++ ) { if ( loc->w_quark == w->core.xrm_name && loc->w == w ) return loc; } } return (XpTableLoc)0; } XpTableLoc XpTableLocFindDefault( loc, w ) XpTableLoc loc; /* Table Locations to examine */ Widget w; /* Widget to find */ { if ( loc && w ) { for ( ; loc->w_quark != NULLQUARK ; loc++ ) { if ( loc->w_quark == w->core.xrm_name && loc->w == (Widget)0 ) return loc; } } return (XpTableLoc)0; } XpTableLoc XpTableLocFindAtPosition( loc, col, row ) XpTableLoc loc; /* Table Locations to examine */ int col, row; /* position of widget to find */ { if ( loc && (0 <= col) && (0 <= row) ) { for ( ; loc->w_quark != NULLQUARK ; loc++ ) { if ( loc->col == col && loc->row == row ) return loc; } } return (XpTableLoc)0; } /* Preferred size determination: **==============================** This almost follows the Xt specification. There are two distinctions: First, if widgets are in any SameSize resource list, then that SameSize is the preferred size. This even overrides resize requests! Second, Xt says: "The changed_managed procedure may assume that the child's current geometry is its preferred geometry." This is usually wrong for Table: take the case where we have 5 widgets, all of size 1. Then 3 are unmanaged, and the layout causes the two remaining to become size 2.5. Then the same 3 are re-managed. They will want to be 1 again, the existing ones still 2.5. This causes a total size of 8. Table then squishes each down to make them fit, resulting in the sizes of the re-managed widgets becoming much smaller than the ones which were before. Repeat several more times, and the transient widgets become very small (size 1). */ int XpTableLocPreferredWidth( loc, tw ) XpTableLoc loc; /* preferred size of widget in this loc */ XpTableWidget tw; /* The widget containing this loc */ { /* First take care of situations where SameSize resources apply */ if ( loc->same_width && loc->same_border ) { return loc->same_width + 2 * loc->same_border; } else if ( loc->same_width && tw->table.resize_child == loc->w ) { return loc->same_width + 2 * tw->table.resize_border_width; } else if ( loc->same_width ) { return loc->same_width + 2 * loc->w->core.border_width; } else if ( loc->same_border && tw->table.resize_child == loc->w ) { return tw->table.resize_width + 2 * loc->same_border; } else if ( tw->table.resize_child == loc->w ) { /* Xt says: "The change request passed to the geometry manager takes * precedence over the preferred geometry [from XtQueryGeometry]" */ return tw->table.resize_width + 2 * tw->table.resize_border_width; } else if ( loc->options & TBL_SM_WIDTH ) { /* Do not change the size of this child from the size it * was when it first became managed. */ return loc->orig_width + 2 * loc->orig_border_width; } else if ( XtClass(loc->w)->core_class.query_geometry == NULL ) { /* If the widget cannot figure its size out except at creation time * (they can all at least do that), then we will use that originally * determined size. XtQueryGeometry returns the current size, which * looks like the widget wants to stay at a changed size, which it * usually does not: a label which has been shrunk seems to like * clipping its image (wrong!), a separator which has been stretched * seems to want to keep the interface wide (wrong!). */ return loc->orig_width + 2 * loc->orig_border_width; } else { XtWidgetGeometry child; int width = loc->w->core.width; int border = loc->w->core.border_width; (void)XtQueryGeometry(loc->w, (XtWidgetGeometry*)0, &child); if (child.request_mode & CWWidth) width = child.width; if (child.request_mode & CWBorderWidth) border = child.border_width; return width + 2*border; } } int XpTableLocPreferredHeight( loc, tw ) XpTableLoc loc; /* preferred size of widget in this loc */ XpTableWidget tw; /* The widget containing this loc */ { if ( loc->same_height && loc->same_border ) { return loc->same_height + 2 * loc->same_border; } else if ( loc->same_height && tw->table.resize_child == loc->w ) { return loc->same_height + 2 * tw->table.resize_border_width; } else if ( loc->same_height ) { return loc->same_height + 2 * loc->w->core.border_width; } else if ( loc->same_border && tw->table.resize_child == loc->w ) { return tw->table.resize_width + 2 * loc->same_border; } else if ( tw->table.resize_child == loc->w ) { return tw->table.resize_height + 2 * tw->table.resize_border_width; } else if ( loc->options & TBL_SM_HEIGHT ) { return loc->orig_height + 2 * loc->orig_border_width; } else if ( XtClass(loc->w)->core_class.query_geometry == NULL ) { return loc->orig_height + 2 * loc->orig_border_width; } else { XtWidgetGeometry child; int height = loc->w->core.height; int border = loc->w->core.border_width; (void)XtQueryGeometry(loc->w, (XtWidgetGeometry*)0, &child); if (child.request_mode & CWHeight) height = child.height; if (child.request_mode & CWBorderWidth) border = child.border_width; return height + 2*border; } } int XpTableLocNumCols( loc ) XpTableLoc loc; { int cols; for ( cols = 0 ; loc && loc->w_quark != NULLQUARK ; loc++ ) if ( cols < (loc->col + loc->col_span) ) cols = loc->col + loc->col_span; return cols; } int XpTableLocNumRows( loc ) XpTableLoc loc; { int rows; for ( rows = 0 ; loc && loc->w_quark != NULLQUARK ; loc++) if ( rows < (loc->row + loc->row_span) ) rows = loc->row + loc->row_span; return rows; } /* Used by qsort when the real_layout table is sorted by ** span before doing distribution of space to rows or columns. */ int XpTableLocCompareColSpan( loc1, loc2 ) XpTableLoc loc1, loc2; { if ( loc1->col_span == loc2->col_span ) return loc1->col - loc2->col; return loc1->col_span - loc2->col_span; } int XpTableLocCompareRowSpan( loc1, loc2 ) XpTableLoc loc1, loc2; { if ( loc1->row_span == loc2->row_span ) return loc1->row - loc2->row; return loc1->row_span - loc2->row_span; } axe-6.1.2.orig/Widgets/TableVec.c100644 243 144 40273 5550557116 15264 0ustar joostusers/*LINTLIBRARY*/ /* * SCCS_data: @(#) TableVec.c 1.8 93/01/29 08:10:55 */ #include #include #ifdef sun #include /* why don't they just use X from mit!?! */ #include #endif #include /* TableVector Methods **=====================** Each Table instance has two TableVectors: one describes the columns, and the other describes the rows. The table vectors are created based on information in the real_layout TableLoc array, hence they must be created after the real_layout, and they must be updated when the real_layout changes. The real_layout data upon which the vectors depend is: number of cols, number of rows, options (only TBL_SM_WIDTH and TBL_SM_HEIGHT). */ XpTableVector XpTableVectorNew( size, tw, do_col ) int size; XpTableWidget tw; int do_col; { int minimize, dontStretch, first_slot, last_slot, slot; XpTableLoc loc = tw->table.real_layout; XpTableVector vec; if ( (XpTableLoc)0 == loc || 0 == size ) return (XpTableVector)0; vec = (XpTableVector) XtCalloc( size+1, sizeof(XpTableVectorRec)); /* Determine which slots need to be minimized */ for ( ; loc->w ; loc++ ) { if ( do_col ) { minimize = loc->options & TBL_SM_WIDTH; dontStretch = loc->options & TBL_LK_WIDTH; first_slot = loc->col; last_slot = loc->col + loc->col_span; } else { minimize = loc->options & TBL_SM_HEIGHT; dontStretch = loc->options & TBL_LK_HEIGHT; first_slot = loc->row; last_slot = loc->row + loc->row_span; } if ( minimize ) for ( slot = first_slot ; slot < last_slot ; slot++ ) vec[ slot ].options |= TBL_VEC_MINIMIZE; if ( dontStretch ) for ( slot = first_slot ; slot < last_slot ; slot++ ) vec[ slot ].options |= TBL_VEC_LOCK; } XpTableVectorMinimize( vec, size, tw, do_col ); return vec; } void XpTableVectorFree( vec ) XpTableVector vec ; { XtFree( (char*)vec ); } /* Minimize Column Widths and Row Heights **========================================** Change the vector to be its minimum size in the direction indicated. If TBL_VEC_MINIMIZE (i.e., TBL_SM_WIDTH (W) or TBL_SM_HEIGHT (H)) then the widget is kept to its original size. TBL_VEC_LOCK (i.e., TBL_LK_WIDTH (w) or TBL_LK_HEIGHT (h) ) not checked, because such widgets DO grow to the minimum size of the column or row. */ void XpTableVectorMinimize( vec, vec_len, tw, do_col ) XpTableVector vec; int vec_len; XpTableWidget tw; int do_col; { int i; XpTableLoc loc = tw->table.real_layout; Widget resize_child = tw->table.resize_child; int resize_width = tw->table.resize_width; int resize_height = tw->table.resize_height; int resize_border_width = tw->table.resize_border_width; if ( (XpTableVector)0 == vec || 0 == vec_len ) return; /* Sort real_layout (in-place) by the number of columns or rows each child ** spans so we first compute sizes of individual columns or rows, then ** compute the spanned columns or rows. */ if ( do_col ) qsort( (char*)loc, /* sort real_layout */ XpTableLocLen(loc), sizeof(XpTableLocRec), XpTableLocCompareColSpan ); /* compare column spans */ else qsort( (char*)loc, /* sort real_layout */ XpTableLocLen(loc), sizeof(XpTableLocRec), XpTableLocCompareRowSpan ); /* compare row spans */ /* Reset all width|heights to zero, then expand to fit */ for ( i = 0 ; i < vec_len ; i++ ) vec[i].value = 0; for ( ; loc->w ; loc++ ) { int pref; /* Check for simple case (span of 1), where col or row just becomes ** large enough for largest child in that col or row. */ if ( do_col && loc->col_span == 1 ) { pref = XpTableLocPreferredWidth( loc, tw ); if ( pref > vec[ loc->col ].value ) vec[ loc->col ].value = pref; } else if ( !do_col && loc->row_span == 1 ) { pref = XpTableLocPreferredHeight( loc, tw ); if ( pref > vec[ loc->row ].value ) vec[ loc->row ].value = pref; } else { /* Spans multiple columns or rows. We have already set each ** column or row to the individual size requirements, now we can ** see which spanned columns or rows need to be stretched. The ** span width includes inter-column or inter-row spacing. */ int to_stretch, span_size, first_slot, stop_before, slot; int can_stretch = 0; if ( do_col ) { span_size = tw->table.col_spacing * (loc->col_span-1); first_slot = loc->col; stop_before = loc->col + loc->col_span; } else { span_size = tw->table.row_spacing * (loc->row_span-1); first_slot = loc->row; stop_before = loc->row + loc->row_span; } for ( slot = first_slot ; slot < stop_before ; slot++ ) { if ( 0 == (vec[ slot ].options & TBL_VEC_LOCK) ) can_stretch++; span_size += vec[ slot ].value; } /* If none of the slots can stretch, then we still must force ** them all to stretch at least to the orig_size of this widget. */ if ( 0 == can_stretch ) { if ( do_col ) { to_stretch = loc->col_span; if ( loc->w == resize_child ) pref = resize_width + 2 * resize_border_width; else pref = loc->orig_width + 2 * loc->orig_border_width; } else { to_stretch = loc->row_span; if ( loc->w == resize_child ) pref = resize_height + 2 * resize_border_width; else pref = loc->orig_height + 2 * loc->orig_border_width; } } else { to_stretch = can_stretch; if ( do_col ) { pref = XpTableLocPreferredWidth( loc, tw ); } else { pref = XpTableLocPreferredHeight( loc, tw ); } } if ( span_size < pref ) { /* Increase size of some or all slots: if nothing ** can stretch, expand every slot, else expand only ** those which are not locked small. */ int excess = pref - span_size; int amt = excess / to_stretch; int truncated = excess - amt*to_stretch; for ( slot = first_slot ; slot < stop_before ; slot++ ) { if ( 0 == can_stretch || 0 == (vec[ slot ].options & TBL_VEC_LOCK) ) { if ( truncated ) { vec[ slot ].value += amt + 1; --truncated; } else vec[ slot ].value += amt; } } } } } /* The vector is minimized: set pref_value from value */ for ( i = 0 ; i < vec_len ; i++ ) vec[i].pref_value = vec[i].value; } /* Total Width or Height **=======================** Including inter-column and inter-row spacing, and margins. Works even when there are no columns or rows (vec==num==0). */ #define DO_ACTUAL 1 #define DO_PREFERRED 0 static int XpTableVectorSize( vec, num, tw, do_col, do_actual ) XpTableVector vec; int num; XpTableWidget tw; int do_col; int do_actual; { int slot, size, space; if (do_col) { space = tw->table.col_spacing; size = 2*tw->table.margin_width; } else { space = tw->table.row_spacing; size = 2*tw->table.margin_height; } if ( 0 != num && (XpTableVector)0 != vec ) { if (do_actual) { for ( size -= space, slot = 0 ; slot < num ; slot++ ) size += vec[ slot ].value + space; } else { for ( size -= space, slot = 0 ; slot < num ; slot++ ) size += vec[ slot ].pref_value + space; } } if ( size > 0 ) return size; else return 1; /* minimum size */ } int XpTableVectorTotalSize( vec, num, tw, do_col ) XpTableVector vec; int num; XpTableWidget tw; int do_col; { return XpTableVectorSize( vec, num, tw, do_col, DO_ACTUAL ); } int XpTableVectorPreferredSize( vec, num, tw, do_col ) XpTableVector vec; int num; XpTableWidget tw; int do_col; { return XpTableVectorSize( vec, num, tw, do_col, DO_PREFERRED ); } #undef DO_ACTUAL #undef DO_PREFERRED /* Adjust rows or columns **========================** When a parent re-sizes a Table, it can make it larger or smaller. The adjustment is distributed as a ratio of the preferred sizes of the col/row, so small ones change slower than larger ones. If the table wants to restrict making things smaller than preferred, then it must simply never respond to resize commands which make the table smaller than its preferred size. Nowhere in the logic below is there any mechanism which prevents things from shrinking smaller than the preferred size. There is, however, mechanisms to prevent any col or row from becoming smaller than 1. If resize makes the Table larger than before: First, all col/row smaller that preferred size are stretched up until their preferred size. The rest of the change is distributed evenly to un-locked col/row, but if all are locked, then all are stretched. If the table is being made smaller, then the inverse is applied: all unlocked (or all if all are locked) are made smaller down to their preferred sizes, then all are made smaller by the same amount. Adjustments to the vectors are made on a relative basis. Big slots change more than small slots. Therefore, the adjustment delta is computed for each slot which might change. While adjusting the vectors, there are too things to watch out for: lots of slots to change, yet not much change, integer truncation then leaves the delta zero. In this case we make the delta 1, which means the change gets used up before all the slots are seen. We use the same algorithm for growing and shrinking, so there should be no perceivable problems. The second problem is when the delta would consume too much change, again due to integer truncation. In this case, we must simply make the delta equal to the remaining change. Notice that there are two resize algorithms used: one applies when everything is smaller than preferred, and another applies when everything is bigger. When smaller, everything gets changed relatively. When larger, change is influenced by the table slot being locked (TBL_VEC_LOCK). Slots which are locked are not adjusted unless ALL slots are locked, then all are adjusted relatively. */ void XpTableVectorAdjust( vec, vec_len, change ) XpTableVector vec; int vec_len, change; { int vec_inx, remaining, amt; int total_pref; int can_change, can_change_pref; int too_small; int too_big, too_big_pref; if ( (XpTableVector)0 == vec || 0 == vec_len || 0 == change ) return; total_pref = can_change = can_change_pref = 0; too_small = too_big = too_big_pref = 0; for ( vec_inx=0 ; vec_inx < vec_len ; vec_inx++ ) { /* NOTE: total_pref can be zero if all pref_value are 0! */ total_pref += vec[ vec_inx ].pref_value; if ( change > 0 ) { if ( 0 == ( vec[ vec_inx ].options & TBL_VEC_LOCK ) ) { /* NOTE: can_change_pref can be zero if all pref_value are 0! */ can_change++; can_change_pref += vec[ vec_inx ].pref_value; } if ( vec[ vec_inx ].value < vec[ vec_inx ].pref_value ) { too_small++; } } else { if ( vec[ vec_inx ].value > vec[ vec_inx ].pref_value ) { /* NOTE: too_big_pref can be zero if all pref_value are 0! */ too_big++; too_big_pref += vec[ vec_inx ].pref_value; } } } if ( change > 0 ) { /**************** Make columns wider or rows taller *************** */ int still_too_small; remaining = change; do { /* Expand everything smaller than preferred up to preferred */ still_too_small = 0; for ( vec_inx=0 ; vec_inx < vec_len ; vec_inx++ ) { if ( vec[ vec_inx ].value < vec[ vec_inx ].pref_value ) { /* Make this one bigger, up to preferred size */ if ( 0 == total_pref ) amt = change / (too_small?too_small:vec_len); else amt = change * vec[ vec_inx ].pref_value / total_pref; if ( 0 == amt ) amt = 1; else if ( remaining < amt ) amt = remaining; if ( vec[vec_inx].value + amt < vec[vec_inx].pref_value ) { vec[ vec_inx ].value += amt; ++still_too_small; } else { amt = vec[vec_inx].pref_value - vec[vec_inx].value; vec[vec_inx].value = vec[vec_inx].pref_value; } remaining -= amt; if ( remaining <= 0 ) return; /* used up all change */ } } change = remaining; } while ( still_too_small ); /* All are at least preferred size, and there is change remaining. * If none of the vector slots can stretch, then we still must * force them all to stretch. */ if ( 0 == can_change ) can_change_pref = total_pref; /* maintain relative sizes */ do { for ( vec_inx = 0 ; vec_inx < vec_len ; vec_inx++ ) { if ( 0 == can_change || 0 == ( vec[ vec_inx ].options & TBL_VEC_LOCK ) ) { /* Add relative amount to all which can change. */ if ( 0 == can_change_pref ) amt = change / (can_change?can_change:vec_len); else amt = change * vec[vec_inx].pref_value/can_change_pref; if ( 0 == amt ) amt = 1; else if ( remaining < amt ) amt = remaining; vec[ vec_inx ].value += amt; remaining -= amt; if ( remaining <= 0 ) return; /* used up all change */ } } /* We have gone thru vector, adding space, but due to truncation * there may still be more change to distribute. */ change = remaining; } while ( 1 ); /* until remaining goes to zero or negative above */ /*NOTREACHED*/ } else /* (change < 0) */ { /**************** Make columns narrower or rows shorter *************** */ int still_too_big, num_larger_than_1; /* For conceptual clarity, switch the sign on change */ change = -change; remaining = change; still_too_big = too_big; while ( still_too_big ) { /* Shrink all which are larger than preferred */ still_too_big = 0; for ( vec_inx = 0 ; vec_inx < vec_len ; vec_inx++ ) { if ( vec[ vec_inx ].value > vec[ vec_inx ].pref_value ) { if ( 0 == too_big_pref ) amt = change / (too_big?too_big:vec_len); else amt = change * vec[vec_inx].pref_value / too_big_pref; if ( 0 == amt ) amt = 1; else if ( remaining < amt ) amt = remaining; if ( vec[ vec_inx ].value - amt < vec[ vec_inx ].pref_value) { amt = vec[ vec_inx ].value - vec[ vec_inx ].pref_value; vec[ vec_inx ].value = vec[ vec_inx ].pref_value; } else { vec[ vec_inx ].value -= amt; still_too_big++; } remaining -= amt; if ( remaining <= 0 ) return; /* used up all change */ } } /* We have made a pass through all slots */ change = remaining; } /* Now all stretchable are preferred sizes, or all were already smaller * than preferred sizes, yet more change is remaining to be absorbed. * * Shrink evenly, but since none can become smaller than 1, we may need * to make multiple passes over vector until total change is absorbed, * or all are of size 1. */ do { num_larger_than_1 = 0; for ( vec_inx = 0 ; vec_inx < vec_len ; vec_inx++ ) { if ( 0 == total_pref ) amt = change / vec_len; else amt = change * vec[vec_inx].pref_value / total_pref; if ( 0 == amt ) amt = 1; else if ( remaining < amt ) amt = remaining; if ( amt < vec[vec_inx].value ) { vec[vec_inx].value -= amt; ++num_larger_than_1; } else { amt = vec[vec_inx].value - 1; vec[vec_inx].value = 1; } remaining -= amt; if ( remaining <= 0 ) return; /* used up all change */ } /* We have made a pass through all slots */ change = remaining; } while ( num_larger_than_1 ); return; /* all are shrunk to absolute minimum size (1) */ } /*NOTREACHED*/ } /* Set Upper Left Corner Coordinates of Each Cell **================================================** Note that it is not worth doing this until the actual correct size of the rows and columns have been computed. */ void XpTableVectorComputeOffsets( vec, vec_len, margin, gap ) XpTableVector vec; int vec_len, margin, gap; { int i; int offset = margin; if ( (XpTableVector)0 == vec || 0 == vec_len ) return; for ( i = 0 ; i < vec_len ; i++ ) { vec[i].offset = offset; offset = offset + vec[i].value + gap; } } axe-6.1.2.orig/Widgets/Viewlist.c100644 243 144 13537 5550557116 15410 0ustar joostusers/* * Copyright 1992 The University of Newcastle upon Tyne * * Permission to use, copy, modify and distribute this software and its * documentation for any purpose other than its commercial exploitation * is hereby granted without fee, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of The University of Newcastle upon Tyne not be used in * advertising or publicity pertaining to distribution of the software * without specific, written prior permission. The University of * Newcastle upon Tyne makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * THE UNIVERSITY OF NEWCASTLE UPON TYNE DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF * NEWCASTLE UPON TYNE BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. * * Author: Jim Wight (j.k.wight@newcastle.ac.uk) * Department of Computing Science * University of Newcastle upon Tyne, UK */ #include #include #include #include #define PRIVATE(w,field) (((ViewlistWidget) w)->viewlist.field) #define Offset(field) XtOffsetOf(ViewlistRec, viewlist.field) static XtResource resources[] = { {XtNlistWidget, XtCListWidget, XtRWidget, sizeof(Widget), Offset(list_widget), XtRImmediate, (XtPointer) 0}, }; #undef Offset static void Initialize(); static XtGeometryResult GeometryManager(); ViewlistClassRec viewlistClassRec = { { /* core_class fields */ /* superclass */ (WidgetClass) &viewportClassRec, /* class_name */ "Viewlist", /* widget_size */ sizeof(ViewlistRec), /* class_initialize */ NULL, /* class_part_init */ NULL, /* class_inited */ FALSE, /* initialize */ Initialize, /* initialize_hook */ NULL, /* realize */ XtInheritRealize, /* actions */ NULL, /* num_actions */ 0, /* resources */ resources, /* num_resources */ XtNumber(resources), /* xrm_class */ NULLQUARK, /* compress_motion */ TRUE, /* compress_exposure */ TRUE, /* compress_enterleave*/ TRUE, /* visible_interest */ FALSE, /* destroy */ NULL, /* resize */ XtInheritResize, /* expose */ XtInheritExpose, /* set_values */ NULL, /* set_values_hook */ NULL, /* set_values_almost */ XtInheritSetValuesAlmost, /* get_values_hook */ NULL, /* accept_focus */ NULL, /* version */ XtVersion, /* callback_private */ NULL, /* tm_table */ NULL, /* query_geometry */ XtInheritQueryGeometry, /* display_accelerator*/ XtInheritDisplayAccelerator, /* extension */ NULL }, { /* composite_class fields */ /* geometry_manager */ GeometryManager, /* change_managed */ XtInheritChangeManaged, /* insert_child */ XtInheritInsertChild, /* delete_child */ XtInheritDeleteChild, /* extension */ NULL }, { /* constraint_class fields */ /* subresourses */ NULL, /* subresource_count */ 0, /* constraint_size */ sizeof(ViewportConstraintsRec), /* initialize */ NULL, /* destroy */ NULL, /* set_values */ NULL, /* extension */ NULL }, { /* form_class fields */ /* layout */ XtInheritLayout }, { /* viewport_class fields */ /* empty */ 0 }, { /* viewlist_class fields */ /* extension */ NULL } }; WidgetClass viewlistWidgetClass = (WidgetClass) &viewlistClassRec; /* ARGSUSED */ static void Initialize(req, new, args, num_args) Widget req, new; ArgList args; Cardinal *num_args; { PRIVATE(new,list_widget) = XtVaCreateManagedWidget("list", listWidgetClass, new, NULL); } static XtGeometryResult GeometryManager(w, desired, allowed) Widget w; XtWidgetGeometry *desired, *allowed; { ViewlistWidget vw = (ViewlistWidget) XtParent(w); XtWidgetGeometry request; XtGeometryResult result; #define REQUESTS(flag) (desired->request_mode & flag) request.request_mode = desired->request_mode; request.width = desired->width; request.height = desired->height; if (request.width < vw->core.width) { request.width = vw->core.width; request.request_mode |= CWWidth; } result = XtMakeGeometryRequest((Widget) vw, &request, allowed); if (REQUESTS(XtCWQueryOnly)) { return result; } if (result == XtGeometryYes) { if (REQUESTS(CWWidth)) { w->core.width = vw->core.width; } if (REQUESTS(CWHeight) && request.height < vw->core.height) { w->core.height = vw->core.height; } } return result; #undef REQUESTS /* if (desired->width >= vw->core.width) { w->core.width = desired->width; w->core.height = desired->height; if (desired->height < vw->core.height) { w->core.height = vw->core.height; } printf("Returning Yes\n"); return XtGeometryYes; } else { allowed->request_mode = desired->request_mode; allowed->width = vw->core.width; allowed->height = desired->height; printf("Returning Almost\n"); return XtGeometryAlmost; } */ } axe-6.1.2.orig/Widgets/Viewlist.h100644 243 144 3323 5550557124 15364 0ustar joostusers/* * Copyright 1992 The University of Newcastle upon Tyne * * Permission to use, copy, modify and distribute this software and its * documentation for any purpose other than its commercial exploitation * is hereby granted without fee, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of The University of Newcastle upon Tyne not be used in * advertising or publicity pertaining to distribution of the software * without specific, written prior permission. The University of * Newcastle upon Tyne makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * THE UNIVERSITY OF NEWCASTLE UPON TYNE DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF * NEWCASTLE UPON TYNE BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. * * Author: Jim Wight (j.k.wight@newcastle.ac.uk) * Department of Computing Science * University of Newcastle upon Tyne, UK */ #ifndef _Viewlist_h #define _Viewlist_h extern WidgetClass viewlistWidgetClass; typedef struct _ViewlistClassRec *ViewlistWidgetClass; typedef struct _ViewlistRec *ViewlistWidget; #define XtNlistWidget "listWidget" #define XtCListWidget "ListWidget" #endif /* _Viewlist_h */ axe-6.1.2.orig/Widgets/ViewlistP.h100644 243 144 4572 5550557124 15513 0ustar joostusers/* * Copyright 1992 The University of Newcastle upon Tyne * * Permission to use, copy, modify and distribute this software and its * documentation for any purpose other than its commercial exploitation * is hereby granted without fee, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of The University of Newcastle upon Tyne not be used in * advertising or publicity pertaining to distribution of the software * without specific, written prior permission. The University of * Newcastle upon Tyne makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * THE UNIVERSITY OF NEWCASTLE UPON TYNE DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF * NEWCASTLE UPON TYNE BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. * * Author: Jim Wight (j.k.wight@newcastle.ac.uk) * Department of Computing Science * University of Newcastle upon Tyne, UK */ #ifndef _ViewlistP_h #define _ViewlistP_h /* Don't know why these two are needed, when the superclass doesn't */ #include #include #include #include typedef struct { XtPointer extension; } ViewlistClassPart; typedef struct _ViewlistClassRec { CoreClassPart core_class; CompositeClassPart composite_class; ConstraintClassPart constraint_class; FormClassPart form_class; ViewportClassPart viewport_class; ViewlistClassPart viewlist_list; } ViewlistClassRec; extern ViewlistClassRec viewlistClassRec; typedef struct _ViewlistPart { /* resources */ Widget list_widget; /* private variables */ } ViewlistPart; typedef struct _ViewlistRec { CorePart core; CompositePart composite; ConstraintPart constraint; FormPart form; ViewportPart viewport; ViewlistPart viewlist; } ViewlistRec; #endif /* _ViewlistP_h */ axe-6.1.2.orig/Widgets/axeLogo.xbm100644 243 144 643 5550557125 15476 0ustar joostusers#define axeLogo_width 30 #define axeLogo_height 13 static unsigned char axeLogo_bits[] = { 0x80, 0x01, 0x00, 0x00, 0x60, 0x02, 0x00, 0x00, 0x18, 0x04, 0x00, 0x00, 0x07, 0x08, 0x00, 0x00, 0x01, 0x18, 0x00, 0x00, 0x02, 0x24, 0x00, 0x00, 0x04, 0x44, 0x00, 0x00, 0x08, 0x82, 0x01, 0x00, 0x10, 0x02, 0x06, 0x00, 0x20, 0x01, 0x18, 0x00, 0x40, 0x01, 0xe0, 0x00, 0x80, 0x01, 0x00, 0x07, 0x00, 0x00, 0x00, 0x38}; axe-6.1.2.orig/Widgets/blockCaret.xbm100644 243 144 304 5550557125 16143 0ustar joostusers#define blockCaret_width 8 #define blockCaret_height 15 static unsigned char blockCaret_bits[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; axe-6.1.2.orig/Widgets/bwdArrow.xbm100644 243 144 320 5550557125 15657 0ustar joostusers#define bwdArrow_width 11 #define bwdArrow_height 9 static unsigned char bwdArrow_bits[] = { 0x20, 0x00, 0x70, 0x00, 0xf8, 0x00, 0xfc, 0x01, 0xfe, 0x03, 0xff, 0x07, 0x70, 0x00, 0x70, 0x00, 0x00, 0x00}; axe-6.1.2.orig/Widgets/fwdArrow.xbm100644 243 144 320 5550557126 15664 0ustar joostusers#define fwdArrow_width 11 #define fwdArrow_height 9 static unsigned char fwdArrow_bits[] = { 0x00, 0x00, 0x70, 0x00, 0x70, 0x00, 0xff, 0x07, 0xfe, 0x03, 0xfc, 0x01, 0xf8, 0x00, 0x70, 0x00, 0x20, 0x00}; axe-6.1.2.orig/Widgets/hzCentre.xbm100644 243 144 350 5550557126 15656 0ustar joostusers#define hzCentre_width 9 #define hzCentre_height 11 static unsigned char hzCentre_bits[] = { 0x10, 0x00, 0x10, 0x00, 0x11, 0x01, 0x93, 0x01, 0xd7, 0x01, 0xff, 0x01, 0xd7, 0x01, 0x93, 0x01, 0x11, 0x01, 0x10, 0x00, 0x10, 0x00}; axe-6.1.2.orig/Widgets/insertfile.c100644 243 144 4156 5550557116 15723 0ustar joostusers/* InsertFileNamed is taken from .../mit/lib/Xaw/TextPop.c */ /*********************************************************** Copyright 1989 by the Massachusetts Institute of Technology, Cambridge, Massachusetts. All Rights Reserved Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation, and that the names of Digital or MIT not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ******************************************************************/ #include #include #include #include Boolean InsertFileNamed(tw, str) Widget tw; char *str; { int fid; XawTextBlock text; char buf[BUFSIZ]; XawTextPosition start_pos, pos; if ( (str == NULL) || (strlen(str) == 0) || ((fid = open(str, O_RDONLY)) <= 0)) return(FALSE); start_pos = pos = XawTextGetInsertionPoint(tw); text.firstPos = 0; text.format = FMT8BIT; while ((text.length = read(fid, buf, BUFSIZ)) > 0) { text.ptr = buf; if (XawTextReplace(tw, pos, pos, &text) != XawEditDone) { /* * If the replace failed then remove what we have * replaced so far, and return an error. */ text.length = 0; (void) XawTextReplace(tw, start_pos, pos, &text); (void) close(fid); return(FALSE); } pos += text.length; } (void) close(fid); XawTextSetInsertionPoint(tw, pos); return(TRUE); } axe-6.1.2.orig/Widgets/match.c100644 243 144 7306 5550557116 14653 0ustar joostusers/* * match.c is taken from Release 1.4 of Byron Rakitzis' rc command interpreter * based on the AT & T Plan 9 shell of the same name. It has only been modified * to the extent of reverting to old C, defining some things locally that are * defined in rc.h in the rc distribution and extending to accept ! and ^ as * additional complementing characters in range checking. * rc's COPYRIGHT notice follows. */ /* * Copyright 1991 Byron Rakitzis. All rights reserved. * * This software is not subject to any license of the American Telephone * and Telegraph Company or of the Regents of the University of California. * * Permission is granted to anyone to use this software for any purpose on * any computer system, and to alter it and redistribute it freely, subject * to the following restrictions: * * 1. The author is not responsible for the consequences of use of this * software, no matter how awful, even if they arise from flaws in it. * * 2. The origin of this software must not be misrepresented, either by * explicit claim or by omission. Since few users ever read sources, * credits must appear in the documentation. * * 3. Altered versions must be plainly marked as such, and must not be * misrepresented as being the original software. Since few users * ever read sources, credits must appear in the documentation. * * 4. This notice may not be removed or altered. * * [this copyright notice is adapted from Henry Spencer's * "awf" copyright notice.] */ /* match.c: pattern matching routines */ static int rangematch(); enum { RANGE_FAIL = -1, RANGE_ERROR = -2 }; typedef enum bool { FALSE, TRUE } bool; #define streq(x, y) (*(x) == *(y) && strcmp(x, y) == 0) /* match() matches a single pattern against a single string. */ bool match(p, m, s) char *p, *m, *s; { int i, j; if (m == 0) return streq(p, s); i = 0; while (1) { if (p[i] == '\0') return *s == '\0'; else if (m[i]) { switch (p[i++]) { case '?': if (*s++ == '\0') return FALSE; break; case '*': while (p[i] == '*' && m[i] == 1) /* collapse multiple stars */ i++; if (p[i] == '\0') /* star at end of pattern? */ return TRUE; while (*s != '\0') if (match(p + i, m + i, s++)) return TRUE; return FALSE; case '[': if (*s == '\0') return FALSE; switch (j = rangematch(p + i, *s)) { default: i += j; break; case RANGE_FAIL: return FALSE; case RANGE_ERROR: if (*s != '[') return FALSE; } s++; break; default: /* fprintf(stderr,"bad metacharacter in match\n"); */ /* NOTREACHED */ return FALSE; } } else if (p[i++] != *s++) return FALSE; } } /* From the ed(1) man pages (on ranges): The `-' is treated as an ordinary character if it occurs first (or first after an initial ^) or last in the string. The right square bracket does not terminate the enclosed string if it is the first character (after an initial `^', if any), in the bracketed string. rangematch() matches a single character against a class, and returns an integer offset to the end of the range on success, or -1 on failure. */ static int rangematch(p,c) char *p, c; { char *orig = p; bool neg = (*p == '~' || *p == '!' || *p == '^'); bool matched = FALSE; if (neg) p++; if (*p == ']') { p++; matched = (c == ']'); } for (; *p != ']'; p++) { if (*p == '\0') return RANGE_ERROR; /* bad syntax */ if (p[1] == '-' && p[2] != ']') { /* check for [..-..] but ignore [..-] */ if (c >= *p) matched |= (c <= p[2]); p += 2; } else { matched |= (*p == c); } } if (matched ^ neg) return p - orig + 1; /* skip the right-bracket */ else return RANGE_FAIL; } axe-6.1.2.orig/Widgets/modMark.xbm100644 243 144 314 5550557126 15466 0ustar joostusers#define modMark_width 9 #define modMark_height 9 static unsigned char modMark_bits[] = { 0x00, 0x00, 0x10, 0x00, 0x7c, 0x00, 0x7c, 0x00, 0xfe, 0x00, 0x7c, 0x00, 0x7c, 0x00, 0x10, 0x00, 0x00, 0x00}; axe-6.1.2.orig/Widgets/regexp.c100644 243 144 66420 5550557117 15074 0ustar joostusers/* * This is an unmodified regexp.c for aXe with the exception of the * inclusion of regerror, which is made static. This avoids a name * clash arising out of Tcl's use of the same regexp software. */ /* * regcomp and regexec -- regsub and regerror are elsewhere * * Copyright (c) 1986 by University of Toronto. * Written by Henry Spencer. Not derived from licensed software. * * Permission is granted to anyone to use this software for any * purpose on any computer system, and to redistribute it freely, * subject to the following restrictions: * * 1. The author is not responsible for the consequences of use of * this software, no matter how awful, even if they arise * from defects in it. * * 2. The origin of this software must not be misrepresented, either * by explicit claim or by omission. * * 3. Altered versions must be plainly marked as such, and must not * be misrepresented as being the original software. * * Beware that some of this code is subtly aware of the way operator * precedence is structured in regular expressions. Serious changes in * regular-expression syntax might require a total rethink. */ #include #include "regexp.h" #include "regmagic.h" /* * The "internal use only" fields in regexp.h are present to pass info from * compile to execute that permits the execute phase to run lots faster on * simple cases. They are: * * regstart char that must begin a match; '\0' if none obvious * reganch is the match anchored (at beginning-of-line only)? * regmust string (pointer into program) that match must include, or NULL * regmlen length of regmust string * * Regstart and reganch permit very fast decisions on suitable starting points * for a match, cutting down the work a lot. Regmust permits fast rejection * of lines that cannot possibly match. The regmust tests are costly enough * that regcomp() supplies a regmust only if the r.e. contains something * potentially expensive (at present, the only such thing detected is * or + * at the start of the r.e., which can involve a lot of backup). Regmlen is * supplied because the test in regexec() needs it and regcomp() is computing * it anyway. */ /* * Structure for regexp "program". This is essentially a linear encoding * of a nondeterministic finite-state machine (aka syntax charts or * "railroad normal form" in parsing technology). Each node is an opcode * plus a "next" pointer, possibly plus an operand. "Next" pointers of * all nodes except BRANCH implement concatenation; a "next" pointer with * a BRANCH on both ends of it is connecting two alternatives. (Here we * have one of the subtle syntax dependencies: an individual BRANCH (as * opposed to a collection of them) is never concatenated with anything * because of operator precedence.) The operand of some types of node is * a literal string; for others, it is a node leading into a sub-FSM. In * particular, the operand of a BRANCH node is the first node of the branch. * (NB this is *not* a tree structure: the tail of the branch connects * to the thing following the set of BRANCHes.) The opcodes are: */ /* definition number opnd? meaning */ #define END 0 /* no End of program. */ #define BOL 1 /* no Match "" at beginning of line. */ #define EOL 2 /* no Match "" at end of line. */ #define ANY 3 /* no Match any one character. */ #define ANYOF 4 /* str Match any character in this string. */ #define ANYBUT 5 /* str Match any character not in this string. */ #define BRANCH 6 /* node Match this alternative, or the next... */ #define BACK 7 /* no Match "", "next" ptr points backward. */ #define EXACTLY 8 /* str Match this string. */ #define NOTHING 9 /* no Match empty string. */ #define STAR 10 /* node Match this (simple) thing 0 or more times. */ #define PLUS 11 /* node Match this (simple) thing 1 or more times. */ #define OPEN 20 /* no Mark this point in input as start of #n. */ /* OPEN+1 is number 1, etc. */ #define CLOSE 30 /* no Analogous to OPEN. */ /* * Opcode notes: * * BRANCH The set of branches constituting a single choice are hooked * together with their "next" pointers, since precedence prevents * anything being concatenated to any individual branch. The * "next" pointer of the last BRANCH in a choice points to the * thing following the whole choice. This is also where the * final "next" pointer of each individual branch points; each * branch starts with the operand node of a BRANCH node. * * BACK Normal "next" pointers all implicitly point forward; BACK * exists to make loop structures possible. * * STAR,PLUS '?', and complex '*' and '+', are implemented as circular * BRANCH structures using BACK. Simple cases (one character * per match) are implemented with STAR and PLUS for speed * and to minimize recursive plunges. * * OPEN,CLOSE ...are numbered at compile time. */ /* * A node is one char of opcode followed by two chars of "next" pointer. * "Next" pointers are stored as two 8-bit pieces, high order first. The * value is a positive offset from the opcode of the node containing it. * An operand, if any, simply follows the node. (Note that much of the * code generation knows about this implicit relationship.) * * Using two bytes for the "next" pointer is vast overkill for most things, * but allows patterns to get big without disasters. */ #define OP(p) (*(p)) #define NEXT(p) (((*((p)+1)&0377)<<8) + *((p)+2)&0377) #define OPERAND(p) ((p) + 3) /* * See regmagic.h for one further detail of program structure. */ /* * Utility definitions. */ #ifndef CHARBITS #define UCHARAT(p) ((int)*(unsigned char *)(p)) #else #define UCHARAT(p) ((int)*(p)&CHARBITS) #endif #define FAIL(m) { regerror(m); return(NULL); } #define ISMULT(c) ((c) == '*' || (c) == '+' || (c) == '?') #define META "^$.[()|?+*\\" /* * Flags to be passed up and down. */ #define HASWIDTH 01 /* Known never to match null string. */ #define SIMPLE 02 /* Simple enough to be STAR/PLUS operand. */ #define SPSTART 04 /* Starts with * or +. */ #define WORST 0 /* Worst case. */ /* * Global work variables for regcomp(). */ static char *regparse; /* Input-scan pointer. */ static int regnpar; /* () count. */ static char regdummy; static char *regcode; /* Code-emit pointer; ®dummy = don't. */ static long regsize; /* Code size. */ /* * Forward declarations for regcomp()'s friends. */ #ifndef STATIC #define STATIC static #endif STATIC char *reg(); STATIC char *regbranch(); STATIC char *regpiece(); STATIC char *regatom(); STATIC char *regnode(); STATIC char *regnext(); STATIC void regc(); STATIC void reginsert(); STATIC void regtail(); STATIC void regoptail(); #ifdef STRCSPN STATIC int strcspn(); #endif /* - regcomp - compile a regular expression into internal code * * We can't allocate space until we know how big the compiled form will be, * but we can't compile it (and thus know how big it is) until we've got a * place to put the code. So we cheat: we compile it twice, once with code * generation turned off and size counting turned on, and once "for real". * This also means that we don't allocate space until we are sure that the * thing really will compile successfully, and we never have to move the * code and thus invalidate pointers into it. (Note that it has to be in * one piece because free() must be able to free it all.) * * Beware that the optimization-preparation code in here knows about some * of the structure of the compiled regexp. */ regexp * regcomp(exp) char *exp; { register regexp *r; register char *scan; register char *longest; register int len; int flags; extern char *malloc(); if (exp == NULL) FAIL("NULL argument"); /* First pass: determine size, legality. */ regparse = exp; regnpar = 1; regsize = 0L; regcode = ®dummy; regc(MAGIC); if (reg(0, &flags) == NULL) return(NULL); /* Small enough for pointer-storage convention? */ if (regsize >= 32767L) /* Probably could be 65535L. */ FAIL("regexp too big"); /* Allocate space. */ r = (regexp *)malloc(sizeof(regexp) + (unsigned)regsize); if (r == NULL) FAIL("out of space"); /* Second pass: emit code. */ regparse = exp; regnpar = 1; regcode = r->program; regc(MAGIC); if (reg(0, &flags) == NULL) return(NULL); /* Dig out information for optimizations. */ r->regstart = '\0'; /* Worst-case defaults. */ r->reganch = 0; r->regmust = NULL; r->regmlen = 0; scan = r->program+1; /* First BRANCH. */ if (OP(regnext(scan)) == END) { /* Only one top-level choice. */ scan = OPERAND(scan); /* Starting-point info. */ if (OP(scan) == EXACTLY) r->regstart = *OPERAND(scan); else if (OP(scan) == BOL) r->reganch++; /* * If there's something expensive in the r.e., find the * longest literal string that must appear and make it the * regmust. Resolve ties in favor of later strings, since * the regstart check works with the beginning of the r.e. * and avoiding duplication strengthens checking. Not a * strong reason, but sufficient in the absence of others. */ if (flags&SPSTART) { longest = NULL; len = 0; for (; scan != NULL; scan = regnext(scan)) if (OP(scan) == EXACTLY && strlen(OPERAND(scan)) >= len) { longest = OPERAND(scan); len = strlen(OPERAND(scan)); } r->regmust = longest; r->regmlen = len; } } return(r); } /* - reg - regular expression, i.e. main body or parenthesized thing * * Caller must absorb opening parenthesis. * * Combining parenthesis handling with the base level of regular expression * is a trifle forced, but the need to tie the tails of the branches to what * follows makes it hard to avoid. */ static char * reg(paren, flagp) int paren; /* Parenthesized? */ int *flagp; { register char *ret; register char *br; register char *ender; register int parno; int flags; *flagp = HASWIDTH; /* Tentatively. */ /* Make an OPEN node, if parenthesized. */ if (paren) { if (regnpar >= NSUBEXP) FAIL("too many ()"); parno = regnpar; regnpar++; ret = regnode(OPEN+parno); } else ret = NULL; /* Pick up the branches, linking them together. */ br = regbranch(&flags); if (br == NULL) return(NULL); if (ret != NULL) regtail(ret, br); /* OPEN -> first. */ else ret = br; if (!(flags&HASWIDTH)) *flagp &= ~HASWIDTH; *flagp |= flags&SPSTART; while (*regparse == '|') { regparse++; br = regbranch(&flags); if (br == NULL) return(NULL); regtail(ret, br); /* BRANCH -> BRANCH. */ if (!(flags&HASWIDTH)) *flagp &= ~HASWIDTH; *flagp |= flags&SPSTART; } /* Make a closing node, and hook it on the end. */ ender = regnode((paren) ? CLOSE+parno : END); regtail(ret, ender); /* Hook the tails of the branches to the closing node. */ for (br = ret; br != NULL; br = regnext(br)) regoptail(br, ender); /* Check for proper termination. */ if (paren && *regparse++ != ')') { FAIL("unmatched ()"); } else if (!paren && *regparse != '\0') { if (*regparse == ')') { FAIL("unmatched ()"); } else FAIL("junk on end"); /* "Can't happen". */ /* NOTREACHED */ } return(ret); } /* - regbranch - one alternative of an | operator * * Implements the concatenation operator. */ static char * regbranch(flagp) int *flagp; { register char *ret; register char *chain; register char *latest; int flags; *flagp = WORST; /* Tentatively. */ ret = regnode(BRANCH); chain = NULL; while (*regparse != '\0' && *regparse != '|' && *regparse != ')') { latest = regpiece(&flags); if (latest == NULL) return(NULL); *flagp |= flags&HASWIDTH; if (chain == NULL) /* First piece. */ *flagp |= flags&SPSTART; else regtail(chain, latest); chain = latest; } if (chain == NULL) /* Loop ran zero times. */ (void) regnode(NOTHING); return(ret); } /* - regpiece - something followed by possible [*+?] * * Note that the branching code sequences used for ? and the general cases * of * and + are somewhat optimized: they use the same NOTHING node as * both the endmarker for their branch list and the body of the last branch. * It might seem that this node could be dispensed with entirely, but the * endmarker role is not redundant. */ static char * regpiece(flagp) int *flagp; { register char *ret; register char op; register char *next; int flags; ret = regatom(&flags); if (ret == NULL) return(NULL); op = *regparse; if (!ISMULT(op)) { *flagp = flags; return(ret); } if (!(flags&HASWIDTH) && op != '?') FAIL("*+ operand could be empty"); *flagp = (op != '+') ? (WORST|SPSTART) : (WORST|HASWIDTH); if (op == '*' && (flags&SIMPLE)) reginsert(STAR, ret); else if (op == '*') { /* Emit x* as (x&|), where & means "self". */ reginsert(BRANCH, ret); /* Either x */ regoptail(ret, regnode(BACK)); /* and loop */ regoptail(ret, ret); /* back */ regtail(ret, regnode(BRANCH)); /* or */ regtail(ret, regnode(NOTHING)); /* null. */ } else if (op == '+' && (flags&SIMPLE)) reginsert(PLUS, ret); else if (op == '+') { /* Emit x+ as x(&|), where & means "self". */ next = regnode(BRANCH); /* Either */ regtail(ret, next); regtail(regnode(BACK), ret); /* loop back */ regtail(next, regnode(BRANCH)); /* or */ regtail(ret, regnode(NOTHING)); /* null. */ } else if (op == '?') { /* Emit x? as (x|) */ reginsert(BRANCH, ret); /* Either x */ regtail(ret, regnode(BRANCH)); /* or */ next = regnode(NOTHING); /* null. */ regtail(ret, next); regoptail(ret, next); } regparse++; if (ISMULT(*regparse)) FAIL("nested *?+"); return(ret); } /* - regatom - the lowest level * * Optimization: gobbles an entire sequence of ordinary characters so that * it can turn them into a single node, which is smaller to store and * faster to run. Backslashed characters are exceptions, each becoming a * separate node; the code is simpler that way and it's not worth fixing. */ static char * regatom(flagp) int *flagp; { register char *ret; int flags; *flagp = WORST; /* Tentatively. */ switch (*regparse++) { case '^': ret = regnode(BOL); break; case '$': ret = regnode(EOL); break; case '.': ret = regnode(ANY); *flagp |= HASWIDTH|SIMPLE; break; case '[': { register int class; register int classend; if (*regparse == '^') { /* Complement of range. */ ret = regnode(ANYBUT); regparse++; } else ret = regnode(ANYOF); if (*regparse == ']' || *regparse == '-') regc(*regparse++); while (*regparse != '\0' && *regparse != ']') { if (*regparse == '-') { regparse++; if (*regparse == ']' || *regparse == '\0') regc('-'); else { class = UCHARAT(regparse-2)+1; classend = UCHARAT(regparse); if (class > classend+1) FAIL("invalid [] range"); for (; class <= classend; class++) regc(class); regparse++; } } else regc(*regparse++); } regc('\0'); if (*regparse != ']') FAIL("unmatched []"); regparse++; *flagp |= HASWIDTH|SIMPLE; } break; case '(': ret = reg(1, &flags); if (ret == NULL) return(NULL); *flagp |= flags&(HASWIDTH|SPSTART); break; case '\0': case '|': case ')': FAIL("internal urp"); /* Supposed to be caught earlier. */ break; case '?': case '+': case '*': FAIL("?+* follows nothing"); break; case '\\': if (*regparse == '\0') FAIL("trailing \\"); ret = regnode(EXACTLY); regc(*regparse++); regc('\0'); *flagp |= HASWIDTH|SIMPLE; break; default: { register int len; register char ender; regparse--; len = strcspn(regparse, META); if (len <= 0) FAIL("internal disaster"); ender = *(regparse+len); if (len > 1 && ISMULT(ender)) len--; /* Back off clear of ?+* operand. */ *flagp |= HASWIDTH; if (len == 1) *flagp |= SIMPLE; ret = regnode(EXACTLY); while (len > 0) { regc(*regparse++); len--; } regc('\0'); } break; } return(ret); } /* - regnode - emit a node */ static char * /* Location. */ regnode(op) char op; { register char *ret; register char *ptr; ret = regcode; if (ret == ®dummy) { regsize += 3; return(ret); } ptr = ret; *ptr++ = op; *ptr++ = '\0'; /* Null "next" pointer. */ *ptr++ = '\0'; regcode = ptr; return(ret); } /* - regc - emit (if appropriate) a byte of code */ static void regc(b) char b; { if (regcode != ®dummy) *regcode++ = b; else regsize++; } /* - reginsert - insert an operator in front of already-emitted operand * * Means relocating the operand. */ static void reginsert(op, opnd) char op; char *opnd; { register char *src; register char *dst; register char *place; if (regcode == ®dummy) { regsize += 3; return; } src = regcode; regcode += 3; dst = regcode; while (src > opnd) *--dst = *--src; place = opnd; /* Op node, where operand used to be. */ *place++ = op; *place++ = '\0'; *place++ = '\0'; } /* - regtail - set the next-pointer at the end of a node chain */ static void regtail(p, val) char *p; char *val; { register char *scan; register char *temp; register int offset; if (p == ®dummy) return; /* Find last node. */ scan = p; for (;;) { temp = regnext(scan); if (temp == NULL) break; scan = temp; } if (OP(scan) == BACK) offset = scan - val; else offset = val - scan; *(scan+1) = (offset>>8)&0377; *(scan+2) = offset&0377; } /* - regoptail - regtail on operand of first argument; nop if operandless */ static void regoptail(p, val) char *p; char *val; { /* "Operandless" and "op != BRANCH" are synonymous in practice. */ if (p == NULL || p == ®dummy || OP(p) != BRANCH) return; regtail(OPERAND(p), val); } /* * regexec and friends */ /* * Global work variables for regexec(). */ static char *reginput; /* String-input pointer. */ static char *regbol; /* Beginning of input, for ^ check. */ static char **regstartp; /* Pointer to startp array. */ static char **regendp; /* Ditto for endp. */ /* * Forwards. */ STATIC int regtry(); STATIC int regmatch(); STATIC int regrepeat(); #ifdef DEBUG int regnarrate = 0; void regdump(); STATIC char *regprop(); #endif /* - regexec - match a regexp against a string */ int regexec(prog, string) register regexp *prog; register char *string; { register char *s; extern char *strchr(); /* Be paranoid... */ if (prog == NULL || string == NULL) { regerror("NULL parameter"); return(0); } /* Check validity of program. */ if (UCHARAT(prog->program) != MAGIC) { regerror("corrupted program"); return(0); } /* If there is a "must appear" string, look for it. */ if (prog->regmust != NULL) { s = string; while ((s = strchr(s, prog->regmust[0])) != NULL) { if (strncmp(s, prog->regmust, prog->regmlen) == 0) break; /* Found it. */ s++; } if (s == NULL) /* Not present. */ return(0); } /* Mark beginning of line for ^ . */ regbol = string; /* Simplest case: anchored match need be tried only once. */ if (prog->reganch) return(regtry(prog, string)); /* Messy cases: unanchored match. */ s = string; if (prog->regstart != '\0') /* We know what char it must start with. */ while ((s = strchr(s, prog->regstart)) != NULL) { if (regtry(prog, s)) return(1); s++; } else /* We don't -- general case. */ do { if (regtry(prog, s)) return(1); } while (*s++ != '\0'); /* Failure. */ return(0); } /* - regtry - try match at specific point */ static int /* 0 failure, 1 success */ regtry(prog, string) regexp *prog; char *string; { register int i; register char **sp; register char **ep; reginput = string; regstartp = prog->startp; regendp = prog->endp; sp = prog->startp; ep = prog->endp; for (i = NSUBEXP; i > 0; i--) { *sp++ = NULL; *ep++ = NULL; } if (regmatch(prog->program + 1)) { prog->startp[0] = string; prog->endp[0] = reginput; return(1); } else return(0); } /* - regmatch - main matching routine * * Conceptually the strategy is simple: check to see whether the current * node matches, call self recursively to see whether the rest matches, * and then act accordingly. In practice we make some effort to avoid * recursion, in particular by going through "ordinary" nodes (that don't * need to know whether the rest of the match failed) by a loop instead of * by recursion. */ static int /* 0 failure, 1 success */ regmatch(prog) char *prog; { register char *scan; /* Current node. */ char *next; /* Next node. */ extern char *strchr(); scan = prog; #ifdef DEBUG if (scan != NULL && regnarrate) fprintf(stderr, "%s(\n", regprop(scan)); #endif while (scan != NULL) { #ifdef DEBUG if (regnarrate) fprintf(stderr, "%s...\n", regprop(scan)); #endif next = regnext(scan); switch (OP(scan)) { case BOL: if (reginput != regbol) return(0); break; case EOL: if (*reginput != '\0') return(0); break; case ANY: if (*reginput == '\0') return(0); reginput++; break; case EXACTLY: { register int len; register char *opnd; opnd = OPERAND(scan); /* Inline the first character, for speed. */ if (*opnd != *reginput) return(0); len = strlen(opnd); if (len > 1 && strncmp(opnd, reginput, len) != 0) return(0); reginput += len; } break; case ANYOF: if (*reginput == '\0' || strchr(OPERAND(scan), *reginput) == NULL) return(0); reginput++; break; case ANYBUT: if (*reginput == '\0' || strchr(OPERAND(scan), *reginput) != NULL) return(0); reginput++; break; case NOTHING: break; case BACK: break; case OPEN+1: case OPEN+2: case OPEN+3: case OPEN+4: case OPEN+5: case OPEN+6: case OPEN+7: case OPEN+8: case OPEN+9: { register int no; register char *save; no = OP(scan) - OPEN; save = reginput; if (regmatch(next)) { /* * Don't set startp if some later * invocation of the same parentheses * already has. */ if (regstartp[no] == NULL) regstartp[no] = save; return(1); } else return(0); } break; case CLOSE+1: case CLOSE+2: case CLOSE+3: case CLOSE+4: case CLOSE+5: case CLOSE+6: case CLOSE+7: case CLOSE+8: case CLOSE+9: { register int no; register char *save; no = OP(scan) - CLOSE; save = reginput; if (regmatch(next)) { /* * Don't set endp if some later * invocation of the same parentheses * already has. */ if (regendp[no] == NULL) regendp[no] = save; return(1); } else return(0); } break; case BRANCH: { register char *save; if (OP(next) != BRANCH) /* No choice. */ next = OPERAND(scan); /* Avoid recursion. */ else { do { save = reginput; if (regmatch(OPERAND(scan))) return(1); reginput = save; scan = regnext(scan); } while (scan != NULL && OP(scan) == BRANCH); return(0); /* NOTREACHED */ } } break; case STAR: case PLUS: { register char nextch; register int no; register char *save; register int min; /* * Lookahead to avoid useless match attempts * when we know what character comes next. */ nextch = '\0'; if (OP(next) == EXACTLY) nextch = *OPERAND(next); min = (OP(scan) == STAR) ? 0 : 1; save = reginput; no = regrepeat(OPERAND(scan)); while (no >= min) { /* If it could work, try it. */ if (nextch == '\0' || *reginput == nextch) if (regmatch(next)) return(1); /* Couldn't or didn't -- back up. */ no--; reginput = save + no; } return(0); } break; case END: return(1); /* Success! */ break; default: regerror("memory corruption"); return(0); break; } scan = next; } /* * We get here only if there's trouble -- normally "case END" is * the terminating point. */ regerror("corrupted pointers"); return(0); } /* - regrepeat - repeatedly match something simple, report how many */ static int regrepeat(p) char *p; { register int count = 0; register char *scan; register char *opnd; extern char *strchr(); scan = reginput; opnd = OPERAND(p); switch (OP(p)) { case ANY: count = strlen(scan); scan += count; break; case EXACTLY: while (*opnd == *scan) { count++; scan++; } break; case ANYOF: while (*scan != '\0' && strchr(opnd, *scan) != NULL) { count++; scan++; } break; case ANYBUT: while (*scan != '\0' && strchr(opnd, *scan) == NULL) { count++; scan++; } break; default: /* Oh dear. Called inappropriately. */ regerror("internal foulup"); count = 0; /* Best compromise. */ break; } reginput = scan; return(count); } /* - regnext - dig the "next" pointer out of a node */ static char * regnext(p) register char *p; { register int offset; if (p == ®dummy) return(NULL); offset = NEXT(p); if (offset == 0) return(NULL); if (OP(p) == BACK) return(p-offset); else return(p+offset); } #ifdef DEBUG STATIC char *regprop(); /* - regdump - dump a regexp onto stdout in vaguely comprehensible form */ void regdump(r) regexp *r; { register char *s; register char op = EXACTLY; /* Arbitrary non-END op. */ register char *next; extern char *strchr(); s = r->program + 1; while (op != END) { /* While that wasn't END last time... */ op = OP(s); printf("%2d%s", s-r->program, regprop(s)); /* Where, what. */ next = regnext(s); if (next == NULL) /* Next ptr. */ printf("(0)"); else printf("(%d)", (s-r->program)+(next-s)); s += 3; if (op == ANYOF || op == ANYBUT || op == EXACTLY) { /* Literal string, where present. */ while (*s != '\0') { putchar(*s); s++; } s++; } putchar('\n'); } /* Header fields of interest. */ if (r->regstart != '\0') printf("start `%c' ", r->regstart); if (r->reganch) printf("anchored "); if (r->regmust != NULL) printf("must have \"%s\"", r->regmust); printf("\n"); } /* - regprop - printable representation of opcode */ static char * regprop(op) char *op; { register char *p; static char buf[50]; (void) strcpy(buf, ":"); switch (OP(op)) { case BOL: p = "BOL"; break; case EOL: p = "EOL"; break; case ANY: p = "ANY"; break; case ANYOF: p = "ANYOF"; break; case ANYBUT: p = "ANYBUT"; break; case BRANCH: p = "BRANCH"; break; case EXACTLY: p = "EXACTLY"; break; case NOTHING: p = "NOTHING"; break; case BACK: p = "BACK"; break; case END: p = "END"; break; case OPEN+1: case OPEN+2: case OPEN+3: case OPEN+4: case OPEN+5: case OPEN+6: case OPEN+7: case OPEN+8: case OPEN+9: sprintf(buf+strlen(buf), "OPEN%d", OP(op)-OPEN); p = NULL; break; case CLOSE+1: case CLOSE+2: case CLOSE+3: case CLOSE+4: case CLOSE+5: case CLOSE+6: case CLOSE+7: case CLOSE+8: case CLOSE+9: sprintf(buf+strlen(buf), "CLOSE%d", OP(op)-CLOSE); p = NULL; break; case STAR: p = "STAR"; break; case PLUS: p = "PLUS"; break; default: regerror("corrupted opcode"); break; } if (p != NULL) (void) strcat(buf, p); return(buf); } #endif /* * The following is provided for those people who do not have strcspn() in * their C libraries. They should get off their butts and do something * about it; at least one public-domain implementation of those (highly * useful) string routines has been published on Usenet. */ #ifdef STRCSPN /* * strcspn - find length of initial segment of s1 consisting entirely * of characters not from s2 */ static int strcspn(s1, s2) char *s1; char *s2; { register char *scan1; register char *scan2; register int count; count = 0; for (scan1 = s1; *scan1 != '\0'; scan1++) { for (scan2 = s2; *scan2 != '\0';) /* ++ moved down. */ if (*scan1 == *scan2++) return(count); count++; } return(count); } #endif char *RegError = 0; static void regerror(s) char *s; { RegError = s; } axe-6.1.2.orig/Widgets/regexp.h100644 243 144 2142 5550557124 15046 0ustar joostusers#ifndef _regexp_h_ #define _regexp_h_ /* * Definitions etc. for regexp(3) routines. * * Caveat: this is V8 regexp(3) [actually, a reimplementation thereof], * not the System V one. */ #define NSUBEXP 10 typedef struct regexp { char *startp[NSUBEXP]; char *endp[NSUBEXP]; char regstart; /* Internal use only. */ char reganch; /* Internal use only. */ char *regmust; /* Internal use only. */ int regmlen; /* Internal use only. */ char program[1]; /* Unwarranted chumminess with compiler. */ } regexp; /* * These definitions added for aXe to avoid a clash with their use * in Tcl (Extension language) where modified versions are used. */ #define regcomp Regcomp #define regexec Regexec extern regexp *regcomp(); extern int regexec(); /* * These declarations commented out for aXe; regsub not used and * different error handling from Tcl's is required. regerror has * been moved inside regexp.c and made static. * * extern void regsub(); * extern void regerror(); */ static void regerror(); /* * New (global) variable for aXe; used to communicate errors. */ extern char *RegError; #endif axe-6.1.2.orig/Widgets/regmagic.h100644 243 144 231 5550557124 15307 0ustar joostusers/* * The first byte of the regexp internal "program" is actually this magic * number; the start node begins in the second byte. */ #define MAGIC 0234 axe-6.1.2.orig/Widgets/scandir.c100644 243 144 5622 5550557117 15202 0ustar joostusers/* * Copyright 1993 The University of Newcastle upon Tyne * * Permission to use, copy, modify and distribute this software and its * documentation for any purpose other than its commercial exploitation * is hereby granted without fee, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of The University of Newcastle upon Tyne not be used in * advertising or publicity pertaining to distribution of the software * without specific, written prior permission. The University of * Newcastle upon Tyne makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * THE UNIVERSITY OF NEWCASTLE UPON TYNE DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF * NEWCASTLE UPON TYNE BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. * * Author: Jim Wight (j.k.wight@newcastle.ac.uk) * Department of Computing Science * University of Newcastle upon Tyne, UK */ #include #ifdef NODIRENT #include #define dirent direct #else #include #endif /* * Hopefully one of these will work */ #ifndef DIRSIZ #define DIRSIZ(dp) ((dp)->d_reclen) /* #define DIRSIZ(dp) \ (((sizeof (struct dirent) - (sizeof((dp)->d_name)+1) + ((dp)->d_namlen+1)) + 3) & ~3) */ /* #define DIRSIZ(dp) \ (((sizeof (struct dirent) - (sizeof((dp)->d_name)+1) + (strlen((dp)->d_name)+1)) + 3) & ~3) */ #endif int scandir(dirname, namelist, select, compar) char *dirname; struct dirent ***namelist; int (*select)(), (*compar)(); { struct dirent *dent, *rent, **list; int nitems, items = 0; DIR *dirp; if ( !(dirp = opendir(dirname)) ) { return(-1); } while (readdir(dirp)) { ++items; } if (!(list = (struct dirent **) malloc(items * sizeof(struct dirent *)))) { return(-1); } rewinddir(dirp); nitems = 0; for (nitems = 0; nitems < items && (dent = readdir(dirp)); ++nitems) { if (select && !(*select)(dent)) { continue; } if (!(rent = (struct dirent *) malloc(DIRSIZ(dent)))) { return(-1); } memcpy((char *) rent, (char *) dent, DIRSIZ(dent)); list[nitems] = rent; } closedir(dirp); if (nitems && compar) { qsort(list, nitems, sizeof(struct dirent *), compar); } *namelist = list; return(nitems); } int alphasort(d1, d2) struct dirent **d1, **d2; { return(strcmp((*d1)->d_name, (*d2)->d_name)); } axe-6.1.2.orig/Widgets/tickMark.xbm100644 243 144 305 5550557126 15641 0ustar joostusers#define tickMark_width 9 #define tickMark_height 8 static unsigned char tickMark_bits[] = { 0x00, 0x01, 0x80, 0x01, 0xc0, 0x00, 0x60, 0x00, 0x31, 0x00, 0x1b, 0x00, 0x0e, 0x00, 0x04, 0x00 }; axe-6.1.2.orig/Widgets/util.c100644 243 144 10276 5550557125 14554 0ustar joostusers/* * Copyright 1993 The University of Newcastle upon Tyne * * Permission to use, copy, modify and distribute this software and its * documentation for any purpose other than its commercial exploitation * is hereby granted without fee, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of The University of Newcastle upon Tyne not be used in * advertising or publicity pertaining to distribution of the software * without specific, written prior permission. The University of * Newcastle upon Tyne makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * THE UNIVERSITY OF NEWCASTLE UPON TYNE DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF * NEWCASTLE UPON TYNE BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. * * Author: Jim Wight (j.k.wight@newcastle.ac.uk) * Department of Computing Science * University of Newcastle upon Tyne, UK */ #include #include #include "AxeIntrinsic.h" #include "util.h" extern char *getenv(); unsigned char xerror; int (*DefaultErrorHandler)(); static int TrapError(dpy, error) Display *dpy; XErrorEvent *error; { xerror = error->error_code; if (xerror != BadWindow) { DefaultErrorHandler(dpy, error); } return 0; } void TrapErrors(dpy) Display *dpy; { /* * XSync is called to ensure that any outstanding * errors are dealt with by the default handler. */ XSync(dpy, False); DefaultErrorHandler = XSetErrorHandler(TrapError); xerror = Success; } void DontTrapErrors(dpy) Display *dpy; { /* * XSync is called to ensure that any error that occurs * while we are trapping errors is dealt with before the * default error handler is restored. */ XSync(dpy, False); (void) XSetErrorHandler(NULL); } void PopupCentred(popup, grabState) Widget popup; Boolean grabState; { Window root, child; unsigned int mask; XEvent event; Dimension width, height, b_width; Position x, y, max_x, max_y; XtRealizeWidget(popup); XQueryPointer(XtDisplay(popup), XtWindow(popup), &root, &child, &event.xbutton.x_root, &event.xbutton.y_root, &event.xbutton.x, &event.xbutton.y, &mask); x = event.xbutton.x_root; y = event.xbutton.y_root; XtVaGetValues(popup, XtNwidth, &width, XtNheight, &height, XtNborderWidth, &b_width, NULL); width += 2 * b_width; height += 2 * b_width; x -= ( (Position) width/2 ); if (x < 0) x = 0; if (x > (max_x = (Position) (XtScreen(popup)->width - width))) x = max_x; y -= ( (Position) height/2 ); if (y < 0) y = 0; if (y > (max_y = (Position) (XtScreen(popup)->height - height))) y = max_y; XtVaSetValues(popup, XtNx, x, XtNy, y, NULL); XtPopup(popup, grabState); } int GetHostName(name, namelen) char *name; int namelen; { #if defined(SYSV) || defined(SVR4) #include struct utsname info; int code; if ( (code = uname(&info)) == 0) { strcpy(name, info.nodename); } return code; #else return gethostname(name, namelen); #endif } Atom HostUserServerAtom(display) Display *display; { char host[MAXHOSTNAMELEN], *user, propName[MAXPATHLEN]; strcpy(propName, AXE_SERVER); if (GetHostName(host, MAXHOSTNAMELEN - strlen(AXE_SERVER)) == 0) { strcat(propName, "_"); strcat(propName, host); } if ( (user = getenv("USER")) ) { strcat(propName, "_"); strcat(propName, user); } return XInternAtom(display, propName, False); } axe-6.1.2.orig/Widgets/util.h100644 243 144 3355 5550557124 14540 0ustar joostusers/* * Copyright 1993 The University of Newcastle upon Tyne * * Permission to use, copy, modify and distribute this software and its * documentation for any purpose other than its commercial exploitation * is hereby granted without fee, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of The University of Newcastle upon Tyne not be used in * advertising or publicity pertaining to distribution of the software * without specific, written prior permission. The University of * Newcastle upon Tyne makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * THE UNIVERSITY OF NEWCASTLE UPON TYNE DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF * NEWCASTLE UPON TYNE BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. * * Author: Jim Wight (j.k.wight@newcastle.ac.uk) * Department of Computing Science * University of Newcastle upon Tyne, UK */ #ifndef util_h #define util_h #include #ifndef MAXHOSTNAMELEN #define MAXHOSTNAMELEN 64 #endif extern unsigned char xerror; extern int (*DefaultErrorHandler)(); extern void TrapErrors(), DontTrapErrors(), PopupCentred(); extern int GetHostName(); extern Atom HostUserServerAtom(); #endif axe-6.1.2.orig/Widgets/vtCentre.xbm100644 243 144 320 5550557126 15663 0ustar joostusers#define vtCentre_width 11 #define vtCentre_height 9 static unsigned char vtCentre_bits[] = { 0xfc, 0x01, 0xf8, 0x00, 0x70, 0x00, 0x20, 0x00, 0xff, 0x07, 0x20, 0x00, 0x70, 0x00, 0xf8, 0x00, 0xfc, 0x01}; axe-6.1.2.orig/Widgets/warn.xbm100644 243 144 10064 5550557127 15107 0ustar joostusers#define warn_width 99 #define warn_height 50 static unsigned char warn_bits[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x55, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaa, 0xa8, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x50, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x2a, 0xa0, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x15, 0x40, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x0a, 0x82, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x05, 0x05, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x82, 0x0a, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x01, 0x05, 0x54, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaa, 0x80, 0x0a, 0xa8, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x00, 0x05, 0x50, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x2a, 0x80, 0x0a, 0xa0, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x15, 0x00, 0x05, 0x40, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x0a, 0x80, 0x0a, 0x80, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x05, 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x02, 0x80, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x01, 0x00, 0x05, 0x00, 0x54, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaa, 0x00, 0x80, 0x0a, 0x00, 0xa8, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x05, 0x00, 0x50, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x2a, 0x00, 0x80, 0x0a, 0x00, 0xa0, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x15, 0x00, 0x00, 0x05, 0x00, 0x40, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x0a, 0x00, 0x00, 0x02, 0x00, 0x80, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x01, 0x00, 0x00, 0x05, 0x00, 0x00, 0x54, 0x01, 0x00, 0x00, 0x00, 0x00, 0xaa, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0xa8, 0x02, 0x00, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x50, 0x05, 0x00, 0x00, 0x00, 0x80, 0x2a, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0xa0, 0x0a, 0x00, 0x00, 0x00, 0x40, 0x15, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x40, 0x15, 0x00, 0x00, 0x00, 0xa0, 0x0a, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x80, 0x2a, 0x00, 0x00, 0x00, 0x50, 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0xa8, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaa, 0x00, 0x00, 0x00, 0x54, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x54, 0x01, 0x00, 0x00, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0xa8, 0x02, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x50, 0x05, 0x00, 0x80, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x0a, 0x00, 0x40, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x15, 0x00, 0xa0, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x2a, 0x00, 0x50, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x00, 0xa8, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x54, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x01, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x02, 0x54, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x01}; axe-6.1.2.orig/Axe.ad.sed100644 243 144 30635 5550557105 13621 0ustar joostusersAxe.version: VERSION *axeLibDir: AXELIBDIR *allowShellResize: True EXTENSION*AxeEditor.translations:#override\n\ :interp-focus() *box.Command.highlightThickness:1 *showGrip: False *fileName.justify: left *buttons*AxeCommand.borderWidth:0 /**/ Replicate AxeEditor's default font list here to snuff out HP_VUE's /**/ server setting of *FontList for some other purpose *FontList: Small:6x13 Medium:8x13 Large:9x15 Huge:10x20 *buttons.columnSpacing: 2 *buttons.AxeMenuButton.borderWidth:0 *buttons*highlightThickness: 20 *moveMenu.label: Move *moveMenu.help: Activate pulldown menu of move operations *moveMenu.menuName: mMove *searchMenu.label: Search *searchMenu.help: Activate pulldown menu of search operations *searchMenu.menuName: mSearch *insertMenu.label: Insert *insertMenu.help: Activate pulldown menu of insert operations *insertMenu.menuName: mInsert *deleteMenu.label: Delete *deleteMenu.help: Activate pulldown menu of delete operations *deleteMenu.menuName: mDelete *helpMenu.label: Help *helpMenu.help: Activate pulldown menu of help operations *helpMenu.menuName: mHelp *miscMenu.label: Misc *miscMenu.help: Activate pulldown menu of miscellaneous operations *miscMenu.menuName: mMisc *fontMenu.label: Font *fontMenu.help: Activate pulldown menu of font names *fontMenu.menuName: mFont *windowMenu.label: Window *windowMenu.help: Activate pulldown menu of window operations *windowMenu.menuName: mWindow *bufferMenu.label: Buffer *bufferMenu.help: Activate pulldown menu of buffer operations *bufferMenu.menuName: mBuffer *showMenu.label: Show *showMenu.help: Activate pulldown menu showing names of files being edited *showMenu.menuName: mShow *mShow.AxeSmeBSB.justify: left *mShow.AxeSmeBSB.leftMargin:16 *mShow.AxeSmeBSB.rightMargin:16 *mShow*AxeSmeBSB.help: Raise window/buffer corresponding to highlighted entry *fileMenu.label: File *fileMenu.help: Activate pulldown menu of file operations *fileMenu.menuName: mFile *quitMenu.label: Quit *quitMenu.help: Activate pulldown menu of quit operations *quitMenu.menuName: mQuit *axeLogo.internalWidth: 0 *buttons.axeLogo.translations:#override\n: unhighlight() update-info() *axeLogo.menuName: mLogo *mLogo.translations: #replacee \n : MenuPopdown() *AxeSimpleMenu.translations:#override \n\ : update-info(Reset) \n\ : highlight() update-info() *AxeSmeBSB.vertSpace: 20 *AxeSmeBSB.justify: center *mbeg.label: Beginning *mbeg.help: Move insertion point to beginning of line [ Ctrl-a ] *mend.label: End *mend.help: Move insertion point to end of line [ Ctrl-e ] *mup.label: Up *mup.help: Move insertion point up one page [ Meta-v ] *mdown.label: Down *mdown.help: Move insertion point down one page [ Ctrl-v ] *mtop.label: Top *mtop.help: Move insertion point to top of file [ Meta-< ] *mbot.label: Bottom *mbot.help: Move insertion point to bottom of file [ Meta-> ] *mSearch.AxeSmeBSB.leftMargin:16 *mSearch.AxeSmeBSB.rightMargin:16 *sbtext.label: Text *sbtext.help: Pop up dialogue box for backward text search [ Ctrl-r ] *sftext.label: Text *sftext.help: Pop up dialogue box for forward text search [ Ctrl-s ] *sline.label: Line *sline.help: Pop up numeric pad for entering the number of a line to go to *scaret.label: Caret *scaret.help: Scroll text so that insertion point is in view *sbsel.label: Selection *sbsel.help: Search backward for the current selection *sfsel.label: Selection *sfsel.help: Search forward for the current selection *ifile.label: File *ifile.help: Pop up file selector *isel.label: Selection *isel.help: Insert current selection *ipaste.label: Paste *ipaste.help: Insert text deleted using Cut [ Ctrl-y ] *ictrl.label: Control codes *ictrl.help: Pop up table of control codes for making selection *dword.label: Word *dword.help: Delete current word, or next if between words [ Meta-f Meta-b Meta-d ] *dline.label: Line *dline.help: Delete current line [ Ctrl-a Ctrl-k ] *dsel.label: Selection *dsel.help: Delete selected (highlighted) text *dcut.label: Cut *dcut.help: Delete selected text for later pasting [ Ctrl-w ] *hgnrl.label: General *hgnrl.help: Pop up general help window *hbind.label: Bindings *hbind.help: Pop up window showing default key/button bindings *hcust.label: Customise *hcust.help: Pop up window explaining how to customise aXe *hpop.label: Popups *hpop.help: Pop up window explaining aXe's popups *hextn.label: Extension *hextn.help: Pop up window explaining aXe's extension language *hchng.label: Changes *hchng.help: Pop up window describing the changes since the last release *mMisc.AxeSmeBSB.leftMargin:16 *mMisc.AxeSmeBSB.rightMargin:16 *mundo.label: Undo *mundo.help: Undo the last operation that changed the buffer *mwhere.label: Where? *mwhere.help: Display the current line number and position within line *mform.label: Format *mform.help: Format the current paragraph [ Meta-q ] *mcentre.label: Centre *mcentre.help: Redraw text window with current line centred vertically [ Ctrl-l ] *mhcentr.label: Centre *mhcentr.help: Centre current line horizontally *mpref.label: Preferences *mpref.help: Pop up dialogue for temporarily setting user preferences *mFont.AxeSmeBSB.justify: left *mFont.AxeSmeBSB.leftMargin:16 *fndflt.label: Default *wnew.label: New *wnew.help: Create a new empty editing window *wfull.label: New & Load *wfull.help: Create a new editing window and load a file into its buffer *wclose.label: Close *wclose.help: Destroy this window, with check for unsaved changes *wclall.label: Close All *wclall.help: Destroy all windows, with check for unsaved changes *wicon.label: Iconify All *wicon.help: Iconify all windows *wdeicon.label: Deiconify All *wdeicon.help: Deiconify all windows *bempty.label: New *bempty.help: Create a new empty buffer in this window *bfull.label: New & Load *bfull.help: Create a new buffer in this window and load a file into it *bclear.label: Clear *bclear.help: Clear text in this buffer making it ready for reuse *bclose.label: Close *bclose.help: Destroy this buffer, with check for unsaved changes *fsvex.label: Save and Close *fsvex.help: Save changes in all buffers, closing where the save is successful *fsvall.label: Save All *fsvall.help: Save changes in all buffers and continue editing *fsave.label: Save *fsave.help: Save changes in this buffer and continue editing *fsvas.label: Save As *fsvas.help: Save this buffer under new name then continue editing that file *fload.label: Load *fload.help: Edit a different file in this buffer *frvrt.label: Reload *frvrt.help: Reload file associated with this buffer, with check for unsaved changes *qquit.label: Close All *qquit.help: Destroy all windows, with check for unsaved changes *qsvex.label: Save and Close All *qsvex.help: Save changes in all buffers and close all windows if successful *qsvclw.label: Save and Close Window *qsvclw.help: Save changes in all buffers in this window and close it if successful *qsvclb.label: Save and Close Buffer *qsvclb.help: Save changes in this buffer and close it if successful *XpTable*mbeg.label: Begin *XpTable*mend.label: End *XpTable*mup.label: Up *XpTable*mdown.label: Down *XpTable*mtop.label: Top *XpTable*mbot.label: Botm *XpTable*sbtext.label: <-Text *XpTable*sftext.label: Text-> *XpTable*sline.label: Line *XpTable*scaret.label: Caret *XpTable*sbsel.label: <-Sel'n *XpTable*sfsel.label: Sel'n-> *XpTable*ifile.label: File *XpTable*isel.label: Sel'n *XpTable*ipaste.label: Paste *XpTable*ictrl.label: Ctrls *XpTable*dword.label: Word *XpTable*dline.label: Line *XpTable*dsel.label: Sel'n *XpTable*dcut.label: Cut *XpTable*hgnrl.label: Gen'l *XpTable*hbind.label: Bind *XpTable*hcust.label: Custom *XpTable*hpop.label: Popups *XpTable.hextn.label: Extend *XpTable*hchng.label: Chngs *XpTable*mundo.label: Undo *XpTable*mwhere.label: Where? *XpTable*mform.label: Format *XpTable*mcentre.label: Cent(V) *XpTable*mhcentr.label: Cent(H) *XpTable*mpref.label: Prefs *XpTable*wnew.label: New *XpTable*wfull.label: New+ *XpTable*wclose.label: Close *XpTable*wclall.label: Quit *XpTable*wicon.label: Iconify *XpTable*wdeicon.label: Deic'fy *XpTable*bempty.label: New *XpTable*bfull.label: New+ *XpTable*bclear.label: Clear *XpTable*bclose.label: Close *XpTable*fsvex.label: Exit *XpTable*fsvall.label: Sv All *XpTable*fsave.label: Save *XpTable*fsvas.label: Sv As *XpTable*fload.label: Load *XpTable*frvrt.label: Reload *XpTable*qquit.label: Quit *XpTable*qsvex.label: Close *XpTable*qsvclw.label: Clos(W) *XpTable*qsvclb.label: Clos(B) *ed.baseTranslations:#override\n\ !:): match-parens() \n\ !:]: match-parens() \n\ !:}: match-parens() \n\ : extend-end(PRIMARY, CUT_BUFFER0) where() \n\ : where() \n\ : extend-end(PRIMARY, CUT_BUFFER0) where() *ed.scrollVertical: always *ed.wrap: line *miniBuffer*editType: Edit *miniBuffer*pieceSize: 32 *miniBuffer.displayCaret:False *miniMenu.internalWidth:2 *miniMenu.bitmap: menu10 *miniMenu.help: Activate menu of minibuffer operations *miniMenu.menuName: mMini *miniMenu.translations: #override \n\ : highlight() update-info() \n\ : reset() *miniMenu: print:lpr spell nroff mail | \ exec:mini-commit abort:mini-abort | \ print:lpr\n spell:spell\n nroff:nroff\n *mMini.print.help: Ready minibuffer with command to print buffer/selection *mMini.spell.help: Ready minibuffer with command to spell check buffer/selection *mMini.nroff.help: Ready minibuffer with command to apply nroff to buffer/selection *mMini.mail.help: Ready minibuffer with command to mail buffer/selection *mMini.exec.help: Re-execute the command in the minibuffer *mMini.abort.help: Remove minibuffer accelerators *mMini.print.help: Print the buffer/selection *mMini.spell.help: Check spelling of buffer/selection *mMini.nroff.help: Run buffer/selection through nroff *FileNominator*path.leftBitmap:menu12 *FileNominator*Filter.label:filter *FileNominator*Filter.leftBitmap:menu12 *FileNominator*PathList:$HOME *Preference.marginWidth: 5 *Preference.marginHeight: 5 *Preference.rowSpacing: 5 *Preference.columnSpacing: 5 *Preference*Label.borderWidth: 0 *Preference.Box.orientation: horizontal *Preference.Box.borderWidth: 0 *Preference.Box.vSpace: 2 *Preference*Toggle.translations: #override \n\ ,: set() notify() *Preference*autoFill.label: Auto Fill *Preference*autoFill.translations:#override \n\ ,: toggle() notify() *Preference.lscroll.label: Scrollbar: *Preference.lwrap.label: Wrap Mode: *Preference.ledmode.label: Edit Mode: *Preference.ltabs.label: Tab Every: *Preference.lfnom.label: Nominator: *Preference.lapply.label: \ Apply To: *Confirmer*Label.borderWidth: 0 *Confirmer*Box.orientation: horizontal *Confirmer*Box.borderWidth: 0 *Confirmer*Box.vSpace: 2 *Confirmer*confirm.accelerators: Ctrla: set() notify() reset() *Confirmer*alternative.accelerators:Ctrlb: set() notify() reset() *Confirmer*cancel.label: cancel (^C) *Confirmer*cancel.accelerators: Ctrlc: set() notify() reset() *NumericPad*Toggle.translations:#override\n,: set() notify() *NumericPad*text.width: 1 *ControlCodeSelector*list.columnSpacing:15 *ControlCodeSelector*list.defaultColumns:3 *ControlCodeSelector.base:8 *fileServer.title: aXe *fileServer.iconName: aXe *fileServer*select.label: Edit *fileServer*path.label: Path *fileServer*cancel.label: Quit *server.title: aXe *server.iconName: aXe *server.Height: 125 *table.layout: waiter 0 0 2; show 0 1 2 hH; poleaxe 0 2 hH; help 1 2 hH; *table.rowSpacing: 5 *table.columnSpacing: 5 *table.marginWidth: 5 *table.marginHeight: 5 *waiter.label: Edit *waiter.width: 80 *show.label: Show *show.leftBitmap: menu12 *show.menuName: mShow *poleaxe.label: Quit *help.label: Help axe-6.1.2.orig/Axe.rules100644 243 144 6053 5550557105 13572 0ustar joostusers/* Borrowed from R5 for R4 case */ /* if [ -d ] or [ ! -d ] causes make to fail, define this as - */ #ifndef DirFailPrefix #define DirFailPrefix #endif #ifndef MakeDir #define MakeDir(dir) DirFailPrefix@if [ -d dir ]; then set +x; \ @@\ else (set -x; $(MKDIRHIER) dir); fi #endif /* * InstallNonExecFile - generate rules to install a data file */ #ifndef InstallNonExecFile #define InstallNonExecFile(file,dest) @@\ install:: file @@\ MakeDir($(DESTDIR)dest) @@\ $(INSTALL) -c $(INSTDATFLAGS) file $(DESTDIR)dest #endif /* InstallNonExecFile */ /* End of R5 borrowing */ #define MakeAxeDefaults(helpdir,interp) @@\ all:: Axe.ad @@\ @@\ Axe.ad: Axe.ad.sed version.h Axe.tmpl @@\ sed -e "s/VERSION/`sed -e 's/.*VERSION \(.*\)/\1/;q' Axe.ad @@\ @@\ clean:: @@\ $(RM) Axe.ad #define MakeXaw3d(deps) @@\ Xaw3d:: @@\ $(RM) deps @@\ MakeDir(X11/Xaw3d/X11) @@\ @(set -x; cd X11/Xaw3d/X11; for i in Xaw Xaw3d; do \ @@\ $(RM) $$i; \ @@\ ln -s Xaw3dIncDir $$i; \ @@\ done) #define InstallAxeDefaults(class,dest) @@\ install:: class.ad @@\ MakeDir($(DESTDIR)dest) @@\ $(INSTALL) -c $(INSTAPPFLAGS) class.ad $(DESTDIR)dest/class #define ComplaxeProgramTarget(program,bindest,mandest) @@\ PROGRAM = program @@\ @@\ all:: @@\ @echo Making in . @@\ @@\ AllTarget(program) @@\ @@\ program: $(OBJS) $(DEPLIBS) @@\ RemoveTargetProgram($@) @@\ $(CC) -o $@ $(OBJS) $(LDOPTIONS) $(LOCAL_LIBRARIES) $(LDLIBS) $(EXTRA_LOAD_FLAGS) @@\ @@\ InstallProgram(program,bindest) @@\ InstallManPage(program,mandest) @@\ DependTarget() @@\ LintTarget() @@\ @@\ clean:: @@\ $(RM) $(PROGRAM) @@\ @@\ extension:: @@\ $(RM) $(EXTN_DEPS) @@\ $(MAKE) #define InstallCoaxe(bindest) @@\ InstallProgram(coaxe,bindest) @@\ install:: @@\ if [ -f bindest/faxe ]; then set +x; \ @@\ else (cd bindest; set -x; $(LN) coaxe faxe); fi @@\ if [ -f bindest/poleaxe ]; then set +x; \ @@\ else (cd bindest; set -x; $(LN) coaxe poleaxe); fi axe-6.1.2.orig/Axe.tmpl100644 243 144 10102 5550557105 13422 0ustar joostusers/* Where do you want the executables to be installed */ Bindir = ${BINDIR} /* Where do you want the app defaults file to be installed */ Appdir = ${XAPPLOADDIR} /* Where do you want the man page to be installed */ Mandir = ${MANDIR} /* Where do you want the ancilliary files to be installed */ AxeLibdir = ${LIBDIR} /* As of aXe 6.0 the help is presented using a separate application called */ /* axinfo. Repeat the above exercise for it. */ InfoBindir = ${Bindir} InfoAppdir = ${Appdir} InfoMandir = ${Mandir} InfoLibdir = ${AxeLibdir} /* Do you have Wcl 2.2 or later (just for the Table widget) installed? */ /* If not then the 2.5 Table widget that is provided will be compiled */ /* If you do, and want to use it, then uncomment and modify the next two */ /* sections to say where... */ /* ...the include files are, i.e. XpIncDir/X11/Xp exists */ /* #define XpIncDir /usr/local/Wcl/include */ /* ...and where the Xp and Wc libraries are */ /* i.e. XpLibDir/libXp.a (or .so.?.?) exists */ /* #define XpLibDir /usr/local/Wcl/lib */ /* If you want to incorporate the optional extension language feature first */ /* read the file INSTALL for more information and uncomment the next line */ /* #define Extension */ /* ...and state where the Tcl include files are */ /* #define TclIncDir /usr/local/tcl/include */ /* ...and where the library is, i.e. TclLibDir/libtcl.a (or .so.?.?) exists */ /* #define TclLibDir /usr/local/tcl/lib */ /* Uncomment the next but one line if you want to build an Xaw3d version */ /* Please read the file INSTALL for essential information in this area */ /* #define ThreeD */ /* ... and state the pathname of the directory containing the Xaw3d headers */ /* #define Xaw3dIncDir /usr/local/Xaw3d/include/X11/Xaw3d */ /* ... and where the Xaw3d library is to be found. This can be omitted */ /* if the library is in the standard place in the installed X tree */ /* #define Xaw3dLibDir /usr/local/Xaw3d/lib */ /* Uncomment the next line if you have rather than */ /* NB It is probably also necessary to specify this under SYSV to force the*/ /* inclusion of . The symptons when it might be required are */ /* characters missing from the filenames in the file selector popup. */ /* #define NODIRENT */ /* Uncomment the final line if you have X11R5 patched to >= patchlevel 20 */ /* Otherwise a workaround for a bug that was fixed in that patch will be */ /* enabled. The workaround assists regular expression query replace. */ /* Query replace via the standard search popup will still be buggy though */ /* HAVEX11R5PL20 = -DHAVEX11R5PL20 */ /* If you know, or find, that your system doesn't have scandir/alphasort */ /* you might like to try the supplied versions to see if they work. In */ /* which case uncomment the next line */ /* #define NOSCANDIR */ /* If you find that MAXPATHLEN is not defined then uncomment the next line */ /* MAXPATHLEN = -DMAXPATHLEN=1024 */ /*------ No need (hopefully) to change anything below this line ------*/ #if ProjectX < 5 R4ONLY_SRCS = Porthole.c R4ONLY_OBJS = Porthole.o #else R5ONLY_SRCS = Viewlist.c R5ONLY_OBJS = Viewlist.o #endif #ifdef XpLibDir TABLE_INCLUDES = -I/**/XpIncDir TABLE_LDFLAGS = -L/**/XpLibDir TABLE_LIBS = -lXp -lWc #else TABLE_SRCS = Table.c TableVec.c TableLoc.c TABLE_OBJS = Table.o TableVec.o TableLoc.o #endif #ifdef Extension EXTN_SRCS = Language.c EXTN_OBJS = Language.o EXTN_INCLUDES = -I/**/TclIncDir EXTN_LDFLAGS = -L/**/TclLibDir EXTN_LIBS = -ltcl -lm EXTENSION = -DEXTENSION #endif EXTN_DEPS = AxeEditor.o axe.o #ifdef ThreeD XAW3D_INCLUDES = -I./X11/Xaw3d #if defined(SunArchitecture) && (OSMajorVersion >= 5) XAW3D_LDFLAGS = -t -L/**/Xaw3dLibDir #else XAW3D_LDFLAGS = -L/**/Xaw3dLibDir #endif XAW3D_LIBS = -lXaw3d XAW3D = -DXAW3D #endif XAW3D_DEPS = AxeCommand.o AxeMenuBtn.o AxeSmeBSB.o #ifdef NOSCANDIR SCANDIR_SRCS = scandir.c SCANDIR_OBJS = scandir.o #endif DEFINES = ${EXTENSION} ${XAW3D} ${HAVEX11R5PL20} ${MAXPATHLEN} axe-6.1.2.orig/COPYRIGHT100644 243 144 2673 5550557105 13300 0ustar joostusers/* * Copyright 1994 The University of Newcastle upon Tyne * * Permission to use, copy, modify and distribute this software and its * documentation for any purpose other than its commercial exploitation * is hereby granted without fee, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of The University of Newcastle upon Tyne not be used in * advertising or publicity pertaining to distribution of the software * without specific, written prior permission. The University of * Newcastle upon Tyne makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * THE UNIVERSITY OF NEWCASTLE UPON TYNE DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF * NEWCASTLE UPON TYNE BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. * * Author: Jim Wight (j.k.wight@newcastle.ac.uk) * Department of Computing Science * University of Newcastle upon Tyne, UK */ axe-6.1.2.orig/HISTORY100644 243 144 32632 5600342424 13077 0ustar joostusers6.1.2 AxeEditor Dealt with assumption in NewWindow that shell widget can only have a single child. 6.1.1 Basic changes for R6. Internationalisation doesn't work though. AxeWindow Removed assumption that shell widget can only have a single child - invalidated by the R6 Xaw VendorShell extension. Now keep record of our child as private data. Preference Removed assumption that shell widget can only have a single child - invalidated by the R6 Xaw VendorShell extension. Ready is now passed Preference widget id as client data. 6.1 AxeEditor Now remove trailing whitespace from minibuffer input in MiniInput. Language Removed extra argument from Tcl_DStringAppendElement call. axinfo Fixed wrong type in (unused) argument num_params of ShowInfo and ClearInfo HyperP.h, Hyper.h Commented trailing text on #endif statements. 6.0 AxeEditor Fixed bug in parsing of quotes in ParseFontList. Fixed it so that ????Menu resources look like AxeEditor resources. Use Confirmer instead of information bar for some errors. Rehighlight modified text after a "|" command. Added SVR4 exception in addition to SYSV. Modified for axinfo help system. #ifdef'd sys_errlist because of BSD 4.4. Use error trapping code from util module. Added support for Apollo workstation filesystem (contributed by David Lightman). Duplicated default font list value in Axe.ad to get round HP VUE's interfering use of *FontList in server resources. AxeText Use error trapping code from util. Use popup centering code form util. AxeiiText Introduction of deleteOnInsert resource. Implementation via envelopment of insert-char action routine is R5 specific. Stopped delete-selection-or-previous-character from deleting the wrong bracket if key hit during bracket matching blinking. Envelope search action routine to pop down search popup - ensures that regexp or undo tinkering that gets removed via popdownCallback callbacks really gets done. Implementation is R5 specific. AxeiiUndo Fixed bug in undo of delete-selection-or-previous-character by removing its undo handling - works fine if left to delete-selection and delete-previous-character. Confirmer Use popup centering code from util. FileNom Added SVR4 exception in addititon to SYSV. Added support for Apollo workstation filesystem (contributed by David Lightman). Language Renamed getSelection, getPos and setPos commands as get-selection, get-position and set-selection respectively. Modified get-selection to return the selection. Added set-selection,set-[source/sink]-value and eval-buffer commands. Added Tcl 7 compatability. ScrollText Made minor improvements to scrolling behaviour. axe Modified for axinfo help system. Use error trapping code from util. Use atom generation code from util. Added setting of WM_COMMAND property on server window. coaxe Treat case where no file argument(s) separately. Fixed use of strcat instead of strcpy when adding first component of absolute pathname given relative filename. Added SVR4 exception in addition to SYSV. #ifdef'd sys_errlist because of BSD 4.4. Use error trapping code from util. Use atom generation code from util. Use GetHostName from util. util New file to help minimise duplication of code. Error trapping. Centering popups. Generating server atoms. Generic GetHostName using gethostname or uname. axe.tcl Renamed loopSel as with-selection. Renamed join and format as join-lines and format-all to avoid hiding the identically named Tcl commands. Added upper and lower commands Modified commands operating on the selection to select the modified text using the new set-selection command. *.xbm Changed declaration of bits to unsigned char with consequent casts in XCreateBitmapFromData in AxeEditor, AxeiiSink, Confirmer and FileNom - stops Solaris warnings. 5.1 AxeEditor Fixed bug arising from help in minibuffer without argument. Allowed repeat-macro to take a repeat count argument. Added closing of display connection number in forked processes. Added mini-stuff action. Added + to miniMenu specification language. Introduction of configurable menus, i.e. ????Menu resources. AxeiiText Added processing to handle search and replace of ^ and $ regexp's. regexp.c Added extern char *strchr() declaration to regrepeat to get rid of warning from gcc. Axe.rules Modified InstallCoaxe rule to avoid full pathnames in faxe and poleaxe links. Replaced use of make by $(MAKE). Replaced leading blanks by TABs. 5.0 AxeiiUndo New. Implements undo. Logically extension of AxeiiText. AxeEditor Fixed (again) replacement of selection via | not working correctly. Added "Undo" Misc menu entry in place of "Size?". Modified for undo. Perform a chdir to associated directory of current buffer in child process when exec'ing subprocess from minibuffer. AxeTextDeck Modified for undo Extended parsing of quoted filename token to split on \n and \t as well as on space. Moved overriding of Text widget translations out to app defaults file. Was undoing users settings. AxeText Modified for undo. AxeiiText Modified for undo. Modified centre-line behaviour to position caret at end of line to fit in with undo implementation. axe Added Show menu button to server window. Added -buffer keyword. coaxe Added -buffer keyword. scandir Redefined DIRSIZ as a result of experience under Solaris. Various Elimination of warnings thrown up by lint. 4.1.1 AxeEditor Fixed insertion point being miscalculated when replacing text via the minibuffer "|" command. Modified to use new FileNominatorStruct information. AxeText Modified to use new FileNominatorStruct information. Check if file exists on save-as. axe Modified to use new FileNominatorStruct information. FileNom Addition of userData resource. Altered struct returned by selectCallback to provide fuller information about access to nominated file. 4.1 AxeEditor Implemented actions as minibuffer commands. Added menuList resource to allow user to specify choice and order of menu bar buttons. various consequential changes. AxeiiText Fixed re-search not checking number of parameters. Undid hiding of caret on parentheses matching - causing too much flashing. FileNom Fixed ESC not toggling "." files if Filter menu not used. scandir Fixed syntax error. 4.0 axe, AxeEditor, Language Introduction of extension language. AxeWindow Added support for WM_DELETE_WINDOW message. Improved method of assigning defaults to Shell resources. AxeEditor Now read help directory name from a resource instead of compiling it in. Modified ParseFontList to allow quoting. Converted minibuffer to do regular expression searching. r, w and e minibuffer commands must be followed by space in order to be distinguishible from Tcl commands. Minibuffer I/O now dealt with through pipes and additional inputs instead of temporary files. Added check for getwd failing. AxeMenuBtn Reinstated brief help at R4 - needed SHAPE to be defined. AxeTextDeck Extended to accommodate AxeTextreloadFailure error code. AxeText Cater for permissions having changed, file no longer existing or no associated file on a reload. AxeTextreloadFailure error code introduced. Improved checking of file access. Removed code that assumed showDotFiles in preferences popup. AxeiiText Regular expression searching. Hide caret when matching parentheses. AxeiiSink New. To permit Text widget caret to be overriden. Confirmer Improved method of assigning defaults to Shell resources. CtrCodeSel Improved method of assigning defaults to Table resources. FileNom Added new resource filterDirectoryNames and corresponding action routine. Added filter menu. Make use of XawViewportSetLocation at R5 to reposition to top on list changing. Added check for getwd failing. Removed selectMenu resource (already superceded by pathList) NumericPad Improved method of assigning defaults to Table resources. Preference Removed FileNominator '.' file stuff - now in FileNom. Added setting of keyboard focus to 'Tab Every' field. Improved method of assigning defaults to Table resources. coaxe Fixed so that not just first command line argument gets passed to axe when server not running; however, buffer information is not being preserved. Added check for getwd failing. scandir New. Possibility for systems that don't provide one. 3.1 AxeEditor Stopped adding multiple work procs to repopulate Show menu. Added 'Save and Close Window' and 'Save and Close Buffer' entries to Quit menu. Fixed disappearance of caret in minibuffer on committal of some directly entered (i.e. not via accelerators) commands. Moved inititialisation of private variables to top of Initialize in order to eliminate unitialised memory access in SaveValues. Plugged memory leaks from use of AxeTextFileToNominatorStruct. Now call CloseWindow when closing last buffer in a window - purify was reporting tons of free memory read violations and other nasty errors. Delete fonts loaded by XLoadQueryFont properly using XFreeFont. AxeTextDeck Fixed AxeSave iteration to save only modified files. AxeText Made permissions of new file same as backup. Provided AxeTextFreeNominatorStruct to free memory allocated in AxeTextFileToNominatorStruct. Now save filename between getting and resetting string resource in Reload operation - purify reported free memory read violations. AxeiiText Modified to remove only its own AsciiSrc callback proc. Confirmer Plugged memory leak - not freeing layout parse table. CtrlCodeSel Plugged memory leak - not freeing list returned by XawListShowCurrent in Feed. FileNom Added filter resource and SetValues procedure. Unset keyboard focus in Destroy to avoid freed memory access. Restored direction of keyboard focus to filename widget from anywhere in widget, not just list, except when pointer in filter, i.e. back to position before filter was introduced. Plugged small memory leak (of m) in FillWindow. Plugged memeory leak of list returned by XawListShowCurrent in ReplaceFilename. NumericPad Plugged memory leak - not freeing layout parse table. Preference /* This only half done - problem if free is done */ Plugged memory leak - not freeing layout parse table. ScrollText Fixed passing of source object instead of text widget in XawTextGetInsertionPoint call. axe coaxe Modified property format to enable multiple files on faxe command line. Extended server property to include user component. axe Added check that correct version of app defaults is found. coaxe Added check on XOpenDisplay succeeding. Added check that received PropertyNotify events relate to the AXE_COAXE property. Undented #define getwd line. Axe.ad Removed # comments - was causing problem if passed to xrdb. 3.0.1 AxeEditor Made helpFile in AxeEditorHelpWindow in AxeEditor.c automatic - was XtMalloc'ing wrong size. Corrected some #ifdef SYSV-isms. Moved static function declarations in Initialize to file scope. Made NewWindow & NewBuffer set associated directory of AxeText buffer. Added originating AxeText widget as first argument of AxeEditorCreateWindow routine. AxeMenuBtn Modified GetValuesHook (only applies at R4) to return null help. AxeTextDeck Added AxeTextDeckSetAssociatedDirectory routine. AxeText Moved static function declarations in Initialize and Destroy to file scope. Cast XtFree arguments to char*. Added associatedDirectory resource and initialDirectory variable in connection with initialising FileNominator. AxeiiText Moved static declaration of FwdBwdLineHook to file scope. ScrollText Corrected wrong argument types to XawTextSinkFindDistance. FileNomWin Added initialDirectory resource - passed directly to FileNominator. FileNom Added #include and removed inclusion of strings.h. Fixed RETURN in filter not working; changed method of determining parent FileNominator in DisplayCaret, Filter and ToggleDotFiles. Added initialDirectory resource. Viewlist Rewrote GeometryManager as allowVert was having no effect - scrollbar either always on or always off. axe Defined MAXHOSTNAMELEN if not defined after #include . Cast XtFree arguments to char*. Corrected width & height args of XParseGeometry to unsigned int. Changed AxeEditorCreateWindow calls. coaxe Added #include and removed inclusion of strings.h. Defined MAXHOSTNAMELEN if not defined after #include . Table Changed "xyz == NULL" comparisons to !xyz. Imakefile Made help file default directory be ${LIBDIR}. Added indexes to customisation and popups help files. 3.0 Widget rewrite axe-6.1.2.orig/INSTALL100644 243 144 20754 5550557105 13056 0ustar joostusersIndex ===== Installation Extension Language Xaw3d Compatability Installing aXe outside the X tree User Guide ---===---===---===--- Installation ============ Check Axe.tmpl for any customisation that needs to be done. Then xmkmf make Makefiles make Xaw3d # If necessary - see *** below make make install make install.man If you want to try out aXe from within the build directory then set AxeLibdir and InfoLibdir to `.' and `./Help' respectively in Axe.tmpl before doing the make. Then make the following environment variable setting XFILESEARCHPATH=./%N.ad:./Help/%N.ad and ensure that ./Help is in your command search path before running axe. All that then needs to be done before installation is to set AxeLibdir and InfoLibdir to their correct values and do another make. Alternatively, with AxeLibdir and InfoLibdir set to their values for installation all is not lost from within the build directory provided you first load the resource setting Axinfo*infoPath:./Help into the RESOURCE_MANAGER property of the root window, e.g. by executing xrdb -merge Axinfo*infoPath:./Help ^D interactively, and proceding as before. The help system can also be tried out independently by cd'ing to the Help directory, setting the environment variable XFILESEARCHPATH to %N.ad, and executing ./axinfo -xrm '*infoPath:.' If you have specified the exension language then it won't be usable unless you explicitly source the startup file by typing `source axe.tcl' in the minibuffer, or start axe as follows: ./axe -xrm '*axeLibDir:.' *** If you have built for Xaw3d compatability and to want to build without, or vice versa, then modify Axe.tmpl appropriately and run through the build sequence from the top again. Note that `make Xaw3d' is also required in the case of undoing Xaw3d. SOLARIS WARNING: I have built aXe under SunOS 5.2 but the process was not straightforward for the following reasons: 1. xmkmf doesn't exist. I used `imake -I/usr/openwin/lib/config' 2. I don't know what Sun have done to the config files (which are based on R4, not R5), but the `make Makefiles' stage failed. What I ended up doing was cd'ing into the Widgets and Help subdirectories and running `imake -I...' and `make' explicitly before returning to the top directory and doing the same there. 3. Because the header files are R5 (as identified by the value of XtSpecificationRelease in /usr/openwin/include/X11/Intrinsic.h) and the config files are R4 (as identified by the value of ProjectX in /usr/openwin/lib/config/Project.tmpl) an incompatability arises between what gets compiled and what gets linked. The answer is to include the following in Axe.tmpl #undef ProjectX #define ProjectX 5 immediately before the test #if ProjectX < 5 N.B. I simply gave aXe a quick test from the build directory without doing an installation. I assume that all that will be necessary will be to run `make install' and `make install.man' in the top directory and the Help subdirectory - there is nothing to install from the Widgets subdirectory. ---===---===---===--- Extension Language ================== An optional extension language facility using Tcl (Tool Command Language) is supported. You must have Tcl installed before you can incorporate this feature though. As it is not an essential part of aXe I have not included Tcl in the distribution. It can be obtained by ftp from sprite.berkeley.edu (128.32.150.27) amongst other places. The extension language feature is compatible with major Tcl versions 6 and 7. ---===---===---===--- Xaw3d Compatability =================== Unlike most other applications that use the Athena Widgets aXe cannot simply be relinked using an Xaw3d libray in place of the Xaw library to obtain an Xaw3d version. Because aXe subclasses some of the Xaw widgets it is necessary to take account of the extra information that Xaw3d introduces into the widget structures, i.e. the derived widgets have to be compiled differently to achieve Xaw3d compatability. I have tried to achieve that compatability by making as few changes as possible to my code. The upshot is that you will only be able to build an Xaw3d version using my procedure if your system supports symbolic links. The reason for this is that my modules #include whereas the Xaw3d ones #include , but in order that both should access the Xaw3d header files the build process creates an X11 directory in the build directory containing symbolic links Xaw and Xaw3d that both point to the installed .../include/X11/Xaw3d directory. This version of aXe is only known to be compatible with versions 0.4, 0.5 and 0.6 of Xaw3d. ---===---===---===--- Installing aXe outside the X tree ================================= If, like me, you don't like adding contributed software to the standard places within the installed X tree then you might be interested in the scheme that I use to avoid doing so. Of course, aXe's Imakefile is designed to make doing this easy. I set aside a directory, /usr/local/X11-local, for contributed X applications and install each in a subdirecory of its own. The scheme allows for version subdirectories, but that is not mandatory. Each version or application directory has a minimum structure consisting of bin, lib and lib/app-defaults subdirectories. Others can be added as demanded by the application, e.g. man and man/man1. Thus the picture is like this: usr | local | X11-local | xappl | +-----------------------------+ | | | version1 version2 <---- current | +-----------------------------+ | | | bin lib man | | | xappl app-defaults man1 | | XAppl xappl.1 The symbolic link current points to the version currently released to users. Thus it is easy to install a new version alongside existing ones without affecting their use. Releasing a new version amounts to making current point to its version directory, and of course if there are problems with it it is easy to switch back to the old one as long as its directory hasn't been deleted. As you can see, deleting an old version is simplicity itself because it is not scattered across several directories. Therefore, when I build aXe I make assignments like these in the Imakefile: Store = /usr/local/X11-local/axe/3.1 Bindir = ${Store}/bin Appdir = ${Store}/lib/app-defaults Mandir = ${Store}/man/man1 Helpdir = ${Store}/lib The key to making all this work is the script xany, which is included in the distribution. It should be installed in a directory where users normally find commands, e.g. /usr/local/bin, and a link made to it for every application that falls within the scheme, e.g. ln xany axe. Briefly, what happens is that for application xappl it constructs and executes the command XFILESEARCHPATH=/usr/local/X11-local/xappl/current/lib/app-defaults/%N \ /usr/local/X11-local/xappl/current/bin/xappl $@ The component current is omitted if /usr/local/X11-local/xappl/current does not exist. Note that the application directory name in /usr/local/X11-local must be the same as the command name, i.e. axe, not aXe. I always make any symbolic links that are needed, e.g. in /usr/local/man/man1 for the man page, in terms of current, so that once they have been made they are always up to date as versions come and go. ---===---===---===--- User Guide ========== Letter and A4 versions of the User Guide are available as compressed PostScript files in the Help subdirectory. The information is almost identical to that contained in the on-line help. Jim --- J.K.Wight@newcastle.ac.uk Department of Computing Science, University of Newcastle, Tel: +44 91 222 8238 Newcastle upon Tyne, NE1 7RU, United Kingdom. Fax: +44 91 222 8232 axe-6.1.2.orig/Imakefile100644 243 144 2207 5550557105 13607 0ustar joostusers/* * You shouldn't need to change anything in this file. * Customisation is carried out in Axe.tmpl */ #include "Axe.tmpl" #include "Axe.rules" #define IHaveSubdirs SUBDIRS = Widgets Help NamedTargetSubdirs(all,${SUBDIRS},Making,,all) NamedTargetSubdirs(Xaw3d,${SUBDIRS},Making,,Xaw3d) SRCS = axe.c OBJS = axe.o EXTRA_INCLUDES = -I. -I./Widgets ${EXTN_INCLUDES} LOCAL_LDFLAGS = ${TABLE_LDFLAGS} ${EXTN_LDFLAGS} ${XAW3D_LDFLAGS} SYS_LIBRARIES = XawClientLibs LOCAL_LIBRARIES = Widgets/libaxe.a ${TABLE_LIBS} ${EXTN_LIBS} ${XAW3D_LIBS} DEPLIBS = Widgets/libaxe.a XawClientDepLibs ComplaxeProgramTarget(axe,${Bindir},${Mandir}) InstallAxeDefaults(Axe,${Appdir}) InstallNonExecFile(axe.tcl,${AxeLibdir}) /* * It ought to be possible to use NullParameter in place of * -DDUMMY but that doesn't work everywhere, e.g. HP-UX 8.07 */ SpecialObjectRule(axe.o,version.h,-DDUMMY) AllTarget(coaxe) NormalProgramTarget(coaxe,coaxe.o,Widgets/libaxe.a,Widgets/libaxe.a,${XLIB}) InstallCoaxe(${Bindir}) #ifdef Extension MakeAxeDefaults(${AxeLibdir},) #else MakeAxeDefaults(${AxeLibdir},\/\*\*\/) #endif MakeXaw3d(axe) axe-6.1.2.orig/README100644 243 144 5531 5600342427 12654 0ustar joostusersThis, version 6.1.2, is an interim release that has been brought out purely to enable aXe 6.1 to work under X11R6. It does not support internationalisation. ...oooOOOooo... aXe is a simple to use text editor for X that represents a significant improvement over xedit. Also built around the Athena Text Widget it features, amongst other things, o multiple windows o multiple buffers o default menu interface o configurable menus o optional configurable button interface o minibuffer for expert use and access to external filters o provision for defining a keyboard macro o geometry specification and resizing in terms of characters o file selection via a browser o knowledge of line numbers o parenthesis matching o regular expression searching o restricted or unlimited undo o ability to change font o easy entry of control codes o xterm-like keymap feature o easy runtime setting of selected preferences (resources) o both brief and comprehensive (hypertext) on-line help o server mode with cooperating client programs o optional extension language using Tcl o optional Xaw3d widget set compatability o collection of reusable widgets that embody the functionality of aXe I have personally built and run core aXe, i.e. without the Tcl and Xaw3d options, on the following systems: Sun SPARC SunOS 4.1.x MIT X11R5 [cc/gcc] & X11R6 [gcc] Sun SPARC SunOS 5.2 OpenWindows (with a struggle) [gcc] Encore Multimax UMAX 4.3 MIT X11R5 [cc] DEC 5000/120 ULTRIX 4.2 MIT X11R5 [gcc] HP 9000/710 HP-UX 9.01 Vendor's X11R5 plus Xaw/Xmu from LUCS [cc] 486 DX2/50 PC Linux 0.99.14 MIT X11R5 [gcc] but not all have been subject to the same level of testing. I have only tested the Tcl and Xaw3d options on the first. A number of '#ifdef SYSV'-isms that have been fed back to me have been incorporated into the code and a possible scandir replacement is provided for those systems that do not have one. Although aXe will probably build under R4 run-time problems have been encountered in the past. I have not bothered to try this version under R4, and have not put any effort into solving previously known problems. Therefore, if you are at R4 you very much take pot luck. aXe is available by anonymous ftp from ftp.x.org (198.112.44.100) and arjuna.ncl.ac.uk (128.240.150.1) initially, and probably in due course from several other ftp sites. Check your nearest using xarchie. If you can't ftp, try sending email to ftpmail@decwrl.dec.com with the word "help" alone in your message body. You will receive instructions on how to ftp via email. Jim --- J.K.Wight@newcastle.ac.uk Department of Computing Science, University of Newcastle, Tel: +44 91 222 8238 Newcastle upon Tyne, NE1 7RU, United Kingdom. Fax: +44 91 222 8232 axe-6.1.2.orig/README.too100644 243 144 2634 5600335203 13447 0ustar joostusersThe only non-original code used is o insertfile.c, taken from ...mit/lib/Xaw/TextPop.c of Release 4 of X. o parts of AxeiiSink.c, being lightly modified R5 AsciiSink.c code. o match.c, taken form Byron Rakitzis' rc command interpreter that is based on AT & T's Plan 9 shell of the same name. o regexp.c - Henry Spencer's regular expression code. Comments in regexp.h and regexp.c explain minor modifications that have had to be made. o the (Xp)Table widget from the 2.5 distribution of Wcl, in case you don't have Wcl. o the HyperWidget by Baudouin Raoult. This has been modified to fix a refresh bug, and extended with a callback list that is triggered when the mouse enters a hypertext segment. o the R5 Porthole widget, which is used in the ScrollingText widget. It is included for the benefit of those still at R4. WARNING: This version of aXe does not support internationalisation at R6. This version may not work at R4. You use it at your peril. See INSTALL for instructions on building and installing. Letter and A4 versions of the User Guide are available as compressed PostScript files in the Help subdirectory. The information is almost identical to that contained in the on-line help. Jim --- J.K.Wight@newcastle.ac.uk Department of Computing Science, University of Newcastle, Tel: +44 91 222 8238 Newcastle upon Tyne, NE1 7RU, United Kingdom. Fax: +44 91 222 8232 axe-6.1.2.orig/WIDGETS100644 243 144 4412 5550557106 13030 0ustar joostusersI haven't had time to document these. The following brief outlines will have to suffice meantime. AxeiiSink ========= Subclass of the AsciiSink object to allow a different caret from the default. AxeiiText ========= Implements the actions of aXe but only provides hooks (mechanism) in the form of callback lists for those actions that require input, e.g. goto-line, load-file, save-file, or produce output, e.g. where, size. Implements mechanism for receiving notification of first change after a request to be notified of such changes. AxeText ======= Subclass of AxeiiText that completes the hooks (policy), using a FileNominator, for example, for input of file names. AxeTextDeck =========== Subclass of Composite that maintains a deck of overlapping AxeText widgets. AxeEditor ========= Subclass of Composite containing the five components of an aXe window. AxeWindow ========= Subclass of TopLevelShell containing an AxeEditor. Looks after the WM hints. AxeMenuButton ============= Subclass of MenuButton that holds help text describing its function. AxeSimpleMenu ============= Subclass of SimpleMenu that stores the id of the widget from which it was popped up. AxeSmeBSB ========= Subclass of SmeBSB that holds help text describing its function. AxeCommand ========== Subclass of Command that holds help text descibing its function. Confirmer ======== Subclass of TransientShell presenting alternative courses of action, in addition to cancellation. ControlCodeSelector =================== Subclass of XpTable. A table of selectable control codes. FileNominator ============= Subclass of Composite. A file selector. FileNominatorWindow =================== Subclass of TransientShell containing a FileNominator. Handles WM size hints. Viewlist ======== Subclass of Viewport. Specifically for use with FileNominator. Constrains list of files to resize in vertical direction only - improves redraw behaviour. ScrollingText ============= Subclass of Porthole containing an AsciiText widget. Used as the filter and filename sections of the FileNominator, enabling scrolling of text longer than the fixed size windows. NumericPad ========== Subclass of XpTable enabling entry of numbers via the mouse. Preference ========== Subclass of XpTable enabling runtime setting of some resources. axe-6.1.2.orig/axe.c100644 243 144 43463 5550557106 12751 0ustar joostusers/* * Copyright 1992 The University of Newcastle upon Tyne * * Permission to use, copy, modify and distribute this software and its * documentation for any purpose other than its commercial exploitation * is hereby granted without fee, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of The University of Newcastle upon Tyne not be used in * advertising or publicity pertaining to distribution of the software * without specific, written prior permission. The University of * Newcastle upon Tyne makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * THE UNIVERSITY OF NEWCASTLE UPON TYNE DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF * NEWCASTLE UPON TYNE BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. * * Author: Jim Wight (j.k.wight@newcastle.ac.uk) * Department of Computing Science * University of Newcastle upon Tyne, UK */ /* * The aXe Server Mode Implementation * * o aXe creates a server window and writes its ID as the value of the * AXE_SERVER property for the host and user running aXe on the default root * window, where the server window is the window of a widget that listens for * AXE_COAXE, AXE_FAXE and AXE_POLEAXE property changes. The AXE_SERVER * property name for a host and user is AXE_SERVER__ * * o A client on some host wishing to be served reads the root window's * AXE_SERVER__ property and writes the file, or files, to be * edited and the ID of a window to be notified when editing has been * completed as the value of the AXE_COAXE, AXE_FAXE or AXE_POLEAXE property * of the server window. * * o The ID of the window to be notified is stored as the value of the * AXE_COAXE property on the aXe window that is created for the client. A * client writes the AXE_FAXE property if it does not wait to be notified, in * which case no property is stored on the aXe window. A client writes the * AXE_POLEAXE property in order to terminate the server. * * o There is no guarantee that the values of the root window's * AXE_SERVER__ properties will be valid when read - aXe may * have been terminated without the corresponding property being deleted and * the window ID may even have been re-allocated in the meantime - so it is * stamped with the AXE_SERVER__ property to enable a * validity check to be carried out by the client. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef EXTENSION #include "Language.h" #endif #include "util.h" /* R4 concession */ #ifndef XPointer #define XPointer caddr_t #endif #define QUIT "QuitQuitQuitQuitQui" typedef struct _ResourceRec { String version; int windows; Boolean server; Boolean fileServer; String geometry; } ResourceRec, *ResourceRecPtr; static void AxeQuit(), AxeService(); static XtActionsRec actions[] = { "axe-quit", AxeQuit, "axe-service", AxeService, }; static char translations[] = "\ : axe-quit() \n\ AXE_COAXE: axe-service(AXE_COAXE) \n\ AXE_FAXE: axe-service(AXE_FAXE) \n\ AXE_POLEAXE:axe-service(AXE_POLEAXE)"; /*ARGSUSED*/ static void AxeQuit(widget, event, params, num_params) Widget widget; XEvent *event; String *params; Cardinal *num_params; { if (event->xclient.message_type == XA_STRING && strncmp(event->xclient.data.b, QUIT, 20) == 0) { exit(0); } } /*ARGSUSED*/ static void AxeService(widget, event, params, num_params) Widget widget; XEvent *event; String *params; Cardinal *num_params; { Display *display = XtDisplay(widget); long propLen = 3; Atom gotAtom; int gotFormat; unsigned long gotItems, moreBytes; unsigned char *propValue; char *p; int windows; Window wid; Widget newWindow; WidgetList axeEditor; if (strcmp(params[0], AXE_POLEAXE) == 0) { /*AxeExit(); Destroys remaining windows and notifies waiting coaxes */ /* StopServer(display); Wipes out AXE_SERVER_ property */ exit(0); } /* * Do an initial read to get the window ID and calculate out how * much there is left to be read in rounded up 32-bit chunks */ if (XGetWindowProperty(display, XtWindow(widget), XInternAtom(display, params[0], False), 0, propLen, False, XA_STRING, &gotAtom, &gotFormat, &gotItems, &moreBytes, &propValue) == Success) { if (gotAtom == XA_STRING) { sscanf((char *) propValue, "%12d", &wid); propLen = (moreBytes + 4) / 4; XtFree((char *) propValue); } } /* Read the remainder - the filename part - of the property */ if (XGetWindowProperty(display, XtWindow(widget), XInternAtom(display, params[0], False), (long) 3, propLen, False, XA_STRING, &gotAtom, &gotFormat, &gotItems, &moreBytes, &propValue) == Success) { if (gotAtom == XA_STRING) { for (p = (char *) propValue, windows = 0; strlen(p) != 0 || (strlen(p) == 0 && windows == 0); p += strlen(p) + 1, ++windows) { newWindow = AxeEditorCreateWindow(widget, XtParent(widget), p); XtRealizeWidget(newWindow); if (strcmp(params[0], AXE_COAXE) == 0) { XtVaGetValues(newWindow, XtNchildren, &axeEditor, NULL); XChangeProperty(display, XtWindow(AxeEditorEdWidget(axeEditor[0])), XInternAtom(display, params[0], False), XA_WINDOW, 32, PropModeReplace, (unsigned char *) &wid, 1); } XtPopup(newWindow, XtGrabNone); } } XtFree((char *) propValue); } } /* ARGSUSED */ static void NewWindow(w, client_data, call_data) Widget w; XtPointer client_data, call_data; { XtPopup(AxeEditorCreateWindow((Widget) client_data, (Widget) client_data, (String) call_data), XtGrabNone); } static void Select(widget, client_data, call_data) Widget widget; XtPointer client_data, call_data; { FileNominatorStruct *data = (FileNominatorStruct *) call_data; char filename[MAXPATHLEN]; if (data->directoryPart && data->filenamePart && (data->filenameStatus & FileNominatorReadable)) { strcpy(filename, data->directoryPart); strcat(filename, data->filenamePart); NewWindow(widget, client_data, (XtPointer) filename); } else { XBell(XtDisplay(widget), 100); return; } } /*ARGSUSED*/ static void ShowMenuChange(widget, client_data, call_data) Widget widget; XtPointer client_data, call_data; { XtVaSetValues(widget, XtNsensitive, (int) call_data ? True : False, NULL); } /*ARGSUSED */ static void Poleaxe(w, client_data, call_data) Widget w; XtPointer client_data, call_data; { exit(0); } static void DelayQuit(widget) Widget widget; { /* * Send a client message to the server window advising that Quit has been * invoked. The reason for delaying the Quit like this is so that coaxes * waiting for notification really get notified. Notification is carried * in the Destroy method of the AxeText widgets that are closed in the * Quit callback. As Destroy does not get called until the callback has * completed we can't call exit as early as the callback. */ XClientMessageEvent clientEvent; clientEvent.type = ClientMessage; clientEvent.display = XtDisplay(widget); clientEvent.window = XtWindow(widget); clientEvent.message_type = XA_STRING; clientEvent.format = 8; strncpy(clientEvent.data.b, QUIT, 20); XSendEvent(XtDisplay(widget), XtWindow(widget), False, NoEventMask, (XEvent *) &clientEvent); } /* ARGSUSED */ static void ReallyQuit(w, client_data, call_data) Widget w; XtPointer client_data, call_data; { AxeEditorIterate(AxeForceClose); DelayQuit((Widget) client_data); } /* ARGSUSED */ static void Quit(w, client_data, call_data) Widget w; XtPointer client_data, call_data; { static Widget confirmer = (Widget) 0; if (!AxeEditorIterate(AxeSafeClose)) { if (!confirmer) { confirmer = XtVaCreatePopupShell("confirmer", confirmerWidgetClass, (Widget) client_data, NULL); } ConfirmerRequestConfirmation(confirmer, "There are unsaved changes", "Quit anyway", ReallyQuit, "unused", NULL, client_data); } else { DelayQuit((Widget) client_data); } } /* ARGSUSED */ static void Help(w, client_data, call_data) Widget w; XtPointer client_data, call_data; { AxeEditorHelpWindow("Axeis", (Widget) client_data); } static XrmOptionDescRec options[] = { {"-buttons", "*buttons", XrmoptionNoArg, (XPointer) "True"}, {"-blinkPeriod", "*blinkPeriod", XrmoptionSepArg, (XPointer) NULL}, {"-fileTitle", "*fileTitle", XrmoptionNoArg, (XPointer) "True"}, {"-infoTimeout", "*infoTimeout", XrmoptionSepArg, (XPointer) NULL}, {"-miniBuffer", "*suppressMinibuffer", XrmoptionNoArg, (XPointer) "False"}, {"-noserver", ".server", XrmoptionNoArg, (XPointer) "False"}, {"-windows", ".windows", XrmoptionSepArg, (XPointer) NULL}, }; static XtResource resources[] = { { "version", "Version", XtRString, sizeof(String), XtOffset(ResourceRecPtr, version), XtRImmediate, (XtPointer) 0 }, { "geometry", "Geometry", XtRString, sizeof(String), XtOffset(ResourceRecPtr, geometry), XtRImmediate, (XtPointer) 0 }, { "server", "Server", XtRBoolean, sizeof(Boolean), XtOffset(ResourceRecPtr, server), XtRImmediate, (XtPointer) True }, { "fileServer", "Server", XtRBoolean, sizeof(Boolean), XtOffset(ResourceRecPtr, fileServer), XtRImmediate, (XtPointer) False }, { "windows", "Windows", XtRInt, sizeof(int), XtOffset(ResourceRecPtr, windows), XtRImmediate, (XtPointer) 0 }, }; main(argc, argv) int argc; char **argv; { XtAppContext app; Widget top, noapps, msg, server, fnom, table, waiter, poleaxe, help; Widget show = 0; Window serverWindow; Display *display; ResourceRec res; int parse, x, y; unsigned int width, height; char resource[MAXPATHLEN]; Pixel fg, bg; int arg, argmost; Boolean buffering, newWindow; String nameList = 0; XrmDatabase db; top = XtVaAppInitialize(&app, "Axe", options, XtNumber(options), #if defined(XtSpecificationRelease) && XtSpecificationRelease > 4 &argc, #else (Cardinal *) &argc, #endif argv, NULL, NULL); display = XtDisplay(top); db = XtDatabase(display); XtAppAddActions(app, actions, XtNumber(actions)); XtVaGetApplicationResources(top, (XtPointer) &res, resources, XtNumber(resources), NULL); if (!res.version || strcmp(res.version, QVERSION) != 0) { char message[1024]; strcpy(message, "This is "); strcat(message, QVERSION); strcat(message, ".\n\n"); strcat(message, "The application defaults file\n"); strcat(message, "for this release has not been\n"); strcat(message, "found."); if (res.version) { strcat(message, "\n\nIt may help to know in solving\n"); strcat(message, "the problem that the defaults\n"); strcat(message, "file for "); strcat(message, res.version); strcat(message, " was found."); } noapps = XtVaCreateManagedWidget("noapps", formWidgetClass, top, NULL); msg = XtVaCreateManagedWidget("msg", labelWidgetClass, noapps, XtNlabel, message, NULL); poleaxe = XtVaCreateManagedWidget("Quit", commandWidgetClass, noapps, XtNfromVert, msg, NULL); XtAddCallback(poleaxe, XtNcallback, Poleaxe, (XtPointer) 0); XtRealizeWidget(top); XtAppMainLoop(app); } if (res.geometry) { parse = XParseGeometry(res.geometry, &x, &y, &width, &height); if (parse & WidthValue) { sprintf(resource, "*AxeText*columns:%d", width); XrmPutLineResource(&db, resource); } if (parse & HeightValue) { sprintf(resource, "*AxeText*rows:%d", height); XrmPutLineResource(&db, resource); } } if (res.fileServer) { server = XtVaCreatePopupShell("fileServer", fileNominatorWindowWidgetClass, top, NULL); fnom = FileNominatorWindowFileNominatorWidget(server); XtAddCallback(fnom, XtNselectCallback, Select, (XtPointer) top); XtAddCallback(fnom, XtNcancelCallback, Quit, (XtPointer) server); res.server = True; } else if (res.server) { server = XtVaCreatePopupShell("server", topLevelShellWidgetClass, top, NULL); table = XtVaCreateManagedWidget("table", xpTableWidgetClass, server, XtNshrinkSimple, False, NULL); waiter = XtVaCreateManagedWidget("waiter", commandWidgetClass, table, NULL); XtAddCallback(waiter, XtNcallback, NewWindow, (XtPointer) top); XtVaGetValues(waiter, XtNforeground, &fg, XtNbackground, &bg, NULL); XtVaSetValues(waiter, XtNbackgroundPixmap, XCreatePixmapFromBitmapData(display, XDefaultRootWindow(display), (char *) axeLogo_bits, axeLogo_width, axeLogo_height, fg, bg, XDefaultDepthOfScreen(XtScreen(waiter))), NULL); show = XtVaCreateManagedWidget("show", axeMenuButtonWidgetClass, table, XtNsensitive, False, NULL); AxeEditorAddShowMenuCallback(show, ShowMenuChange, (XtPointer) 0); poleaxe = XtVaCreateManagedWidget("poleaxe", commandWidgetClass, table, NULL); XtAddCallback(poleaxe, XtNcallback, Quit, (XtPointer) server); help = XtVaCreateManagedWidget("help", commandWidgetClass, table, NULL); XtAddCallback(help, XtNcallback, Help, (XtPointer) top); } if (res.server) { XtOverrideTranslations(server, XtParseTranslationTable(translations)); XtRealizeWidget(server); serverWindow = XtWindow(server); TrapErrors(display); /* If there is already a server running this one will replace it */ XChangeProperty(display, XDefaultRootWindow(display), HostUserServerAtom(display), XA_WINDOW, 32, PropModeReplace, (unsigned char *) &serverWindow, 1); if (xerror == Success) { XChangeProperty(display, serverWindow, HostUserServerAtom(display), XA_STRING, 32, PropModeReplace, NULL, 0); } DontTrapErrors(display); } else { XrmPutLineResource(&db, "*ExitOnCloseLastWindow:True"); } #ifdef EXTENSION interpreter.Initialize(top); #endif argmost = (res.windows) ? res.windows : (res.server ? 0 : 1); for (buffering = False, arg = 1; arg < argc; ++arg) { if (strncmp(argv[arg], "-buffer", strlen(argv[arg])) == 0) { buffering = True; } if (buffering) { --argmost; } } if (argc == 1 && !res.server) { for (arg = 1; arg <= argmost; ++arg) { NewWindow((XtPointer) 0, (XtPointer) top, (XtPointer) 0); } } else { for (arg = argc - 1; arg < argmost; ++arg) { NewWindow((XtPointer) 0, (XtPointer) top, (XtPointer) 0); } for (buffering = False, newWindow = True, arg = 1; arg < argc; ++arg) { if (strncmp(argv[arg], "-buffer", strlen(argv[arg])) == 0) { buffering = True; newWindow = True; if (nameList) { NewWindow((XtPointer) 0, (XtPointer) top, (XtPointer) nameList); XtFree(nameList); nameList = 0; } continue; } if (buffering) { if (newWindow) { nameList = XtMalloc((unsigned) (strlen(argv[arg]) + 1)); strcpy(nameList, argv[arg]); newWindow = False; } else { int len = strlen(nameList); nameList = XtRealloc(nameList, (unsigned) (len + 1 + strlen(argv[arg]) + 1)); nameList[len] = ' '; strcpy(&nameList[len + 1], argv[arg]); } } else { NewWindow((XtPointer) 0, (XtPointer) top, (XtPointer) argv[arg]); } } if (nameList) { NewWindow((XtPointer) 0, (XtPointer) top, (XtPointer) nameList); XtFree(nameList); } } if (res.server) { int argc; String *argv; XtVaGetValues(top, XtNargc, &argc, XtNargv, &argv, NULL); XSetCommand(display, XtWindow(server), argv, argc); XtPopup(server, XtGrabNone); } XtAppMainLoop(app); } axe-6.1.2.orig/axe.man100644 243 144 6441 5550557106 13255 0ustar joostusers.TH AXE 1 "January 1994" "aXe Release 6.0" .SH NAME aXe - an X editor .SH SYNOPSIS .B axe [ -toolkitoption ...] [ -option ... ] [ filename ... ] [ -buffer filename ...] .SH DESCRIPTION .I aXe is a simple to use text editor for X that represents a significant improvement over xedit. Also built around the Athena Text Widget it features, amongst other things, .DS o multiple windows o multiple buffers o default menu interface o configurable menus o optional configurable button interface o minibuffer for expert use and access to external filters o provision for defining a keyboard macro o geometry specification and resizing in terms of characters o file selection via a browser o knowledge of line numbers o parenthesis matching o regular expression searching o restricted or unlimited undo o ability to change font o easy entry of control codes o xterm-like keymap feature o easy runtime setting of selected preferences (resources) o both brief and comprehensive (hypertext) on-line help o server mode with cooperating client programs o optional extension language using Tcl o optional Xaw3d widget set compatability o collection of reusable widgets that embody the functionality of aXe .DE .PP By default aXe provides a menu interface to some common Text Widget operations and most of its extra features. An optional button interface, in which there is one button present for every static menu entry, can be selected via the keyword .I -buttons, or by setting the top level resource .I buttons. A reduced button interface is configurable. .PP Individual file names on the command line will be allocated to separate windows. A list of file names introduced by the keyword .I -buffer will be allocated to buffers belonging to the same window (an older, still supported feature, enables the same to be achieved by quoting the list of names). Note that files destined for individual windows must precede those for buffers if the -buffer keyword is used. An initial number of windows to open can be specified on the command line by using the keyword .I -windows or by giving the top level resource .I windows a numeric value. The value of windows is ignored if the files specified on the command line require more than that number of windows. .PP If a top level geometry resource is provided, e.g. by using the toolkit keyword .I -geometry, then the width and height fields will be interpreted to mean the numbers of columns and rows respectively that editing widnows are to have. .PP aXe also acts as a server of editing windows to cooperating clients. Two, coaxe and faxe, are provided as part of the aXe suite. Server mode is the default, but can be switched off by using the command line keyword .I -noserver, or by setting the top level resource .I server False .PP aXe has comprehensive on-line help, so, to avoid having to keep the information up to date in two places, it will not be duplicated here. .SH ACKNOWLEDGEMENTS That aXe makes use of code from Byron Rakitzis' rc command interpreter that is based on AT&T's Plan 9 shell of the same name is duly acknowledged. .SH SEE ALSO xedit(1), Athena Widget (Xaw) documentation .SH AUTHOR Jim Wight (j.k.wight@newcastle.ac.uk) .br Department of Computing Science, University of Newcastle, Newcastle upon Tyne, UK, NE1 7RU axe-6.1.2.orig/axe.tcl100644 243 144 3656 5550557106 13271 0ustar joostusersproc with-selection {func {args {}}} { set selection [get-selection] set start [lindex $selection 0] set end [lindex $selection 1] set lines [lindex $selection 2] if {$start == $end} {return} set-position $start for {set line 0} {$line < $lines} {incr line} { action beginning-of-line eval $func $args action next-line } action beginning-of-line set-selection $start [get-position] } proc prefix {{text {> }}} { with-selection action insert-string $text } proc stripn {{n 1}} { action multiply $n action delete-next-character } proc strip {{n 1}} { with-selection stripn $n } proc join-lines {{n 1} {insert " "}} { for {set line 0} {$line < $n} {incr line} { action end-of-line action delete-next-character action insert-string $insert } } proc format-all {} { set caret [get-position] action beginning-of-file for {set lastpos -1; set curpos 0} \ {$curpos != $lastpos} \ {set lastpos $curpos; set curpos [get-position]} { action forward-paragraph action form-paragraph action next-line } set-position $caret action redraw-display } proc upper {{conversion toupper}} { set selected [get-selection] set start [lindex $selected 0] set finish [lindex $selected 1] set selection [lindex $selected 3] action delete-selection action insert-string [string $conversion $selection] set-selection $start $finish } proc lower {} { upper tolower } # - # - # - # - # - # - # - Backwards Compatability - # - # - # - # - # - # - # proc loopSel {func {args {}}} { eval with-selection $func $args } proc getSelection {} { get-selection } proc setSelection {from to} { set-selection $from $to } proc getPos {} { get-position } proc setPos {pos} { set-position $pos } # Compatability versions of join and format have not been # implemented as they mask Tcl commands of the same name. axe-6.1.2.orig/coaxe.c100644 243 144 16657 5550557106 13300 0ustar joostusers/* * Copyright 1992 The University of Newcastle upon Tyne * * Permission to use, copy, modify and distribute this software and its * documentation for any purpose other than its commercial exploitation * is hereby granted without fee, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of The University of Newcastle upon Tyne not be used in * advertising or publicity pertaining to distribution of the software * without specific, written prior permission. The University of * Newcastle upon Tyne makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * THE UNIVERSITY OF NEWCASTLE UPON TYNE DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF * NEWCASTLE UPON TYNE BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. * * Author: Jim Wight (j.k.wight@newcastle.ac.uk) * Department of Computing Science * University of Newcastle upon Tyne, UK */ #include #include #include #include #include extern int errno; #ifndef __BSD_4_4__ extern char *sys_errlist[]; #endif #include extern char *getenv(); extern char *malloc(), *realloc(); #include "util.h" #include static int ValidWindow(display, wid, atom) Display *display; Window wid; Atom atom; { Atom gotAtom; int gotFormat; unsigned long gotItems, moreBytes; unsigned char *propValue; TrapErrors(display); if (XGetWindowProperty(display, wid, atom, 0, 0, False, XA_STRING, &gotAtom, &gotFormat, &gotItems, &moreBytes, &propValue) == Success) { if (gotAtom == None) { xerror = BadAtom; } XFree((char *) propValue); } DontTrapErrors(display); return xerror == Success; } static void NoAxe(error) int error; { char host[MAXHOSTNAMELEN]; (void) GetHostName(host, MAXHOSTNAMELEN); fprintf(stderr, "aXe server on %s not running: unable to start axe: %s\n", host, sys_errlist[error]); exit(1); } main(argc, argv) int argc; char *argv[]; { int coaxe, faxe, poleaxe, arg, proplen, nchunk, newlen; char *r, *dpy; Display *display; Bool buffers = False, newWindow = True; char *token; Atom reqAtom = XA_WINDOW, gotAtom; int gotFormat; unsigned long gotItems, moreBytes; unsigned char *propValue; Window propWindow; int serverOK; char wid[13], cwd[MAXPATHLEN]; char *property, *maxp, *p; Window window; XEvent event; #if defined(SYSV) || defined(SVR4) extern char *getcwd(); #define getwd(a) getcwd(a,MAXPATHLEN) #else extern char *getwd(); #endif r = (r = rindex(argv[0], '/')) ? ++r : argv[0]; coaxe = strncmp(r, "coaxe", 5) == 0; faxe = strncmp(r, "faxe", 4) == 0; /* poleaxe = strncmp(r, "poleaxe", 7) == 0; Not used */ if ( !(display = XOpenDisplay(NULL)) ) { if ( !(dpy = getenv("DISPLAY")) ) { fprintf(stderr, "DISPLAY variable not set\n"); } else { /* Assume XOpenDisplay puts out appropriate message */ } exit(1); } window = XCreateSimpleWindow(display, DefaultRootWindow(display), 0, 0, 1, 1, 0, WhitePixel(display, DefaultScreen(display)), WhitePixel(display, DefaultScreen(display)) ); XSelectInput(display, window, PropertyChangeMask); sprintf(wid, "%12ld", window); if (XGetWindowProperty(display, XDefaultRootWindow(display), HostUserServerAtom(display), 0, 1, False, reqAtom, &gotAtom, &gotFormat, &gotItems, &moreBytes, &propValue) == Success) { if (gotAtom == reqAtom) { propWindow = *((Window *) propValue); serverOK = ValidWindow(display, propWindow, HostUserServerAtom(display)); XFree((char *) propValue); } else { serverOK = False; } } if (!getwd(cwd)) { fprintf(stderr, "Current directory unreadable\n" ); exit(1); } property = malloc((unsigned) MAXPATHLEN * sizeof(char)); maxp = property + MAXPATHLEN; nchunk = 1; strcpy(property, wid); p = &property[strlen(property)]; for (arg = 1; (faxe && arg < argc) || (coaxe && arg < argc && arg <= 1); ++arg) { token = argv[arg]; if (token[0] == '-' && strncmp(token, "-buffer", strlen(token)) == 0) { buffers = True; newWindow = True; continue; } if (argv[arg][0] == '/') { newlen = strlen(argv[arg]) + 1; } else { newlen = strlen(cwd) + 1 + strlen(argv[arg]) + 1; } if (p + newlen >= maxp) { { int poff = p - property; if ( !(property = realloc(property, (unsigned) ++nchunk * MAXPATHLEN * sizeof(char))) ) { fprintf(stderr, "Out of memory\n"); exit(1); } p = property + poff; maxp = property + (nchunk * MAXPATHLEN); } } if (buffers && !newWindow) { *(p - 1) = ' '; } if (argv[arg][0] == '/') { strcpy(p, token); } else { strcpy(p, cwd); strcat(p, "/"); strcat(p, token); } p += strlen(p) + 1; if (!serverOK) { *(p - 1) = ' '; } if (buffers && newWindow) { newWindow = !newWindow; } } *p = *(p + 1) = '\0'; proplen = p + 2 - property; if (!serverOK) { int err; if (coaxe) { if (argc == 1) { err = execlp("axe", "axe", "-noserver", (char *) 0); } else { err = execlp("axe", "axe", "-noserver", property + 12, (char *) 0); } if (err == -1) { NoAxe(errno); } } else if (faxe) { char command[MAXPATHLEN]; if (argc == 1) { sprintf(command, "axe -noserver &"); } else { sprintf(command, "axe -noserver %s &", property + 12); } err = system(command); if ( ((err >> 8) & 0xff) != 0) { err = (err >> 8) & 0xff; } else { err = errno; } if (err != 0) { NoAxe(err); } else { exit(0); } } } XChangeProperty(display, propWindow, XInternAtom(display, (coaxe ? AXE_COAXE : (faxe ? AXE_FAXE : AXE_POLEAXE)), False), XA_STRING, 8, PropModeReplace, (unsigned char *) property, proplen); free(property); XFlush(display); if (coaxe) { for(;;) { XNextEvent(display, &event); if (event.type == PropertyNotify && event.xproperty.atom == XInternAtom(display, AXE_COAXE, False)) { break; } } } XCloseDisplay(display); return 0; } axe-6.1.2.orig/patchlevel.h100644 243 144 25 5600342430 14217 0ustar joostusers#define PATCHLEVEL 3 axe-6.1.2.orig/version.h100644 243 144 67 5600342432 13565 0ustar joostusers#define VERSION aXe 6.1.2 #define QVERSION "aXe 6.1.2" axe-6.1.2.orig/xany100644 243 144 5667 5550557106 12716 0ustar joostusers#!/bin/sh X11LOCAL=/usr/local/X11-local app=`expr //$0 : '.*/\(.*\)'` appdir=$app test -d $X11LOCAL/$app/current && appdir=$app/current XFSP=$X11LOCAL/$appdir/lib/app-defaults XFILESEARCHPATH=$XFSP/%N:$XFILESEARCHPATH; export XFILESEARCHPATH path=$X11LOCAL/$appdir/bin:$PATH if test $# -eq 0 then PATH=$path exec $app else PATH=$path exec $app "$@" fi ############################################################################### ## ## ## The purpose of this script is to provide a hook so that any X application ## ## that has a class specific application defaults file can be linked to it ## ## and run without having to place that file in a standard place within the ## ## installed X tree. The assumption is made that applications, e.g. xother, ## ## are installed in directories that have the following minimum structure. ## ## The version level may or may not exist. If it does then current should ## ## be a symbolic link to the current (default) version. ## ## ## ############################################################################### ## ## ## usr ## ## | ## ## local ## ## | ## ## X11-local ## ## | ## ## xother ## ## | ## ## +-----------------------------+ ## ## | | | ## ## version1 version2 <---- current ## ## | ## ## +-----------------------------+ ## ## | | ## ## bin lib ## ## | | ## ## xother app-defaults ## ## | ## ## XOther ## ## ## ###############################################################################