home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / x / volume17 / tcl-editor / part06 / mouse.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-03-18  |  11.2 KB  |  426 lines

  1. /* $Header: /nfs/unmvax/faculty/crowley/x/pt/RCS/mouse.c,v 1.9 1992/03/04 17:07:18 crowley Exp crowley $ */
  2.  
  3. #include <stdio.h>
  4. #include "pt.h"
  5. #include <X11/Xatom.h>
  6.  
  7. /* mouse motion constants (for the arrays) */
  8. #define MM_NOMOTION    0
  9. #define MM_NORTH    1
  10. #define MM_EAST        2
  11. #define MM_SOUTH    3
  12. #define MM_WEST        4
  13.  
  14. static int mouseMotionActive = 0;
  15. static int currentDirection;
  16.  
  17. /* variables to handle timing */
  18. static int intervalOn = 0;
  19. static Tk_TimerToken timer_token;
  20. static struct window * mouse_w;
  21.  
  22. /* global mouse motion variables */
  23. struct mmData * mm_data;
  24. int mm_length[5];
  25. int mm_x, mm_y, mm_row, mm_col;
  26. int mm_origin_x[5];
  27. int mm_origin_y[5];
  28. Offset mm_cp = -1;
  29. GC gc;
  30.  
  31. static Tk_Uid BeginSelection;
  32. static Tk_Uid BeginExtend;
  33. static Tk_Uid ExtendSel;
  34. static Tk_Uid EndExtending;
  35. static Tk_Uid BeginMouseMenu1;
  36. static Tk_Uid BeginMouseMenu2;
  37. static Tk_Uid ContinueMouseMenu;
  38. static Tk_Uid CancelMouseMenu;
  39. static Tk_Uid EndMouseMenu;
  40.  
  41. void
  42. InitMouse()
  43. {
  44.     BeginSelection    = Tk_GetUid( "BeginSelection" );
  45.     BeginExtend    = Tk_GetUid( "BeginExtend" );
  46.     ExtendSel    = Tk_GetUid( "ExtendSelection" );
  47.     EndExtending    = Tk_GetUid( "EndExtending" );
  48.     BeginMouseMenu1    = Tk_GetUid( "BeginMouseMenu1" );
  49.     BeginMouseMenu2    = Tk_GetUid( "BeginMouseMenu2" );
  50.     ContinueMouseMenu=Tk_GetUid( "ContinueMouseMenu" );
  51.     CancelMouseMenu    = Tk_GetUid( "CancelMouseMenu" );
  52.     EndMouseMenu    = Tk_GetUid( "EndMouseMenu" );
  53. }
  54.  
  55. static void DrawInitialMenu();
  56.  
  57. static void
  58. DrawMenuString( w, direction )
  59.         struct window * w;
  60.     int direction;
  61. {
  62.     extern Display *MainDisplay;
  63.  
  64.     XDrawImageString( MainDisplay, w->x_window_id, gc,
  65.         mm_origin_x[direction], mm_origin_y[direction],
  66.         mm_data[direction].label, mm_data[direction].length);
  67. }
  68.  
  69. /*ARGSUSED*/
  70. static void
  71. mmTimeout( client_data )
  72.     ClientData client_data;
  73. {
  74.     intervalOn = 0;
  75.     DrawInitialMenu( mouse_w );
  76. }
  77.  
  78. void
  79. Mouse( w, cmd, x, y )
  80.     struct window * w;
  81.     char * cmd;
  82.     int x;
  83.     int y;
  84. {
  85.     extern struct window *selWindow;
  86.     extern Offset selBegin, selEnd;
  87.     extern int selMode;
  88.     extern int menuDelay;
  89.     extern struct mmData mm1Data[];
  90.     extern struct mmData mm2Data[];
  91.     extern Cursor currentCursor;
  92.     extern Display *MainDisplay;
  93.     extern Window MainWindow;
  94.     extern int mouseSpriteMenu;
  95.     extern int menuTolerance;
  96.     extern Tcl_Interp * interp;
  97.     extern char msgBuffer[];
  98.     
  99.     static int lastRow = -1;
  100.     static int lastCol = -1;
  101.  
  102.     int row, col, n;
  103.     Offset cp, beginRowCp;
  104.     /* two abbreviations */
  105.     struct fontDataStruct *font = &(w->font);
  106.     int fid = w->fileId;
  107.     Tk_Uid cmd_uid = Tk_GetUid( cmd );
  108.  
  109.     row = (y - w->topMargin) / font->height;
  110.     col = (x - w->leftMargin) / font->width;
  111.     cp = xyToOffset( w, row, col );
  112.     n = -1;
  113.     beginRowCp = prevLine( fid, cp, &n );
  114.  
  115. if( cmd_uid == BeginSelection ) {
  116.     Offset oldBegin, oldEnd;
  117.  
  118.     lastRow = row;
  119.     lastCol = col;
  120.     if( mouseMotionActive )
  121.         goto restoreCursor;
  122.  
  123.     /* determine the proper selection mode */
  124.     else if( selBegin <= cp && cp <= selEnd && w == selWindow ) {
  125.         if( selMode++ == SELLINE )
  126.             selMode = SELCHAR;
  127.         if( selMode == SELLINE ) {
  128.             sprintf(msgBuffer,"Line %d",LineNumberOfSelection());
  129.             msg( msgBuffer, 1 );
  130.         }
  131.         drawSelection( 1 );
  132.         /* Extend the selection by the selection mode */
  133.         oldBegin = selBegin;
  134.         oldEnd = selEnd;
  135.         modeExtend( selWindow, cp, row, col, beginRowCp );
  136.         /* see if we need to erase the whole selection */
  137.         /* this can happen if you click inside a large, */
  138.         /* drawn-through selection within the double click */
  139.         /* interval. */
  140.         if( oldBegin < selBegin || selEnd < oldEnd )
  141.             drawSelection( 1 );
  142.         if( selMode != SELBLOCK ) {
  143.             int row1, row2, col1, col2;
  144.             Offset begin = selBegin;
  145.             Offset end = selEnd;
  146.             /* restrict begin-end range to what is */
  147.             /* visible on the screen */
  148.             if( begin < selWindow->posTopline )
  149.                 begin = selWindow->posTopline;
  150.             if( end >= selWindow->posBotline )
  151.                 end = selWindow->posBotline - 1;
  152.             if( begin <= end ) {
  153.                 /* at least part of the selection */
  154.                 /* is on the screen */
  155.                 int n = -1;
  156.                 Offset cp = prevLine(selWindow->fileId,
  157.                         begin, &n);
  158.                 OffsetToXY( selWindow, begin, &row1,
  159.                         &col1 );
  160.                 OffsetToXY( selWindow, end, &row2,
  161.                         &col2 );
  162.                 DrawSection( selWindow, cp, row1, col1,
  163.                         row2, col2 );
  164.             }
  165.         } else {
  166.             drawWindow( selWindow );
  167.         }
  168.  
  169.     } else {
  170.         drawSelection( 1 );
  171.         selEnd = selBegin = cp;
  172.         selWindow = w;
  173.         selMode = SELCHAR;
  174.         DrawSection(selWindow, beginRowCp, row, col, row, col);
  175.     }
  176.     AssertSelectionOwnership();
  177.  
  178. } else if( cmd_uid == BeginExtend ) {
  179.     ExtendSelection( cp, row, col, beginRowCp );
  180.  
  181. } else if( cmd_uid == ExtendSel ) {
  182.     if( row == lastRow && col == lastCol )
  183.         return;
  184.     lastRow = row;
  185.     lastCol = col;
  186.  
  187.     /* extend or contract the selection. */
  188.     ExtendSelection( cp, row, col, beginRowCp );
  189.  
  190. } else if( cmd_uid == EndExtending )
  191.     /*EMPTY*/
  192. {
  193.     /* nothing to do on end selection */
  194.  
  195. } else if( cmd_uid == BeginMouseMenu1 ) {
  196.     mm_data = mm1Data;
  197.     goto BeginEitherMenu;
  198.  
  199. } else if( cmd_uid == BeginMouseMenu2 ) {
  200.     mm_data = mm2Data;
  201.  
  202. BeginEitherMenu:
  203.     /* remember the important parameters */
  204.     mm_x = x;
  205.     mm_y = y;
  206.     mm_row = row;
  207.     mm_col = col;
  208.     mm_cp = cp;
  209.     mouseMotionActive = 1;
  210.     currentDirection = MM_NOMOTION;
  211.     /* record all the label lengths */
  212.     for( n = 0; n < 5; ++n )
  213.         mm_length[n] = strlen(mm_data[n].label);
  214.  
  215.     if( mouseSpriteMenu ) {
  216.         XDefineCursor( MainDisplay, Tk_WindowId(w->tk_toplevel),
  217.                 mm_data[currentDirection].cursor );
  218.     } else {
  219.         intervalOn = 1;
  220.         mouse_w = w;
  221.         timer_token = Tk_CreateTimerHandler( menuDelay, mmTimeout, 0 );
  222.     }
  223.  
  224. } else if( cmd_uid == ContinueMouseMenu ) {
  225.     int newDirection;
  226.  
  227.     x -= mm_x;
  228.     y -= mm_y;
  229.     /* make it insensitive to small changes */
  230.     if( abs(x) < menuTolerance && abs(y) < menuTolerance )
  231.         newDirection = MM_NOMOTION;
  232.     else if( x > y ) {
  233.         if( x > -y )
  234.             newDirection = MM_EAST;
  235.         else
  236.             newDirection = MM_NORTH;
  237.     } else {
  238.         if( x > -y )
  239.             newDirection = MM_SOUTH;
  240.         else
  241.             newDirection = MM_WEST;
  242.     }
  243.     if( mouseMotionActive && (currentDirection != newDirection) ) {
  244.         if( mouseSpriteMenu ) {
  245.             XDefineCursor( MainDisplay, Tk_WindowId(w->tk_toplevel),
  246.                     mm_data[newDirection].cursor );
  247.         } else if( !intervalOn ) {
  248.             /* unhighlight the old item */
  249.             gc = font->gc_normal;
  250.             DrawMenuString( w, currentDirection );
  251.             /* highlight the new item */
  252.             gc = font->gc_selected;
  253.             DrawMenuString( w, newDirection );
  254.         }
  255.     }
  256.     currentDirection = newDirection;
  257.  
  258. } else if( cmd_uid == EndMouseMenu ) {
  259.     if( mouseMotionActive ) {
  260.         int row1, row2;
  261.         char * cmd = mm_data[currentDirection].tcl_command;
  262.         if( striccmp(cmd,"ExtendSelection") != 0 ) {
  263.             (void)ExecTclCommand( cmd );
  264.         } else
  265.             /* extend or contract the selection */
  266.             ExtendSelection( cp, row, col, beginRowCp );
  267. restoreCursor:
  268.         if( mouseSpriteMenu ) {
  269.             XDefineCursor( MainDisplay, Tk_WindowId(w->tk_toplevel),
  270.                             currentCursor);
  271.         } else {
  272.             /* redraw the text we wrote over */
  273.             if( intervalOn ) {
  274.                 intervalOn = 0;
  275.                 Tk_DeleteTimerHandler( timer_token );
  276.             } else {
  277.                 if( (row1 = mm_row - 2) < 0 )
  278.                     row1 = 0;
  279.                 row2 = mm_row + 2;
  280.                 drawWindowFast( w, row1, row2, 0, w->nCols );
  281.             }
  282.         }
  283.         mouseMotionActive = 0;
  284.     }
  285. } else if( cmd_uid == CancelMouseMenu ) {
  286.     goto restoreCursor;
  287. } else {    /* must be a Point command */
  288.     printf("Mouse command `%s' not understood\n", cmd );
  289. }
  290. }
  291.  
  292. static void
  293. DrawInitialMenu( w )
  294.         struct window * w;
  295. {
  296.     extern Display *MainDisplay;
  297.  
  298.     int col9;
  299.     /* two abbreviations */
  300.     struct fontDataStruct *font = &(w->font);
  301.  
  302.     /* write out the circular menu items */
  303.  
  304.     /* first figure out where everything goes */
  305.     mm_origin_y[MM_NOMOTION] = w->topMargin + font->ascent
  306.                         + mm_row * font->height;
  307.     mm_origin_y[MM_WEST] = mm_origin_y[MM_NOMOTION];
  308.     mm_origin_y[MM_EAST] = mm_origin_y[MM_NOMOTION];
  309.     mm_origin_y[MM_NORTH] = mm_origin_y[MM_NOMOTION] - font->height - 2;
  310.     mm_origin_y[MM_SOUTH] = mm_origin_y[MM_NOMOTION] + font->height + 2;
  311.  
  312.     col9 = mm_col - mm_length[MM_NOMOTION]/2;
  313.     mm_origin_x[MM_NOMOTION] = w->leftMargin + col9 * font->width;
  314.     mm_origin_x[MM_WEST] = mm_origin_x[MM_NOMOTION]
  315.                 - mm_length[MM_WEST] * font->width - 2;
  316.     mm_origin_x[MM_EAST] = mm_origin_x[MM_NOMOTION]
  317.                 + mm_length[MM_NOMOTION] * font->width + 2;
  318.     col9 = mm_col - mm_length[MM_NORTH]/2;
  319.     mm_origin_x[MM_NORTH] = w->leftMargin + col9 * font->width;
  320.     col9 = mm_col - mm_length[MM_SOUTH]/2;
  321.     mm_origin_x[MM_SOUTH] = w->leftMargin + col9 * font->width;
  322.  
  323.     /* draw rectangles around the strings */
  324.     gc = (w->font).gc_normal;
  325.     XDrawRectangle(MainDisplay, w->x_window_id, gc,
  326.         mm_origin_x[MM_NOMOTION] - 1,
  327.         mm_origin_y[MM_NOMOTION] - font->ascent - 1,
  328.         font->width * mm_length[MM_NOMOTION] + 2,
  329.         font->height + 2);
  330.     XDrawRectangle(MainDisplay, w->x_window_id, gc,
  331.         mm_origin_x[MM_NORTH] - 1,
  332.         mm_origin_y[MM_NORTH] - font->ascent - 1,
  333.         font->width * mm_length[MM_NORTH] + 2,
  334.         font->height + 2);
  335.     XDrawRectangle(MainDisplay, w->x_window_id, gc,
  336.         mm_origin_x[MM_EAST] - 1,
  337.         mm_origin_y[MM_EAST] - font->ascent - 1,
  338.         font->width * mm_length[MM_EAST] + 2,
  339.         font->height + 2);
  340.     XDrawRectangle(MainDisplay, w->x_window_id, gc,
  341.         mm_origin_x[MM_SOUTH] - 1,
  342.         mm_origin_y[MM_SOUTH] - font->ascent - 1,
  343.         font->width * mm_length[MM_SOUTH] + 2,
  344.         font->height + 2);
  345.     XDrawRectangle(MainDisplay, w->x_window_id, gc,
  346.         mm_origin_x[MM_WEST] - 1,
  347.         mm_origin_y[MM_WEST] - font->ascent - 1,
  348.         font->width * mm_length[MM_WEST] + 2,
  349.         font->height + 2);
  350.     /* now write the strings */
  351.     gc = (w->font).gc_normal;
  352.     DrawMenuString( w, MM_NOMOTION );
  353.     DrawMenuString( w, MM_NORTH );
  354.     DrawMenuString( w, MM_WEST );
  355.     DrawMenuString( w, MM_SOUTH );
  356.     DrawMenuString( w, MM_EAST );
  357.     /* this one will be written twice */
  358.     gc = (w->font).gc_selected;
  359.     DrawMenuString( w, currentDirection );
  360. }
  361.  
  362. /* global variables for making cursor from pixmaps */
  363. static Pixmap pixmap;
  364. static GC mouse_gc;
  365. static XColor black, white;
  366. static int ascent;
  367. extern Display *MainDisplay;
  368.  
  369. static void
  370. MakeCursors( mm_data )
  371.     struct mmData * mm_data;
  372. {
  373.  
  374.     int i;
  375.  
  376.     for( i = 0; i < 5; ++i ) {
  377.         mm_data[i].length = strlen( mm_data[i].label );
  378.         if( mm_data[i].length > 0 ) {
  379.             XDrawImageString( MainDisplay, pixmap, mouse_gc, 2,
  380.                 ascent+2, mm_data[i].label, mm_data[i].length );
  381.             mm_data[i].cursor = XCreatePixmapCursor( MainDisplay,
  382.                 pixmap, None, &white, &black, 1, 1 );
  383.         } else
  384.             mm_data[i].cursor = NULL;
  385.     }
  386. }
  387.  
  388. void
  389. MakeMouseMenuCursors()
  390. {
  391.     extern Pixel ptWhitePixel, ptBlackPixel;
  392.     extern struct mmData mm1Data[];
  393.     extern struct mmData mm2Data[];
  394.     extern char * mouseMenuFont;
  395.  
  396.     XFontStruct *fontInfo;
  397.  
  398.     /* set up the pixmap and stuff to create the cursors */
  399.     pixmap = XCreatePixmap( MainDisplay, DefaultRootWindow(MainDisplay),
  400.             28, 17, 1 );
  401.     fontInfo = XLoadQueryFont( MainDisplay, mouseMenuFont );
  402.     if( fontInfo == NULL )
  403.         /* we assume every X server has a "fixed" font */
  404.         fontInfo = XLoadQueryFont( MainDisplay, "fixed" );
  405.     ascent = fontInfo->ascent;
  406.     mouse_gc = XCreateGC(MainDisplay, pixmap, 0, NULL);
  407.     XSetFont(MainDisplay, mouse_gc, fontInfo->fid);
  408.  
  409.     /* clear out the edges of the pixmap */
  410.     XFillRectangle( MainDisplay, pixmap, mouse_gc, 0, 0, 28, 17 );
  411.     black.pixel = ptBlackPixel;
  412.     ptBlackPixel = BlackPixel(MainDisplay, MainDisplay->default_screen);
  413.     XQueryColor( MainDisplay, DefaultColormap(MainDisplay,
  414.                 DefaultScreen(MainDisplay)), &black);
  415.     white.pixel = ptWhitePixel;
  416.     XQueryColor( MainDisplay, DefaultColormap(MainDisplay,
  417.                 DefaultScreen(MainDisplay)), &white);
  418.  
  419.     MakeCursors( mm1Data );
  420.     MakeCursors( mm2Data ); 
  421.  
  422.     XFreeGC( MainDisplay, mouse_gc );
  423.     XFreePixmap( MainDisplay, pixmap );
  424. }
  425.  
  426.