home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1993 #3 / NN_1993_3.iso / spool / comp / windows / x / motif / 8780 < prev    next >
Encoding:
Text File  |  1993-01-23  |  15.2 KB  |  485 lines

  1. Path: sparky!uunet!olivea!pagesat!netsys!agate!ucbvax!lilbit.UUCP!prakash
  2. From: prakash@lilbit.UUCP (Prakash Baskaran)
  3. Newsgroups: comp.windows.x.motif
  4. Subject: Re: Text widgets - solution with one stroke "delay"
  5. Message-ID: <9301222210.AA04057@lilbit.tdtech.com>
  6. Date: 22 Jan 93 17:10:10 GMT
  7. Sender: daemon@ucbvax.BERKELEY.EDU
  8. Distribution: inet
  9. Organization: The Internet
  10. Lines: 473
  11.  
  12. > On Jan 21,  5:49pm, Prakash Baskaran wrote:
  13. >
  14. >  2.  As the user moves around in the text widget using arrow keys or
  15. >  mouse, I would like to show the x,y ( column and line number) in the
  16. >  text widget.  Any good ways to do these?
  17.  
  18. Hello:
  19.  
  20. I used to following technique to solve the problem.  It works allright
  21. -execpt- that I get the answer one "stroke" later.  I am using
  22. XmNmotionVerifyCallback to return the x, y position of my cursor. And
  23. I get x,y position for the previous click or movement for my current
  24. movement and the current positions are printed for the next movement.
  25. Obviously I am missing something trivial.  Can any one guess what it
  26. is ?
  27.  
  28. The following is the editor.c of the volume 6, where I have inserted my
  29. code.  Though I get the x,y positions, I guess it would take lots of
  30. time for bigger texts.  
  31.  
  32. prakash
  33.  
  34. _____________________________________________________________________________
  35.  
  36. Prakash Baskaran        
  37. T.D. Technologies, Inc.            12000 Fairhill Rd, #616
  38. 12608 Cedar Rd.                Cleveland, OH 44120
  39. Cleveland Hts, OH 44106            (216) 791 3554
  40. (216) 371 9777
  41.  
  42.         lilbit!prakash@skybridge.scl.cwru.edu
  43.  
  44. Disclaimer:  Ya...  It's all mine.
  45. _____________________________________________________________________________
  46.  
  47.  
  48.  
  49.  
  50. _________
  51. cut here
  52. ____________________________
  53.  
  54. /* Written by Dan Heller.  Copyright 1991, O'Reilly && Associates.
  55.  * This program is freely distributable without licensing fees and
  56.  * is provided without guarantee or warrantee expressed or implied.
  57.  * This program is -not- in the public domain.
  58.  */
  59.  
  60. /* editor.c -- create a full-blown Motif editor application complete
  61.  * with a menubar, facilities to read and write files, text search
  62.  * and replace, clipboard support and so forth.
  63.  */
  64. #include <Xm/Text.h>
  65. #include <Xm/LabelG.h>
  66. #include <Xm/PushBG.h>
  67. #include <Xm/RowColumn.h>
  68. #include <Xm/MainW.h>
  69. #include <Xm/PanedW.h>
  70. #include <Xm/FileSB.h>
  71. #include <X11/Xos.h>
  72. #include <stdio.h>
  73. #include <sys/types.h>
  74. #include <sys/stat.h>
  75.  
  76. Widget text_w, search_w, replace_w, text_output;
  77.  
  78. char  *select_to_beginning ( pos, w )
  79.      XmTextPosition pos;
  80.      Widget w;
  81. {
  82.   char *full_text;
  83.   char *sel_text;
  84.   
  85.   full_text = XmTextGetString ( w );
  86.   sel_text = (char *) malloc ( (pos) * sizeof (char) );
  87.   strncpy ( sel_text, full_text, pos);
  88.   return (sel_text);
  89. }
  90.  
  91. void get_number_of_lines_and_chars (selection, lines, chars, pos)
  92.      char *selection;
  93.      int *lines, *chars, pos;
  94. {
  95.   int i;
  96.   
  97.   for ( i=0; i<pos; i++ )
  98.     {
  99.       if (selection[i] == '\n') 
  100.     {
  101.       (*lines)++;
  102.       (*chars) = 0;
  103.     }
  104.       (*chars)++;
  105.     }
  106. }
  107.  
  108. void cursor_moved (cb,  w, cbs )
  109.      Widget cb, w;
  110.      XmTextVerifyCallbackStruct *cbs;
  111. {
  112.   char *selection;
  113.   int lines = 0, chars = 0;
  114.   
  115.   if (cbs->reason != XmCR_MOVING_INSERT_CURSOR ) return;
  116.  
  117.   selection = select_to_beginning ( cbs->currInsert, w );
  118.   get_number_of_lines_and_chars (selection, &lines, &chars, cbs->currInsert);
  119.   printf ("x:y = %d, %d\n", lines, chars);
  120.   XtFree ( selection );
  121. }
  122.  
  123.  
  124. main(argc, argv)
  125. int argc;
  126. char *argv[];
  127. {
  128.     XtAppContext  app;
  129.     Widget        toplevel, main_w, menubar, pane, rowcol, pb;
  130.     void          file_cb(), cut_paste(), search_cb();
  131.     Arg           args[5];
  132.     XmString      new, save, quit, quit_acc, file, edit, cut,
  133.                   clear, copy, paste, search, next, find, replace;
  134.  
  135.     toplevel = XtVaAppInitialize(&app, "Demos",
  136.         NULL, 0, &argc, argv, NULL, NULL);
  137.     
  138.     main_w = XtVaCreateWidget("main_w",
  139.         xmMainWindowWidgetClass, toplevel, NULL);
  140.  
  141.     /* Create a simple MenuBar that contains three menus */
  142.     file = XmStringCreateSimple("File");
  143.     edit = XmStringCreateSimple("Edit");
  144.     search = XmStringCreateSimple("Search");
  145.     menubar = XmVaCreateSimpleMenuBar(main_w, "menubar",
  146.         XmVaCASCADEBUTTON, file, 'F',
  147.         XmVaCASCADEBUTTON, edit, 'E',
  148.         XmVaCASCADEBUTTON, search, 'S',
  149.         NULL);
  150.     XmStringFree(file);
  151.     XmStringFree(edit);
  152.     XmStringFree(search);
  153.  
  154.     /* First menu is the File menu -- callback is file_cb() */
  155.     new = XmStringCreateSimple("New ...");
  156.     save = XmStringCreateSimple("Save ...");
  157.     quit = XmStringCreateSimple("Quit");
  158.     quit_acc = XmStringCreateSimple("Ctrl-C");
  159.     XmVaCreateSimplePulldownMenu(menubar, "file_menu", 0, file_cb,
  160.         XmVaPUSHBUTTON, new, 'N', NULL, NULL,
  161.         XmVaPUSHBUTTON, save, 'S', NULL, NULL,
  162.         XmVaSEPARATOR,
  163.         XmVaPUSHBUTTON, quit, 'Q', "Ctrl<Key>c", quit_acc,
  164.         NULL);
  165.     XmStringFree(new);
  166.     XmStringFree(save);
  167.     XmStringFree(quit);
  168.     XmStringFree(quit_acc);
  169.  
  170.     /* ...create the "Edit" menu --  callback is cut_paste() */
  171.     cut = XmStringCreateSimple("Cut");      /* create a simple    */
  172.     copy = XmStringCreateSimple("Copy");    /* pulldown menu that */
  173.     clear = XmStringCreateSimple("Clear");  /* has these menu     */
  174.     paste = XmStringCreateSimple("Paste");  /* items in it.       */
  175.     XmVaCreateSimplePulldownMenu(menubar, "edit_menu", 1, cut_paste,
  176.         XmVaPUSHBUTTON, cut, 'C', NULL, NULL,
  177.         XmVaPUSHBUTTON, copy, 'o', NULL, NULL,
  178.         XmVaPUSHBUTTON, paste, 'P', NULL, NULL,
  179.         XmVaSEPARATOR,
  180.         XmVaPUSHBUTTON, clear, 'l', NULL, NULL,
  181.         NULL);
  182.     XmStringFree(cut);
  183.     XmStringFree(copy);
  184.     XmStringFree(paste);
  185.  
  186.     /* create the "Search" menu -- callback is search_cb() */
  187.     next = XmStringCreateSimple("Find Next");
  188.     find = XmStringCreateSimple("Show All");
  189.     replace = XmStringCreateSimple("Replace Text");
  190.     XmVaCreateSimplePulldownMenu(menubar, "search_menu", 2, search_cb,
  191.         XmVaPUSHBUTTON, next, 'F', NULL, NULL,
  192.         XmVaPUSHBUTTON, find, 'S', NULL, NULL,
  193.         XmVaPUSHBUTTON, replace, 'R', NULL, NULL,
  194.         XmVaSEPARATOR,
  195.         XmVaPUSHBUTTON, clear, 'C', NULL, NULL,
  196.         NULL);
  197.     XmStringFree(next);
  198.     XmStringFree(find);
  199.     XmStringFree(replace);
  200.     XmStringFree(clear);
  201.  
  202.     XtManageChild(menubar);
  203.  
  204.     /* create a standard vertical PanedWindow... */
  205.     pane = XtVaCreateWidget("pane",
  206.         xmPanedWindowWidgetClass, main_w, NULL);
  207.  
  208.     /* create horizontal RowColumn inside the pane... */
  209.     rowcol = XtVaCreateWidget("rowcol",
  210.         xmRowColumnWidgetClass, pane,
  211.         XmNorientation,  XmHORIZONTAL,
  212.         XmNpacking,      XmPACK_TIGHT,
  213.         NULL);
  214.     /* Create two Text widgets with Labels... */
  215.     XtVaCreateManagedWidget("Search Pattern:",
  216.         xmLabelGadgetClass, rowcol, NULL);
  217.     search_w = XtVaCreateManagedWidget("search_text",
  218.         xmTextWidgetClass, rowcol, NULL);
  219.     XtVaCreateManagedWidget("     Replace Pattern:",
  220.         xmLabelGadgetClass, rowcol, NULL);
  221.     replace_w = XtVaCreateManagedWidget("replace_text",
  222.         xmTextWidgetClass, rowcol, NULL);
  223.     XtManageChild(rowcol);
  224.  
  225.     text_output = XtVaCreateManagedWidget("text_out",
  226.         xmTextWidgetClass, pane,
  227.         XmNeditable,              False,
  228.         XmNcursorPositionVisible, False,
  229.         XmNshadowThickness,       0,
  230.         XmNsensitive,             False,
  231.         NULL);
  232.  
  233.     XtSetArg(args[0], XmNrows,      10);
  234.     XtSetArg(args[1], XmNcolumns,   80);
  235.     XtSetArg(args[2], XmNeditMode,  XmMULTI_LINE_EDIT);
  236.     text_w = XmCreateScrolledText(pane, "text_w", args, 3);
  237.     XtManageChild(text_w);
  238.  
  239.     XtAddCallback ( text_w, XmNmotionVerifyCallback, cursor_moved, text_w);
  240.     
  241.     XtManageChild(pane);
  242.     XtManageChild(main_w);
  243.  
  244.     XtRealizeWidget(toplevel);
  245.     XtAppMainLoop(app);
  246. }
  247.  
  248. /* callback routine for "Ok" button in FileSelectionDialogs */
  249. void
  250. open_file(dialog, save, cbs)
  251. Widget dialog;
  252. int save;         /* actually, item_no from "new" or "save" */
  253. XmFileSelectionBoxCallbackStruct *cbs;
  254. {
  255.     char buf[BUFSIZ], *filename, *text;
  256.     struct stat statb;
  257.     long len;
  258.     FILE *fp;
  259.  
  260.     if (!XmStringGetLtoR(cbs->value,
  261.         XmSTRING_DEFAULT_CHARSET, &filename))
  262.         return; /* must have been an internal error */
  263.  
  264.     if (!*filename) {
  265.         XtFree(filename);
  266.         XBell(XtDisplay(text_w), 50);
  267.         XmTextSetString(text_output, "Choose a file.");
  268.         return; /* nothing typed */
  269.     }
  270.  
  271.     if (save) {
  272.         if (!(fp = fopen(filename, "w"))) {
  273.             perror(filename);
  274.             sprintf(buf, "Can't save to %s.", filename);
  275.             XmTextSetString(text_output, buf);
  276.             XtFree(filename);
  277.             return;
  278.         }
  279.         /* saving -- get text from Text widget... */
  280.         text = XmTextGetString(text_w);
  281.         len = XmTextGetLastPosition(text_w);
  282.         /* write it to file (check for error) */
  283.         if (fwrite(text, sizeof(char), len, fp) != len)
  284.             strcpy(buf, "Warning: did not write entire file!");
  285.         else {
  286.             /* make sure a newline terminates file */
  287.             if (text[len-1] != '\n')
  288.                 fputc('\n', fp);
  289.             sprintf(buf, "Saved %ld bytes to %s.", len, filename);
  290.         }
  291.     } else {
  292.         /* make sure the file is a regular text file and open it */
  293.         if (stat(filename, &statb) == -1 ||
  294.                 (statb.st_mode & S_IFMT) != S_IFREG ||
  295.                 !(fp = fopen(filename, "r"))) {
  296.             perror(filename);
  297.             sprintf(buf, "Can't read %s.", filename);
  298.             XmTextSetString(text_output, buf);
  299.             XtFree(filename);
  300.             return;
  301.         }
  302.         /* put the contents of the file in the Text widget by
  303.          * allocating enough space for the entire file, reading the
  304.          * file into the space, and using XmTextSetString() to show
  305.          * the file.
  306.          */
  307.         len = statb.st_size;
  308.         if (!(text = XtMalloc((unsigned)(len+1)))) /* +1 for NULL */
  309.             sprintf(buf, "%s: XtMalloc(%ld) failed", len, filename);
  310.         else {
  311.             if (fread(text, sizeof(char), len, fp) != len)
  312.                 sprintf(buf, "Warning: did not read entire file!");
  313.             else
  314.                 sprintf(buf, "Loaded %ld bytes from %s.",
  315.                     len, filename);
  316.             text[len] = 0; /* NULL-terminate */
  317.             XmTextSetString(text_w, text);
  318.         }
  319.     }
  320.     XmTextSetString(text_output, buf); /* purge output message */
  321.  
  322.     /* free all allocated space. */
  323.     XtFree(text);
  324.     XtFree(filename);
  325.     fclose(fp);
  326. }
  327.  
  328. /* a menu item from the "File" pulldown menu was selected */
  329. void
  330. file_cb(w, item_no, cbs)
  331. Widget w;
  332. int item_no;  /* pulldown menu item number */
  333. XmAnyCallbackStruct *cbs;  /* unused here */
  334. {
  335.     static Widget open_dialog, save_dialog;
  336.     Widget        dialog = NULL;
  337.     XmString      str, title;
  338.  
  339.     if (item_no == 2)
  340.         exit(0);
  341.  
  342.     if (item_no == 0 && open_dialog)
  343.         dialog = open_dialog;
  344.     else if (item_no == 1 && save_dialog)
  345.         dialog = save_dialog;
  346.  
  347.     if (dialog) {
  348.         XtManageChild(dialog);
  349.         /* make sure that dialog is raised to top of window stack */
  350.         XMapRaised(XtDisplay(dialog), XtWindow(XtParent(dialog)));
  351.         return;
  352.     }
  353.     dialog = XmCreateFileSelectionDialog(text_w, "Files", NULL, 0);
  354.     XtAddCallback(dialog, XmNcancelCallback, XtUnmanageChild, NULL);
  355.     XtAddCallback(dialog, XmNokCallback, open_file, item_no);
  356.     if (item_no == 0) {
  357.         str = XmStringCreateSimple("Open");
  358.         title = XmStringCreateSimple("Open File");
  359.         open_dialog = dialog;
  360.     } else {
  361.         str = XmStringCreateSimple("Save");
  362.         title = XmStringCreateSimple("Save File");
  363.         save_dialog = dialog;
  364.     }
  365.     XtVaSetValues(dialog,
  366.         XmNokLabelString, str,
  367.         XmNdialogTitle,   title,
  368.         NULL);
  369.     XmStringFree(str);
  370.     XmStringFree(title);
  371.     XtManageChild(dialog);
  372. }
  373.  
  374. /* a menu item from the "Search" pulldown menu was selected */
  375. void
  376. search_cb(w, item_no, cbs)
  377. Widget w;
  378. int item_no;  /* pulldown menu item number */
  379. XmAnyCallbackStruct *cbs;  /* unused here */
  380. {
  381. #define FIND_NEXT 0
  382. #define FIND_ALL  1
  383. #define REPLACE   2
  384. #define CLEAR     3
  385.     char *search_pat, *p, *string, *new_pat, buf[32];
  386.     XmTextPosition pos = 0;
  387.     int len, nfound = 0;
  388.     int search_len, pattern_len;
  389.  
  390.     if (item_no == CLEAR) {
  391.         pos = XmTextGetLastPosition(text_w);
  392.         XmTextSetHighlight(text_w, 0, pos, XmHIGHLIGHT_NORMAL);
  393.         return;
  394.     }
  395.  
  396.     if (!(string = XmTextGetString(text_w)) || !*string) {
  397.         XmTextSetString(text_output, "No text to search.");
  398.         return;
  399.     }
  400.     if (!(search_pat = XmTextGetString(search_w)) || !*search_pat) {
  401.         XmTextSetString(text_output, "Specify a search pattern.");
  402.         XtFree(string);
  403.         return;
  404.     }
  405.  
  406.     new_pat = XmTextGetString(replace_w);
  407.     search_len = strlen(search_pat);
  408.     pattern_len = strlen(new_pat);
  409.  
  410.     /* start searching at current cursor position + 1 */
  411.     if (item_no == FIND_NEXT)
  412.         pos = XmTextGetCursorPosition(text_w) + 1;
  413.     for (p = &string[pos]; p = index(p, *search_pat); p++)
  414.         if (!strncmp(p, search_pat, search_len)) {
  415.             nfound++;
  416.             /* get the position where pattern was found */
  417.             pos = (XmTextPosition)(p-string);
  418.             if (item_no == REPLACE) {
  419.                 /* replace the text position + strlen(new_pat) */
  420.                 XmTextReplace(text_w, pos, pos + search_len, new_pat);
  421.                 /* "string" has changed -- get the new value */
  422.         XtFree(string);
  423.         string = XmTextGetString(text_w);
  424.                 /* continue search -after- replacement */
  425.                 p = &string[pos + pattern_len];
  426.             } else if (item_no == FIND_ALL)
  427.                 XmTextSetHighlight(text_w, pos, pos+search_len,
  428.                     XmHIGHLIGHT_SELECTED);
  429.             else
  430.                 break;
  431.         }
  432.     if (item_no == FIND_NEXT && nfound == 0) {
  433.         /* search from beginning till we've passed "pos" */
  434.         for (p = string; p = index(p, *search_pat); p++)
  435.             if (p - string > pos ||
  436.                     !strncmp(p, search_pat, search_len)) {
  437.                 nfound++;
  438.                 break;
  439.             }
  440.     }
  441.     if (nfound == 0)
  442.         XmTextSetString(text_output, "Pattern not found.");
  443.     else {
  444.         switch (item_no) {
  445.             case FIND_NEXT :
  446.                 pos = (XmTextPosition)(p - string);
  447.                 sprintf(buf, "Pattern found at position %ld.", pos);
  448.                 XmTextSetInsertionPosition(text_w, pos);
  449.                 break;
  450.             case FIND_ALL :
  451.                 sprintf(buf, "Found %d occurrences.", nfound);
  452.                 break;
  453.             case REPLACE :
  454.             default :
  455.                 sprintf(buf, "Made %d replacements.", nfound);
  456.         }
  457.         XmTextSetString(text_output, buf);
  458.     }
  459.     XtFree(string);
  460.     XtFree(search_pat);
  461.     XtFree(new_pat);
  462. }
  463.  
  464. /* the callback routine for the items in the edit menu */
  465. void
  466. cut_paste(widget, num)
  467. Widget widget;  /* the menu item (pushbutton) that was selected */
  468. int num;        /* the menu item number */
  469. {
  470.     Boolean result = True;
  471.  
  472.     switch (num) {
  473.         case 0 : result = XmTextCut(text_w, CurrentTime); break;
  474.         case 1 : result = XmTextCopy(text_w, CurrentTime); break;
  475.         case 2 : result = XmTextPaste(text_w);
  476.         case 3 : XmTextClearSelection(text_w, CurrentTime); break;
  477.     }
  478.     if (result == False)
  479.         XmTextSetString(text_output, "There is no selection.");
  480.     else
  481.         XmTextSetString(text_output, NULL);
  482. }
  483.