Back to index

plt-scheme  4.2.1
xwScrollText.c
Go to the documentation of this file.
00001 /*
00002  * Copyright 2004-2009 PLT Scheme Inc.
00003  * Copyright 1992, 1994 The University of Newcastle upon Tyne
00004  * 
00005  * Permission to use, copy, modify and distribute this software and its
00006  * documentation for any purpose other than its commercial exploitation
00007  * is hereby granted without fee, provided that the above copyright
00008  * notice appear in all copies and that both that copyright notice and
00009  * this permission notice appear in supporting documentation, and that
00010  * the name of The University of Newcastle upon Tyne not be used in
00011  * advertising or publicity pertaining to distribution of the software
00012  * without specific, written prior permission. The University of
00013  * Newcastle upon Tyne makes no representations about the suitability of
00014  * this software for any purpose. It is provided "as is" without express
00015  * or implied warranty.
00016  * 
00017  * THE UNIVERSITY OF NEWCASTLE UPON TYNE DISCLAIMS ALL WARRANTIES WITH
00018  * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
00019  * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF
00020  * NEWCASTLE UPON TYNE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
00021  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
00022  * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
00023  * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
00024  * PERFORMANCE OF THIS SOFTWARE.
00025  * 
00026  * Author:  Jim Wight (j.k.wight@newcastle.ac.uk)
00027  *          Department of Computing Science
00028  *          University of Newcastle upon Tyne, UK
00029  */
00030 
00031 #include <X11/IntrinsicP.h>
00032 #include <X11/StringDefs.h>
00033 #include <X11/Xaw/AsciiText.h>
00034 #include <xwScrollTextP.h>
00035 
00036 #define CLASS(field) scrollingTextClassRec.scrolling_text_class.field
00037 #define PRIVATE(w,field) (((ScrollingTextWidget) w)->scrollingText.field)
00038 
00039 static XtResource resources[] = {
00040 #define Offset(field) XtOffsetOf(ScrollingTextRec, scrollingText.field)
00041     { XtNscrollOnMovement, XtCScrollOnMovement, XtRBoolean, sizeof(Boolean),
00042        Offset(scroll_on_movement), XtRImmediate, (XtPointer) True },
00043     { XtNtextWidget, XtCTextWidget, XtRWidget, sizeof(Widget),
00044        Offset(text_widget), XtRImmediate, (XtPointer) NULL },
00045 #undef Offset
00046 };
00047 
00048 static void ClassInitialize(), Initialize(), Destroy();
00049 static Boolean SetValues();
00050 
00051 static void AdjustForMovement(), AdjustForChange();
00052 static Boolean AfterAction();
00053 
00054 static char translations[] = "<Key>Return:no-op() \n <Key>Linefeed:no-op()";
00055 
00056 ScrollingTextClassRec scrollingTextClassRec = {
00057   { /* core fields */
00058     /* superclass           */     (WidgetClass) &portholeClassRec,
00059     /* class_name           */     "ScrollingText",
00060     /* widget_size          */     sizeof(ScrollingTextRec),
00061     /* class_initialize            */     ClassInitialize,
00062     /* class_part_initialize       */     NULL,
00063     /* class_inited         */     FALSE,
00064     /* initialize           */     Initialize,
00065     /* initialize_hook             */     NULL,
00066     /* realize                     */     XtInheritRealize,
00067     /* actions                     */     NULL,
00068     /* num_actions          */     0,
00069     /* resources            */     resources,
00070     /* num_resources        */     XtNumber(resources),
00071     /* xrm_class            */     NULLQUARK,
00072     /* compress_motion             */     TRUE,
00073     /* compress_exposure    */     TRUE,
00074     /* compress_enterleave  */     TRUE,
00075     /* visible_interest            */     FALSE,
00076     /* destroy                     */     Destroy,
00077     /* resize               */     XtInheritResize,
00078     /* expose               */     NULL,
00079     /* set_values           */     SetValues,
00080     /* set_values_hook             */     NULL,
00081     /* set_values_almost    */     XtInheritSetValuesAlmost,
00082     /* get_values_hook             */     NULL,
00083     /* accept_focus         */     NULL,
00084     /* version                     */     XtVersion,
00085     /* callback_private            */     NULL,
00086     /* tm_table                    */     NULL,
00087     /* query_geometry              */     XtInheritQueryGeometry,
00088     /* display_accelerator  */     XtInheritDisplayAccelerator,
00089     /* extension            */     NULL
00090   },
00091   { /* composite fields */
00092     /* geometry_manager            */     XtInheritGeometryManager,
00093     /* change_managed              */     XtInheritChangeManaged,
00094     /* insert_child         */     XtInheritInsertChild,
00095     /* delete_child         */     XtInheritDeleteChild,
00096     /* extension            */     NULL
00097   },
00098   { /* porthole fields */
00099     /* ignore                   */ 0
00100   },
00101   { /* scrollingText fields */
00102     /* extension                   */     NULL
00103   },
00104 };
00105 
00106 WidgetClass scrollingTextWidgetClass = (WidgetClass) &scrollingTextClassRec;
00107 
00108 static void
00109 ClassInitialize()
00110 {
00111      CLASS(translations) = XtParseTranslationTable(translations);
00112 }
00113 
00114 /* ARGSUSED */
00115 static void
00116 Initialize(req, new, args, num_args)
00117     Widget req, new;
00118     ArgList args;
00119     Cardinal *num_args;
00120 {
00121     XFontStruct *font;
00122     Dimension width, height;
00123 
00124     Widget text = PRIVATE(new,text_widget) =
00125         XtVaCreateManagedWidget("text", asciiTextWidgetClass, new, NULL);
00126 
00127     XtOverrideTranslations(text, CLASS(translations));
00128     XtAddCallback(XawTextGetSource(text), XtNcallback, AdjustForChange, NULL);
00129 
00130     if (PRIVATE(new,scroll_on_movement))
00131     {
00132        PRIVATE(new,action_hook) = 
00133            XtAppAddActionHook(XtWidgetToApplicationContext(new),
00134                                         AdjustForMovement, (XtPointer) text);
00135     }
00136     else
00137     {
00138        PRIVATE(new,action_hook) = (XtActionHookId) 0;
00139     }
00140 
00141     XtVaGetValues(text,
00142                 XtNfont, &font,
00143                 XtNwidth, &width,
00144                 XtNheight, &height,
00145                 NULL);
00146 
00147     PRIVATE(new,font_width) = font->max_bounds.width;
00148 
00149     if (!new->core.width)
00150     {
00151        new->core.width = width;
00152     }
00153 
00154     if (!new->core.height)
00155     {
00156        new->core.height = height;
00157     }
00158 
00159     PRIVATE(new,work_proc) = (XtWorkProcId) 0;
00160 }
00161 
00162 /* ARGSUSED */
00163 static Boolean
00164 SetValues(old, request, new, args, num_args)
00165      Widget old, request, new;
00166      ArgList args;
00167      Cardinal *num_args;
00168 {
00169     if (PRIVATE(old,scroll_on_movement) != PRIVATE(new,scroll_on_movement))
00170     {
00171        if (PRIVATE(new,scroll_on_movement))
00172        {
00173            PRIVATE(new,action_hook) = 
00174               XtAppAddActionHook
00175                   (XtWidgetToApplicationContext(new),
00176                    AdjustForMovement, (XtPointer) PRIVATE(new,text_widget));
00177        }
00178        else
00179        {
00180            XtRemoveActionHook(PRIVATE(new,action_hook));
00181            PRIVATE(new,action_hook) = (XtActionHookId) 0;
00182        }
00183     }
00184 
00185     return False;
00186 }
00187 
00188 static void
00189 Destroy(w)
00190      Widget w;
00191 {
00192     if (PRIVATE(w,action_hook))
00193     {
00194        XtRemoveActionHook(PRIVATE(w,action_hook));
00195     }
00196 }
00197 
00198 /* ARGSUSED */
00199 static void
00200 AdjustForMovement(widget, client_data, action, event, params, num_params)
00201      Widget widget;
00202      XtPointer client_data;
00203      String action;
00204      XEvent *event;
00205      String *params;
00206      Cardinal *num_params;
00207 {
00208     Widget text = (Widget) client_data;
00209 
00210     if (widget != text)
00211     {
00212        return;
00213     }
00214 
00215     /*
00216      * This routine gets called before the action takes place so set
00217      * up a work proc to do the work after the action has taken place
00218      */
00219     if (strcmp(action, "forward-character")  == 0 ||
00220        strcmp(action, "backward-character") == 0 ||
00221        strcmp(action, "forward-word")       == 0 ||
00222        strcmp(action, "backward-word")      == 0 ||
00223        strcmp(action, "beginning-of-line")  == 0 ||
00224        strcmp(action, "end-of-line")        == 0)
00225     {
00226        /*
00227         * Positioning with the mouse results in work_proc being corrupted with
00228         * the result that the test fails and scrolling stops happening. I don't
00229         * understand what is going on. Therefore, for the time being always
00230         * register a work proc. It is probably unlikely that events will come
00231         * in fast enough anyway for there to be an unexecuted one still around.
00232 
00233        if (!PRIVATE(text,work_proc))
00234        {
00235         */
00236            PRIVATE(text,work_proc) =
00237               XtAppAddWorkProc(XtWidgetToApplicationContext(widget),
00238                                           AfterAction, (XtPointer) widget);
00239      /* } */
00240     }
00241 }
00242 
00243 static Boolean
00244 AfterAction(client_data)
00245      XtPointer client_data;
00246 {
00247     Widget text = (Widget) client_data;
00248 
00249 
00250     AdjustForChange(XawTextGetSource(text), (XtPointer) 0, (XtPointer) 0);
00251 
00252     PRIVATE(text,work_proc) = (XtWorkProcId) 0;
00253 
00254     return True;
00255 }
00256 
00257 /* ARGSUSED */
00258 static void
00259 AdjustForChange(widget, client_data, call_data)
00260      Widget widget;
00261      XtPointer client_data, call_data;
00262 {
00263     Widget source, sink, text = XtParent(widget), porthole = XtParent(text);
00264     Position x, prevx, top;
00265     Dimension lm, width, phwidth, fwidth = PRIVATE(porthole,font_width);
00266     XawTextPosition pos, eol, junk;
00267     int pd, ed, morejunk;
00268 
00269     XtVaGetValues(text,
00270                 XtNtextSource, &source,
00271                 XtNtextSink, &sink,
00272                 XtNleftMargin, &lm,
00273                 XtNx, &prevx,
00274                 NULL);
00275 
00276     XtVaGetValues(porthole, XtNwidth, &phwidth, NULL);
00277     top = phwidth - fwidth - fwidth;
00278 
00279     pos = XawTextGetInsertionPoint(text);
00280     eol = XawTextSourceScan(source, pos, XawstAll, XawsdRight, 1, True);
00281 
00282     /* Calculations of pd and ed take tabs into account */
00283     XawTextSinkFindDistance(sink, 0, lm, pos, &pd, &junk, &morejunk);
00284     XawTextSinkFindDistance(sink, 0, lm, eol, &ed, &junk, &morejunk);
00285 
00286     if (pd > top - prevx)
00287     {
00288        x =  top - pd;
00289     }
00290     else if (pd < fwidth - prevx)
00291     {
00292        x = fwidth - pd;
00293     }
00294     else
00295     {
00296        x = prevx;
00297     }
00298 
00299     /* Stretch widget to eliminate solid block at end of line */
00300     width = ed + fwidth;
00301     
00302     XtVaSetValues(text, XtNx, x, XtNwidth, width, NULL);
00303 }
00304 
00305 #undef PRIVATE
00306 #undef CLASS