Back to index

plt-scheme  4.2.1
xwTabString.c
Go to the documentation of this file.
00001 /*
00002  *     Functions for drawing String's with tab characters in them
00003  */
00004 
00005 #include <stdlib.h>
00006 #include <X11/Intrinsic.h>
00007 #include <X11/StringDefs.h>
00008 #ifdef WX_USE_XFT
00009 # include <X11/Xcms.h>
00010 # include <X11/Xft/Xft.h>
00011 #endif
00012 #include "xwTabString.h"
00013 #include "wxAllocColor.h"
00014 
00015 extern int scheme_utf8_decode_all(unsigned char *, int, unsigned int *, int);
00016 extern int scheme_utf8_decode(const unsigned char *s, int start, int end, 
00017                            unsigned int *us, int dstart, int dend,
00018                            long *ipos, char utf16, int permissive);
00019 #ifdef WX_USE_XFT
00020 extern wxExtFont wxFindAAFont(Display *dpy, wxExtFont xfont, int c);
00021 #endif
00022 
00023 static int leading_utf8_len(char *s, int len)
00024 {
00025   long ipos;
00026   scheme_utf8_decode((const unsigned char *)s, 0, len, 
00027                    NULL, 0, 1,
00028                    &ipos, 0, '?');
00029   return ipos;
00030 }
00031 
00032 static int xdoDraw(measure, font,
00033                  display, drawable, gc, x, y, string, length, image
00034 #ifdef WX_USE_XFT
00035                  , xfont, draw, col
00036 #endif
00037                  )
00038  int measure;
00039  XFontStruct *font;
00040  Display *display;
00041  Drawable drawable;
00042  GC gc;
00043  int x;
00044  int y;
00045  String string;
00046  int length;
00047 #ifdef WX_USE_XFT
00048  wxExtFont xfont;
00049  XftDraw *draw;
00050  XftColor *col;
00051 #endif
00052 {
00053 # define WXTAB_BUF_SIZE 64
00054   unsigned int *us, usbuf[WXTAB_BUF_SIZE];
00055   long ulen;
00056   int width = 0;
00057 
00058   ulen = scheme_utf8_decode_all((unsigned char *)string, length, NULL, '?');
00059   if (ulen <= WXTAB_BUF_SIZE)
00060     us = usbuf;
00061   else
00062     us = (unsigned int *)XtMalloc(ulen * sizeof(unsigned int));
00063   ulen = scheme_utf8_decode_all((unsigned char *)string, length, us, '?');
00064 
00065 #ifdef WX_USE_XFT
00066   if (!xfont)
00067 #endif
00068     {
00069       /* Squash 32-bit encoding into 16-bit encoding.
00070         Since we overwrite the array, it's important
00071         to start at position 0 and go up: */
00072       int i, v;
00073       for (i = 0; i < ulen; i++) {
00074        if (us[i] > 0xFFFF)
00075          v = '?';
00076        else
00077          v = us[i];
00078        ((XChar2b *)us)[i].byte2 = v & 0xff;
00079        ((XChar2b *)us)[i].byte1 = v >> 8;
00080       }
00081     }
00082 
00083   if (measure
00084 #ifdef WX_USE_XFT
00085       || xfont
00086 #endif
00087       ) {
00088 #ifdef WX_USE_XFT
00089     if (xfont) {
00090       XGlyphInfo overall;
00091       int i, start = 0;
00092       
00093       width = 0;
00094       while (1) {
00095        for (i = start; i < ulen; i++) {
00096          if (!XftGlyphExists(display, xfont, us[i]))
00097            break;
00098        }
00099 
00100        if (i > start) {
00101          XftTextExtents32(display, xfont, us + start, i - start, &overall);
00102          if (!measure) {
00103            if (gc) {
00104              XFillRectangle(display, drawable, gc, x + width, y - xfont->ascent,
00105                           overall.xOff, xfont->ascent + xfont->descent);
00106            }
00107            XftDrawString32(draw, col, xfont, x + width, y, us + start, i - start);
00108          }
00109          width += overall.xOff;
00110        }
00111 
00112        start = i;
00113        if (start < ulen) {
00114          /* Substitute */
00115          wxExtFont sxfont;
00116          sxfont = wxFindAAFont(display, xfont, us[start]);
00117          XftTextExtents32(display, sxfont, us + start, 1, &overall);
00118 
00119          if (!measure) {
00120            if (gc) {
00121              XFillRectangle(display, drawable, gc, x + width, y - sxfont->ascent,
00122                           overall.xOff, sxfont->ascent + sxfont->descent);
00123            }
00124            XftDrawString32(draw, col, sxfont, x + width, y, us + start, 1);
00125          }
00126 
00127          width += overall.xOff;
00128          start++;
00129        } else
00130          break;
00131       }
00132     } else
00133 #endif
00134       {
00135        width = XTextWidth16(font, (XChar2b *)us, ulen);
00136       }
00137   }
00138 
00139   if (!measure) {
00140 #ifdef WX_USE_XFT
00141     if (xfont) {
00142       /* Done above */
00143     } else 
00144 #endif
00145       {
00146        if (image)
00147          XDrawImageString16(display, drawable, gc, x, y, (XChar2b*)us, ulen);
00148        else
00149          XDrawString16(display, drawable, gc, x, y, (XChar2b*)us, ulen);
00150       }
00151   }
00152 
00153   if (us != usbuf)
00154     XtFree((char *)us);
00155 
00156   return width;
00157 }
00158 
00159 #ifdef WX_USE_XFT
00160 # define doDraw(dpy, d, gc, x, y, s, len, i, xf, dw, c) xdoDraw(0, font, dpy, d, gc, x, y, s, len, i, xf, dw, c)
00161 #else
00162 # define doDraw(dpy, d, gc, x, y, s, len, i, xf, dw, c) xdoDraw(0, font, dpy, d, gc, x, y, s, len, i)
00163 #endif
00164 
00165 #ifdef WX_USE_XFT
00166 # define wxXftTextWidth(dpy, font, s, len, xfont) xdoDraw(1, font, dpy, 0, 0, 0, 0, s, len, 0, xfont, 0, 0)
00167 #else
00168 # define wxXftTextWidth(dpy, font, s, len, xfont) xdoDraw(1, font, dpy, 0, 0, 0, 0, s, len, 0) 
00169 #endif
00170 
00171 /*
00172  *     Like DrawImageString, except it takes an additional  "tabs"
00173  *     argument, used to specify what horizontal pixel position to
00174  *     move to when tab characters are present in the string.  If
00175  *     the "tabs" argument is NULL, works exactly like its
00176  *     counterpart.
00177  */
00178 static void
00179 doDrawImageString(display, drawable, gc, x, y, string, length, tabs, font, xfont, line, image, xon, clip, doamps)
00180      Display *display;
00181      Drawable drawable;
00182      GC gc;
00183      int x;
00184      int y;
00185      String string;
00186      int length;
00187      int *tabs;
00188      XFontStruct *font;
00189      wxExtFont xfont;
00190      int line;
00191      int image;
00192      int xon;
00193      Region clip;
00194      int doamps;
00195 {
00196   register char      *p, *ep, *ap;
00197   register int       tx, tab;
00198 #ifdef WX_USE_XFT
00199   XftColor col;
00200   XftDraw *draw;
00201 #endif
00202 
00203   if (!length)
00204     return;
00205 
00206 #ifdef WX_USE_XFT
00207   if (xfont) {
00208     Visual *visual;
00209     Colormap cm;
00210 
00211     cm = wx_default_colormap;
00212     visual = XcmsVisualOfCCC(XcmsCCCOfColormap(display, cm));
00213     
00214     draw = XftDrawCreate(display, drawable, visual, cm);
00215     if (clip)
00216       XftDrawSetClip(draw, clip);
00217 
00218     if (xon < 0) {
00219       col.pixel = 0;
00220       col.color.red = 0xFFFF;
00221       col.color.green = 0xFFFF;
00222       col.color.blue = 0xFFFF;
00223     } else if (xon) {
00224       col.pixel = 0;
00225       col.color.red = 0;
00226       col.color.green = 0;
00227       col.color.blue = 0;
00228     } else {
00229       col.pixel = 0;
00230       col.color.red = 0xA0A0;
00231       col.color.green = 0xA0A0;
00232       col.color.blue = 0xA0A0;
00233     }
00234     col.color.alpha = 0xFFFF;
00235   } else
00236     draw = NULL;
00237 #endif
00238   
00239   tab = tx = 0;
00240   for (p = string; length; )
00241     {
00242       if (tabs)
00243        ep = strnchr(p, '\t', length);
00244       else
00245        ep = NULL;
00246       if (doamps)
00247        ap = strnchr(p, '&', length);
00248       else
00249        ap = NULL;
00250 
00251       if (ep && ap) {
00252        if ((long)ep < (long)ap)
00253          ap = NULL;
00254        else
00255          ep = NULL;
00256       }
00257 
00258       if (ep) {
00259        doDraw(display, drawable, gc, x+tx, y, p, ep - p, image, xfont, draw, &col);
00260        tx = tabs[tab++];
00261        length -= ep - p + 1;
00262        p = ep + 1;
00263       } else if (ap) {
00264        doDraw(display, drawable, gc, x+tx, y, p, ap - p, image, xfont, draw, &col);
00265        tx += wxXftTextWidth(display, font, p, ap - p, xfont);
00266        length -= ap - p + 1;
00267        p = ap + 1;
00268        if (length) {
00269          /* Underline next */
00270          int ww;
00271          int csize;
00272          
00273          csize = leading_utf8_len(p, length);
00274 
00275          ww = wxXftTextWidth(display, font, p, csize, xfont);
00276          doDraw(display, drawable, gc, x+tx, y, p, csize, image, xfont, draw, &col);
00277          if (line && (*p != '&')) {
00278 #ifdef WX_USE_XFT    
00279            if (xfont)
00280              XftDrawRect(draw,&col, x+tx, y+1, ww, 1);
00281            else
00282 #endif
00283              XDrawLine(display, drawable, gc, x+tx, y+1, x+tx+ww, y+1);
00284          }
00285          length -= csize;
00286          tx += ww;
00287          p += csize;
00288        }
00289       } else {
00290        doDraw(display, drawable, gc, x+tx, y, p, length, image, xfont, draw, &col);
00291        break;
00292       }
00293     }
00294 
00295 #ifdef WX_USE_XFT
00296   if (draw)
00297     XftDrawDestroy(draw);
00298 #endif
00299 }
00300 
00301 void
00302 XfwfDrawImageString(display, drawable, gc, x, y, string, length, tabs, fnt, xfnt, xon, clip)
00303      Display *display;
00304      Drawable drawable;
00305      GC gc;
00306      int x;
00307      int y;
00308      String string;
00309      int length;
00310      int *tabs;
00311      XFontStruct *fnt;
00312      wxExtFont xfnt;
00313      int xon;
00314      Region clip;
00315 {
00316   doDrawImageString(display, drawable, gc, x, y, string, length, tabs, fnt, xfnt, 1, 1, xon, clip, 1);
00317 }
00318 
00319 void
00320 XfwfDrawString(display, drawable, gc, x, y, string, length, tabs, fnt, xfnt, xon, line, clip, doamps)
00321      Display *display;
00322      Drawable drawable;
00323      GC gc;
00324      int x;
00325      int y;
00326      String string;
00327      int length;
00328      int *tabs;
00329      XFontStruct *fnt;
00330      wxExtFont xfnt;
00331      int line;
00332      int xon;
00333      Region clip;
00334      int doamps;
00335 {
00336   doDrawImageString(display, drawable, gc, x, y, string, length, tabs, fnt, xfnt, line, 0, xon, clip, doamps);
00337 }
00338 
00339 /*
00340  *     Converts a string list of tabs to an array of tabs
00341  */
00342 int *
00343 XfwfTablist2Tabs(tablist)
00344 char *tablist;
00345 {
00346        register int  *tabs = NULL;
00347        register int  ntabs = 0;
00348 
00349        if (!tablist)
00350               return NULL;
00351        for (;;)
00352        {
00353               /* Skip leading blanks */
00354               while (*tablist && *tablist == ' ') ++tablist;
00355               if (!*tablist) break;
00356 
00357               /* Allocate space for the new tab */
00358               if (ntabs)
00359                      tabs = (int *) XtRealloc( (char *) tabs,
00360                                           (ntabs+1) * sizeof(int));
00361               else
00362                      tabs = (int *) XtMalloc( (ntabs + 1) * sizeof(int));
00363               /* Add it to the list */
00364               tabs[ntabs++] = atoi(tablist);
00365               /* Skip to the next blank */
00366               while (*tablist && *tablist != ' ') ++tablist;
00367        }
00368        return (tabs);
00369 }
00370 
00371 /*
00372  *     Like TextWidth, except it takes an additional  "tabs"
00373  *     argument, used to specify what horizontal pixel position to
00374  *     move to when tab characters are present in the string.  If
00375  *     the "tabs" argument is NULL, works exactly like its
00376  *     counterpart.
00377  */
00378 int
00379 XfwfTextWidth(display, font, xfont, str, length, tabs)
00380      Display *display;
00381      XFontStruct *font;
00382      wxExtFont xfont;
00383      String str;
00384      int length;
00385      int *tabs;
00386 {
00387   register char      *p, *ep, *c = NULL, *pp;
00388   register int       tx, tab, rc, ll;
00389 
00390   if (!length)
00391     return 0;
00392  
00393   p = pp = str;
00394   ll = length;
00395 
00396   while (1) {
00397     ep = strnchr(pp, '&', ll);
00398     if (ep) {
00399       int l = ep - p;
00400       if (!c)
00401        c = XtMalloc(length + 1);
00402       memmove(c, p, l);
00403       memmove(c + l, p + l + 1, length - l); /* gets nul char */
00404       length -= 1;
00405       p = c;
00406       if (length > l) {
00407        pp = c + l + 1; /* Skip next char */
00408        ll = length - (l + 1);
00409       } else {
00410        pp = p;
00411        ll = length;
00412       }
00413     } else
00414       break;
00415   }
00416 
00417   tab = tx = 0;
00418   if (length == 0) {
00419     if (c)
00420       XtFree(c);
00421     return 0;
00422   }
00423   for (; length; ) {
00424     ep = strnchr(p, '\t', length);
00425     if (ep && tabs) {
00426       tx = tabs[tab++];
00427       length -= ep - p + 1;
00428       p = ep + 1;
00429     } else {
00430       rc = wxXftTextWidth(display, font, p, length, xfont);
00431       if (c)
00432        XtFree(c);
00433       if (rc < 0) return rc; else return rc + tx;
00434     }
00435   }
00436 
00437   if (c)
00438     XtFree(c);
00439 
00440   return -1;
00441 }
00442 
00443 /*
00444  *     Like strchr, except has a length limit.
00445  */
00446 char *
00447 strnchr(s, c, n)
00448      char *s;
00449      int c;
00450      int n;
00451 {
00452        while (n--)
00453               if (*s == c) return s; else ++s;
00454        return NULL;
00455 }
00456 
00457 int wx_enough_colors(Screen *s)
00458 {
00459   if (wx_visual_depth > 8)
00460     return 1;
00461   else
00462     return 0;
00463 }
00464 
00465 
00466