home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #31 / NN_1992_31.iso / spool / comp / sys / next / bugs / 6 < prev    next >
Encoding:
Text File  |  1992-12-27  |  10.4 KB  |  409 lines

  1. Newsgroups: comp.sys.next.bugs
  2. Path: sparky!uunet!elroy.jpl.nasa.gov!sdd.hp.com!spool.mu.edu!umn.edu!csus.edu!netcom.com!netcomsv!yamanote!gordie
  3. From: gordie@cyclesoft.com (Gordie Freedman)
  4. Subject: Bug in subclassed Text object in scrollview? (Long)
  5. Message-ID: <1992Dec27.201506.8391@netcom.com>
  6. Keywords: text subclass appkit.555 scrollview font
  7. Sender: gordie@netcom.com
  8. Reply-To: gordie@cyclesoft.com
  9. Organization: Dolphin Software
  10. Date: Sun, 27 Dec 1992 20:15:06 GMT
  11. Lines: 396
  12.  
  13. Hi,
  14.  
  15. (On a NeXTStation Color (non turbo) running 3.0, 16/400, 21" color monitor.)
  16.  
  17. I have a problem with subclassing the Text object, and than replacing the Text  
  18. object in a scrollview with my custom subclass, as explained in NeXTanswer  
  19. appkit.555.
  20.  
  21. For the most part it works as advertised, however if I read ascii into the Text  
  22. object (after setting it to MonoFont:YES), and than try to change the font from  
  23. the Font Panel - the old text (with the old font) is not cleared, and the new  
  24. text (with the new font) is painted over it. Not a pretty sight. As well, I  
  25. have to do some mucking around when reading in a new document into the Text,  
  26. otherwise it does the same thing (paints the new text over the old instead of  
  27. replacing it).
  28.  
  29. I don't have these problems with the same code/nib keeping the original text  
  30. object.
  31.  
  32. In the nib, I have a Controller object (which inherits from Object, and doesn't  
  33. really do a whole lot in this example). The controller is the delegate for the  
  34. Application, and there is one window (besides the main menu). The Controller  
  35. has three outlets related to the window, an id for the window itself (set in  
  36. the nib), an id for the scrollview (set in the nib), and an id for the text  
  37. object (set in appDidInit: after getting the new custom Text object). The  
  38. controller is also set to be the delegate of the window from IB, and  
  39. programmatically set to be the delegate of the subclassed Text object.
  40.  
  41. I don't know if I am doing something wrong here (possibly with font stuff, see  
  42. code example), or if there is a problem with the Text object that this usage  
  43. uncovers.
  44.  
  45. Here's the code in the implementation of the Controller object:
  46.  
  47. ------------------------------------------------
  48.  
  49. #import "Controller.h"
  50. #import <strings.h>
  51. #include <sys/types.h>
  52. #include <sys/uio.h>
  53. #include <sys/file.h>
  54.  
  55. //
  56. // This app illustrates a problem using the code from NeXTAnswers
  57. // appkit.555 - replacing a Text object in a ScrollView with a custom
  58. // Text object (in this case a PText object - see below). 
  59. //
  60.  
  61. // This app is for NeXTSTEP 3.0 using all standard dev tools/etc., and
  62. // can be built using project builder.
  63.  
  64. // The Controller is set up as the delegate for the Window with the 
  65. // ScrollView and the Text, and is also set as the delegate for the
  66. // Application object via IB.
  67.  
  68. // To see the problem, launch the App, use the Display menu item to
  69. // display the Text window, than use the Open... menu item to open a file.
  70. // Select a file that is ascii (not rich text). Bring up the Font panel
  71. // (Command-t), set focus in the Text in the Text Window, than select
  72. // a different font from the font panel. The result will be that the
  73. // old text is left in the window and the new text is painted over it.
  74.  
  75. // Note that this does not happen with Rich Text, although without the code
  76. // in [Controller clearText] reading in a new document has similar problems.
  77.  
  78. // Questions:
  79. //
  80. // 1. Why doesn't setting the font from the Font Panel work correctly on
  81. //    non-rich text?
  82. //
  83. // 2. Why is the "clearText" method needed when reading in new text?
  84. //
  85.  
  86. /*---------------------------------------------------------------------------*/
  87.  
  88. // This is the subclassed PText - it doesn't do anything now,
  89. // but would be used to specialize methods such as addToPageSetup
  90. // When it replaces the standard text object in a ScrollView, modifying
  91. // the font for a MonoFont document does not work correctly. It paints
  92. // the new text (with the new font setting) on top of the previous text,
  93. // rather than replacing the old text. When this program is run without
  94. // replacing the Text object with the PText, the problems go away.
  95.  
  96. @interface PText: Text
  97. {
  98. }
  99.  
  100. @end
  101.  
  102. @implementation PText
  103.  
  104. - addToPageSetup
  105. {    
  106.     [super addToPageSetup];
  107.         
  108.     return self;
  109.  
  110. }
  111.  
  112. @end
  113.  
  114.  
  115. // Some private methods for the Controller object.
  116.  
  117. @interface Controller (Private)
  118.  
  119. - clearText;
  120. - (BOOL) openTextFile:(const char*) fileName;
  121. - doit:(const char*) name;
  122.  
  123. @end
  124.  
  125. @implementation Controller (Private)
  126.  
  127. // This method is needed when reading in new text from a stream -
  128. // Without it, the old text is still present in the window, and 
  129. // the new text is painted over it. This is not needed when a standard
  130. // Text object is used.
  131.  
  132. - clearText
  133. {
  134.     NXRect r;
  135.     [text getFrame:&r];
  136.     
  137.     [text setTextGray:NX_WHITE];
  138.     [text display];
  139.     [text setTextGray:NX_BLACK];
  140.     [text renewRuns:NULL text:"" frame:&r tag:[text tag]];    
  141.     return self;
  142. }
  143.  
  144. #define    BUF_SIZE    5
  145. #define    RTF_SIG        "{\\rtf"
  146. #define NUM_TABS    10
  147. static char buf[BUF_SIZE];
  148.  
  149. // Method to open a text file. Checks to see if it is rich text,
  150. // and if so, sets MonoFont:NO and reads in as such. Otherwise, sets
  151. // MonoFont:YES and reads in ascii text.
  152. //
  153. - (BOOL) openTextFile:(const char*) fileName
  154. {
  155.     int        fd ;
  156.     NXStream  *stream ;
  157.  
  158.     fd = open (fileName, O_RDONLY) ;
  159.     if (fd == 0)
  160.     {
  161.         return NO ;
  162.     }
  163.     stream = NXOpenFile (fd, NX_READONLY) ;
  164.     if (stream == 0)
  165.     {
  166.         close (fd) ;
  167.         return NO ;
  168.     }
  169.  
  170.     // read in the beginning of the text to see if rtf. Seek back to
  171.     // the beginning of the file before reading from the stream.
  172.     
  173.     buf [0] = '\0';
  174.     read (fd, buf, BUF_SIZE);
  175.     lseek (fd, 0, L_SET);
  176.     [self clearText];
  177.     if (!strncmp (buf, RTF_SIG, BUF_SIZE))
  178.     {
  179.         [text setMonoFont:NO];
  180.         [text readRichText:stream];
  181.     }
  182.     else
  183.     {
  184.         [text setMonoFont:YES];
  185.         [text readText:stream];        
  186.         // Set whatever font the user last selected in Font Panel
  187. //        [text setFont:font];
  188.     }
  189.     NXClose (stream);
  190.     close (fd);
  191.     return YES;
  192. }
  193.  
  194. // 
  195. // Method to find out if the text file is rtfd or not. Gets the
  196. // text into the PText object via openTextFile (if not rtfd), or
  197. // openRTFDFrom (if rtfd).
  198. //
  199. - doit:(const char*) name
  200. {
  201.     id newFont;
  202.     const char* type;
  203.     NXSize oldSize;
  204.     
  205.     // Save the old size to see if the paper size changes
  206.     oldSize.width = pageSize.width;
  207.     oldSize.height = pageSize.height;
  208.     
  209.     if ((!name) || (*name == '\0'))
  210.     {
  211.         return nil;
  212.     }
  213.  
  214.     // Get whatever font is in the font panel, free previous
  215.     // font if not the same ...    
  216.     newFont = [fontPanel panelConvertFont:font];
  217.     if (font != newFont)
  218.     {
  219.         [font free];
  220.         font = newFont;
  221.     }
  222.  
  223.     // Get the type of the file
  224.     if ((type = rindex (name, '.')) == NULL)
  225.     {
  226.         type = "";
  227.     }
  228.     else
  229.     {
  230.         type ++;
  231.     }
  232.     if (!strcmp (type, "rtfd"))
  233.     {
  234.         [text setMonoFont:NO];
  235.         [self clearText];
  236.         if ([text openRTFDFrom:name] != NX_RTFDErrorNone)
  237.         {
  238.             return nil;
  239.         }
  240.     }
  241.     else
  242.     {
  243.         if ([self openTextFile:name] == NO)
  244.         {
  245.             return nil;
  246.         }
  247.     }
  248.     
  249.     // If the paper size changed, resize the window
  250.     if (pageSize.width != oldSize.width)
  251.     {
  252.         NXSize size;
  253.         [scrollView getContentSize:&size];
  254.         [textWindow sizeWindow:pageSize.width+NX_SCROLLERWIDTH
  255.             :size.height];
  256.     }
  257.     // Set the window title and return
  258.     [textWindow setTitle:name];
  259.     return self;
  260. }
  261.  
  262. @end
  263.  
  264. @implementation Controller
  265.  
  266. //
  267. // appDidInit - gets size from old text object, and sets up
  268. // new PText object in its place in the scrollview. Makes the
  269. // Controller the delegate of the PText to get the textDidRead msg.
  270. //
  271. - appDidInit:sender
  272. {
  273.     id    stdText;
  274.     NXRect    r;
  275.  
  276.     // Get a font opanel and an initial font
  277.     fontPanel = [FontPanel new];
  278.     font = [Font newFont:"Helvetica" size:12.0];
  279.     
  280.     // Straight out of appkit.555, only the names were
  281.     // changed to protect the innocent    
  282.     
  283.     // If this code is skipped, everything works as advertised ...
  284.     // If skipping it, have to do:
  285.     // [text setDelegate:self];
  286.     
  287.     stdText = [scrollView docView];
  288.     [stdText getFrame:&r];
  289.     
  290.     [scrollView setVertScrollerRequired:YES];
  291.     [scrollView setHorizScrollerRequired:NO];
  292.     [scrollView setDynamicScrolling:YES]; 
  293.     
  294.     text = [[PText alloc] initFrame:&r];
  295.     [text moveTo:0.0:0.0];
  296.     [text notifyAncestorWhenFrameChanged: YES];
  297.     [text setVertResizable:YES];
  298.     [text setSelectable:YES];
  299.     [text setEditable: YES];
  300.     [text setAutosizing:NX_WIDTHSIZABLE];
  301.     [text setMinSize:&r.size];
  302.     r.size.height = 1.0e30;
  303.     [text setMaxSize:&r.size];
  304.     [scrollView setDocView:text];
  305.     [stdText free];
  306.  
  307.     // Set oursleves as the delegate for the new PText object
  308.     [text setDelegate:self];
  309.  
  310.     return self;
  311. }
  312.  
  313.  
  314. // Invoked in response to user selecting Display menu item
  315. // Displays the window with text in it.
  316. - showText:sender
  317. {
  318.  
  319.     [textWindow makeKeyAndOrderFront:self];
  320.     return self;
  321. }
  322.  
  323. // Window delegate method for the text window, invoked when
  324. // the window resizes. Saves the new size
  325. - windowDidResize:sender
  326. {
  327.     NXSize size;
  328.     [scrollView getContentSize:&size];
  329.     pageSize.width = size.width;
  330.     pageSize.height = size.height;
  331.     return self;
  332. }
  333.  
  334. // PText delegate method invoked when reading an rtf stream
  335. // and the papersize directives are read. Saves the size for later.
  336. - textDidRead:sender paperSize:(NXSize*) psize
  337. {
  338.     pageSize.width = psize->width;
  339.     pageSize.height = psize->height;
  340.     return self;
  341. }
  342.  
  343. // Private routine to make a full path name out of dir and file name
  344. static char* 
  345. makeFileName (const char* const file, const char* const dir)
  346. {
  347.     char* name ;
  348.     name = calloc (strlen (dir) + strlen (file) + 2, 1) ;
  349.     strcpy (name, dir) ;
  350.     strcat (name, "/") ;
  351.     strcat (name, file) ;
  352.     return name ;
  353. }
  354.  
  355. // Method invoked in reponse to user selecting "Open..." menu item.
  356. // Displays the standard open panel, and opens files selected.
  357. const char* typeList[] = { NULL };
  358.  
  359. - openFile:sender
  360. {
  361.     OpenPanel* op ;
  362.     const char* const* filenames ;
  363.     const char* directory ;
  364.     char* name ;
  365.     int rc;
  366.     
  367.     op = [OpenPanel new] ;
  368.     [op allowMultipleFiles:YES] ;
  369.     rc = [op runModalForTypes:typeList] ;
  370.     
  371.     if (rc == NX_CANCELTAG)
  372.     {
  373.         return self;
  374.     }
  375.     filenames = [op filenames] ;
  376.     directory = [op directory] ;
  377.  
  378.     if ((! directory) || (! filenames))
  379.     {
  380.         return self;
  381.     }
  382.         
  383.     while (*filenames)
  384.     {
  385.         name = makeFileName (*filenames, directory);
  386.         [self doit:name];
  387.         free (name);
  388.         filenames++;
  389.     }
  390.     return self;
  391. }
  392.  
  393. @end
  394.  
  395. ----------------------------
  396.  
  397. I can supply the .nib as well, I didn't want to make the post too huge, and  
  398. hopefully the description is enough to recreate the problem. I have a full  
  399. project (around 25KBytes uncompiled) that illustrates this problem. I can  
  400. NeXTMail it if this post does not give enough of a description to recreate, and  
  401. anyone would like to explore this further.
  402.  
  403. Thanks,
  404.  
  405. Gordie Freedman
  406. -- 
  407. Gordie Freedman gordie@cyclesoft.com   ->   NextMail encouraged
  408.  
  409.