home *** CD-ROM | disk | FTP | other *** search
/ Enigma Amiga Life 110 / EnigmaAmiga110CD.iso / indispensabili / utility / apdf / xpdf-0.80 / ltk / ltklist.cc < prev    next >
C/C++ Source or Header  |  1998-11-27  |  8KB  |  314 lines

  1. //========================================================================
  2. //
  3. // LTKList.cc
  4. //
  5. // Copyright 1997 Derek B. Noonburg
  6. //
  7. //========================================================================
  8.  
  9. #ifdef __GNUC__
  10. #pragma implementation
  11. #endif
  12.  
  13. #include <stdlib.h>
  14. #include <stdarg.h>
  15. #include <stddef.h>
  16. #include <X11/Xlib.h>
  17. #include <X11/Xutil.h>
  18. #include "gmem.h"
  19. #include "LTKList.h"
  20.  
  21. #define horizBorder 4
  22. #define vertBorder  2
  23.  
  24. LTKList::LTKList(char *name1, int widgetNum1,
  25.          int minWidth1, int minLines1,
  26.          GBool allowSelection1, char *fontName1):
  27.     LTKWidget(name1, widgetNum1) {
  28.   minWidth = minWidth1;
  29.   minLines = minLines1;
  30.   allowSelection = allowSelection1;
  31.   clickCbk = NULL;
  32.   dblClickCbk = NULL;
  33.   text = NULL;
  34.   numLines = 0;
  35.   textSize = 0;
  36.   topLine = 0;
  37.   horizOffset = 0;
  38.   selection = -1;
  39.   fontName = fontName1;
  40.   fontStruct = NULL;
  41.   textGC = None;
  42. }
  43.  
  44. LTKList::~LTKList() {
  45.   int i;
  46.  
  47.   for (i = 0; i < numLines; ++i)
  48.     delete text[i];
  49.   gfree(text);
  50.   if (fontName && fontStruct) {
  51.     XFreeFont(getDisplay(), fontStruct);
  52.     XFreeGC(getDisplay(), textGC);
  53.   }
  54. }
  55.  
  56. long LTKList::getEventMask() {
  57.   return LTKWidget::getEventMask() | ButtonPressMask | ButtonReleaseMask;
  58. }
  59.  
  60. void LTKList::insertLine(int line, char *s) {
  61.   XCharStruct extents;
  62.   int direction, ascent, descent;
  63.   int i;
  64.  
  65.   if (line <= numLines) {
  66.     if (numLines >= textSize) {
  67.       textSize += 32;
  68.       text = (GString **)grealloc(text, textSize * sizeof(GString *));
  69.     }
  70.     for (i = numLines-1; i >= line; --i)
  71.       text[i+1] = text[i];
  72.     text[line] = new GString(s);
  73.     ++numLines;
  74.     if (getXWindow() != None) {
  75.       XTextExtents(fontStruct, text[line]->getCString(),
  76.            text[line]->getLength(),
  77.            &direction, &ascent, &descent, &extents);
  78.       if (extents.width + 2*horizBorder > maxWidth)
  79.     maxWidth = extents.width + 2*horizBorder;
  80.       redrawBelow(line);
  81.     }
  82.   }
  83. }
  84.  
  85. void LTKList::replaceLine(int line, char *s) {
  86.   XCharStruct extents;
  87.   int direction, ascent, descent;
  88.  
  89.   if (line < numLines) {
  90.     delete text[line];
  91.     text[line] = new GString(s);
  92.     if (getXWindow() != None) {
  93.       XTextExtents(fontStruct, text[line]->getCString(),
  94.            text[line]->getLength(),
  95.            &direction, &ascent, &descent, &extents);
  96.       if (extents.width + 2*horizBorder > maxWidth)
  97.     maxWidth = extents.width + 2*horizBorder;
  98.       redrawLine(line);
  99.     }
  100.   }
  101. }
  102.  
  103. //~ this should reduce size of text array
  104. void LTKList::deleteLine(int line) {
  105.   int i;
  106.  
  107.   if (line < numLines) {
  108.     delete text[line];
  109.     for (i = line; i < numLines - 1; ++i)
  110.       text[i] = text[i+1];
  111.     text[numLines-1] = NULL;
  112.     --numLines;
  113.     if (selection == line) {
  114.       xorSelection();
  115.       selection = -1;
  116.     }
  117.     if (getXWindow() != None)
  118.       redrawBelow(line);
  119.   }
  120. }
  121.  
  122. void LTKList::deleteAll() {
  123.   int line;
  124.  
  125.   for (line = 0; line < numLines; ++line)
  126.     delete text[line];
  127.   delete text;
  128.   text = NULL;
  129.   numLines = 0;
  130.   textSize = 0;
  131.   topLine = 0;
  132.   horizOffset = 0;
  133.   selection = -1;
  134.   if (getXWindow() != None) {
  135.     maxWidth = 0;
  136.     redraw();
  137.   }
  138. }
  139.  
  140. void LTKList::setSelection(int line) {
  141.   if (allowSelection) {
  142.     xorSelection();
  143.     selection = line;
  144.     xorSelection();
  145.   }
  146. }
  147.  
  148. int LTKList::getDisplayedLines() {
  149.   return (height - 2 * vertBorder) / textHeight;
  150. }
  151.  
  152. void LTKList::scrollTo(int line, int horiz) {
  153.   GBool changed;
  154.  
  155.   changed = gFalse;
  156.   if (line != topLine && line < numLines) {
  157.     topLine = line;
  158.     changed = gTrue;
  159.   }
  160.   if (horiz != horizOffset) {
  161.     horizOffset = horiz;
  162.     changed = gTrue;
  163.   }
  164.   //~ blit-scroll if possible
  165.   if (changed && getXWindow() != None)
  166.     redraw();
  167. }
  168.  
  169. void LTKList::makeVisible(int line) {
  170.   int dispLines;
  171.  
  172.   dispLines = getDisplayedLines();
  173.   if (line < topLine)
  174.     scrollTo(line, horizOffset);
  175.   else if (line >= topLine + dispLines)
  176.     scrollTo(line - dispLines + 1, horizOffset);
  177. }
  178.  
  179. void LTKList::layout1() {
  180.   XGCValues gcValues;
  181.   XCharStruct extents;
  182.   int direction, ascent, descent;
  183.   int line;
  184.  
  185.   // get/create GCs
  186.   if (textGC == None) {
  187.     if (fontName &&
  188.     (fontStruct = XLoadQueryFont(getDisplay(), fontName))) {
  189.       XGetGCValues(getDisplay(), getFgGC(),
  190.            GCForeground | GCBackground | GCGraphicsExposures,
  191.            &gcValues);
  192.       gcValues.font = fontStruct->fid;
  193.       textGC = XCreateGC(getDisplay(), parent->getXWindow(),
  194.              GCForeground | GCBackground | GCGraphicsExposures |
  195.              GCFont,
  196.              &gcValues);
  197.     } else {
  198.       fontName = NULL;
  199.       fontStruct = parent->getXFontStruct();
  200.       textGC = getFgGC();
  201.     }
  202.   }
  203.  
  204.   // compute max line width
  205.   maxWidth = 0;
  206.   for (line = 0; line < numLines; ++line) {
  207.     XTextExtents(fontStruct, text[line]->getCString(), text[line]->getLength(),
  208.          &direction, &ascent, &descent, &extents);
  209.     if (extents.width > maxWidth)
  210.       maxWidth = extents.width;
  211.   }
  212.   maxWidth += 2 * horizBorder;
  213.  
  214.   // text parameters
  215.   textHeight = fontStruct->ascent + fontStruct->descent;
  216.   textBase = fontStruct->ascent;
  217.  
  218.   // compute min width/height
  219.   width = minWidth + 2 * horizBorder;
  220.   height = minLines * textHeight + 2 * vertBorder;
  221. }
  222.  
  223. void LTKList::layout3() {
  224.   XRectangle rect;
  225.  
  226.   LTKWidget::layout3();
  227.   rect.x = horizBorder;
  228.   rect.y = vertBorder;
  229.   rect.width = width - 2 * horizBorder;
  230.   rect.height = height - 2 * vertBorder;
  231.   XSetClipRectangles(getDisplay(), textGC, 0, 0, &rect, 1, Unsorted);
  232. }
  233.  
  234. void LTKList::redraw() {
  235.   int y;
  236.   int i;
  237.  
  238.   XFillRectangle(getDisplay(), xwin, getBgGC(), 0, 0, width, height);
  239.   y = vertBorder;
  240.   for (i = topLine;
  241.        i < numLines && y < height - vertBorder;
  242.        ++i, y += textHeight) {
  243.     XDrawString(getDisplay(), xwin, textGC,
  244.         horizBorder - horizOffset, y + textBase,
  245.         text[i]->getCString(), text[i]->getLength());
  246.   }
  247.   xorSelection();
  248. }
  249.  
  250. void LTKList::redrawLine(int line) {
  251.   int y;
  252.  
  253.   if (line < topLine ||
  254.       line >= topLine +
  255.               (height - 2*vertBorder + textHeight - 1) / textHeight)
  256.     return;
  257.   y = vertBorder + (line - topLine) * textHeight;
  258.   XFillRectangle(getDisplay(), xwin, getBgGC(),
  259.          horizBorder, y, width - 2*horizBorder, textHeight);
  260.   XDrawString(getDisplay(), xwin, textGC,
  261.           horizBorder - horizOffset, y + textBase,
  262.           text[line]->getCString(), text[line]->getLength());
  263.   if (selection == line)
  264.     xorSelection();
  265. }
  266.  
  267. void LTKList::redrawBelow(int line) {
  268.   int y;
  269.   int i;
  270.  
  271.   if (line >= topLine +
  272.               (height - 2*vertBorder + textHeight - 1) / textHeight)
  273.     return;
  274.   y = vertBorder + (line - topLine) * textHeight;
  275.   XFillRectangle(getDisplay(), xwin, getBgGC(),
  276.          horizBorder, y,
  277.          width - 2*horizBorder, height - vertBorder - y);
  278.   for (i = line;
  279.        i < numLines && y < height - vertBorder;
  280.        ++i, y += textHeight) {
  281.     XDrawString(getDisplay(), xwin, textGC,
  282.         horizBorder - horizOffset, y + textBase,
  283.         text[i]->getCString(), text[i]->getLength());
  284.   }
  285.   if (selection >= line)
  286.     xorSelection();
  287. }
  288.  
  289. void LTKList::xorSelection() {
  290.   if (selection < topLine ||
  291.       selection >= topLine +
  292.                    (height - 2*vertBorder + textHeight - 1) / textHeight)
  293.     return;
  294.   y = vertBorder + (selection - topLine) * textHeight;
  295.   XFillRectangle(getDisplay(), xwin, getXorGC(),
  296.          horizBorder, y, width - 2*horizBorder, textHeight);
  297. }
  298.  
  299. void LTKList::buttonPress(int mx, int my, int button, GBool dblClick) {
  300.   int line;
  301.  
  302.   line = topLine + (my - vertBorder) / textHeight;
  303.   if (line < numLines) {
  304.     setSelection(line);
  305.     if (dblClick) {
  306.       if (dblClickCbk)
  307.     (*dblClickCbk)(this, widgetNum, selection);
  308.     } else {
  309.       if (clickCbk)
  310.     (*clickCbk)(this, widgetNum, selection);
  311.     }
  312.   }
  313. }
  314.