home *** CD-ROM | disk | FTP | other *** search
/ Nebula 1 / Nebula One.iso / Internet / News / Alexandra.0.82 / Source / Decoding.subproj / DecoderController.m < prev    next >
Encoding:
Text File  |  1996-01-30  |  9.1 KB  |  310 lines

  1.  
  2. #import <appkit/appkit.h>
  3. #import <misckit/MiscSortedList.h>
  4. #import <misckit/MiscAppDefaults.h>
  5. #import "../Preferences.subproj/preferences.h"
  6.  
  7. #import "decode.h"
  8.  
  9. #import "NiftyMatrix.h"
  10. #import "DecodeCell.h"
  11. #import "NNTP.h"
  12. #import "MainWindowControl.h"
  13. #import "ArticleSetMatrix.h"
  14. #import "ArticleSet.h"
  15. #import "Article.h"
  16. #import "MatrixScroller.h"
  17.  
  18. #import "DecoderController.h"
  19.  
  20. #import "descriptors.h"
  21.  
  22. @implementation DecoderController : Object
  23.  
  24. - (void) doDecoding:sender
  25. // Sender is the MainWindowControl. This is activated after the user
  26. // chooses Tools->UUdecode from the menu.
  27. {
  28.     int articlesSelected;
  29.     
  30.     // Keep the main window control around cause we'll need it.
  31.     mainWindowControl = sender;
  32.     
  33.     articlesSelected = [[mainWindowControl articleSet] numSelCells];
  34.     // If multiple articles are selected then we have to do the
  35.     // modal panel.
  36.     
  37.     setDecodeDepositPathname([NXApp defaultValue:DEFAULT_SAVE_PATH]);
  38.  
  39.     if (articlesSelected > 1) {
  40.         [self showDecodePanel:self];
  41.     }
  42.     else    
  43.     // If only a single article is selected then we can grab
  44.     // the text from the text object.
  45.     if (articlesSelected == 1) {
  46.         Text *articleText = [sender articleText];
  47.         NXStream *textStream;
  48.         int status;
  49.         
  50.         textStream = [articleText stream];
  51.         NXSeek(textStream,0,NX_FROMSTART);        
  52.  
  53.         uud_start();
  54.         status = uudecode(textStream);
  55.  
  56.         if (status == -1) {
  57.             NXRunAlertPanel("UUdecode Error", 
  58.                 "Could not decode the selected article.", "OK", NULL, NULL);
  59.         }
  60.         else 
  61.         if (status == 0 && uudecode_state() == SKIP_LEADING) {
  62.             NXRunAlertPanel("UUdecode Error", 
  63.                 "Could not find the end of article.", "OK", NULL, NULL);
  64.         }
  65.         decode_end();
  66.     }
  67. }
  68.  
  69. - (void) uudecodeMultipleArticles
  70. // Begin the uudecoding.
  71. {
  72.     DecodeCell * selectedArticleCell;
  73.     int selectedArticleCount;
  74.     int i;
  75.     
  76.     [decodeAndAbortButton setEnabled:NO];
  77.     continueDecoding = YES;
  78.     // Start with the first cell that isn't decoded. Usually that's the first
  79.     // one, but if the user clicks the "Abort" button and then decides to 
  80.     // continue...
  81. //    currentDecodeIndex = 0;
  82.  
  83.     selectedArticleCount = [selectedArticleMatrix cellCount];    
  84.     for (i=0; i<selectedArticleCount; i++) {
  85.         selectedArticleCell = [selectedArticleMatrix cellAt:i :0];
  86.         if ([selectedArticleCell decodeStatus] == NOT_DECODED) {
  87.             break;
  88.         }
  89.     }
  90.     currentDecodeIndex = i;
  91.     
  92.     // This starts the chain of decoding. If there are more articles
  93.     // and the abort button is not clicked then they will get done in turn.
  94.     if (currentDecodeIndex < selectedArticleCount) {
  95.         uud_start();
  96.         [self uudecodeArticle:[[selectedArticleMatrix cellAt:
  97.             currentDecodeIndex :0] articleIndex]];
  98.     }
  99. }
  100.  
  101. - (void) uudecodeArticle:(int)articleIndex
  102. // This method uudecodes the given article (the articleIndex is it's place in
  103. // the articleMatrix in the main window), then primes (delay performs) the next 
  104. // not yet decoded article if the abort button hasn't been clicked. 
  105. // This is just so you have something like multithreading without actually 
  106. // having to write it.
  107. {
  108.     // Has the abort button been clicked?
  109.     if (continueDecoding) {
  110.         id nntpServer = [mainWindowControl nntpServer];
  111.         Article * article;
  112.         char * body;
  113.         int selectedArticleCount;
  114.         
  115.         // Get and load the article.
  116.         article = [[mainWindowControl articleMatrix] cellAt:articleIndex :0];
  117.         [nntpServer loadArticleBody:article toString:&body];
  118.         
  119.         if (body) {
  120.             // It's probably not the most efficient thing to put the article
  121.             // in a stream, but that's how the uudecode function now expects
  122.             // it.
  123.             NXStream * articleStream = NXOpenMemory(body, strlen(body),
  124.                                                     NX_READONLY);
  125.             DecodeCell * currentCell;
  126.             int currentStatus;
  127.             int px,py;
  128.                 
  129.             currentStatus = uudecode(articleStream);
  130.             NXCloseMemory(articleStream, NX_FREEBUFFER);
  131.  
  132.             // Should it only be setRead if it's successful? For now as you 
  133.             // can see it marks it read regardless.
  134.             //[article setRead];
  135.             
  136.             // Set the image in the cell to show success or failure.
  137.             currentCell = [selectedArticleMatrix cellAt:currentDecodeIndex :0];
  138.             [currentCell setDecodeStatus:(currentStatus == 0) ? 
  139.                     DECODE_SUCCESSFUL : DECODE_FAILED];
  140.             [selectedArticleMatrix getRow:&px andCol:&py ofCell:currentCell];
  141.             [selectedArticleMatrix drawCellAt:px :py];
  142.             [selectedArticleMatrix scrollCellToVisible:px upperOffset:1.5 lowerOffset:1.5];
  143.             
  144.             //stop if error
  145.             if(currentStatus){
  146.                 decode_end();
  147.                 return;
  148.             }
  149.         }            
  150.  
  151.         // Set the next cell for uudecoding if there are any more.        
  152.         selectedArticleCount = [selectedArticleMatrix cellCount];
  153.         currentDecodeIndex++;
  154.         if (currentDecodeIndex < selectedArticleCount) {
  155.             DecodeCell * nextCell;
  156.             
  157.             nextCell = [selectedArticleMatrix cellAt:currentDecodeIndex :0];
  158.             // This is probably bad (passing an int to the with argument).
  159.             [self perform:_cmd with:(void*)[nextCell articleIndex] 
  160.                 afterDelay:0.0 cancelPrevious:NO];
  161.         }
  162.         // We are done decoding so set the button back to say "Decode".
  163.         else {
  164.             //[decodeAndAbortButton setState:0];
  165.             continueDecoding = NO;
  166.             decode_end();
  167.             [panel close];
  168.             [(ArticleSet *)mainWindowControl markRead:self];
  169.             [NXApp abortModal];
  170.         }
  171.     }
  172. }
  173.  
  174. - (void) showDecodePanel:sender
  175. {
  176.     if (panel == nil) {
  177.         [NXApp loadNibSection:"ModalDecodingPanel.nib" owner:self];
  178.         [self setupDecodePanel];
  179.     }
  180.  
  181.     [decodeAndAbortButton setState:0];
  182.     [decodeAndAbortButton setEnabled:YES];
  183.     [self loadMatrixWithArticles];
  184.     [panel orderFront:self];
  185.     [NXApp runModalFor:panel];
  186. }
  187.  
  188. - (void) setupDecodePanel
  189. // This is called only the first time the nib is loaded so we can swap
  190. // the matrix with a nifty matrix.
  191. {
  192.     NiftyMatrix * niftyMatrix;
  193.     ScrollView * scrollView = [[selectedArticleMatrix superview] superview];
  194.     NXRect scrollBoundsRect;
  195.     NXSize interCellSpacing;
  196.     NXSize cellSize;
  197.         
  198.     // Determine the Matrix bounds.
  199.     [scrollView getBounds:&scrollBoundsRect];
  200.     
  201.     // Prepare a NiftyMatrix to go inside the ScrollView.
  202.     niftyMatrix = [[NiftyMatrix alloc] initFrame:&scrollBoundsRect 
  203.         mode:NX_RADIOMODE cellClass:[DecodeCell class]
  204.         numRows:5 numCols:1];
  205.     
  206.     // Eliminate intercell spacing.  
  207.     interCellSpacing.height = 0.0;
  208.     interCellSpacing.width = 0.0;
  209.     [niftyMatrix setIntercell:&interCellSpacing];
  210.             
  211.     // Set the Cell size to the width of the ScrollView's bounds rect. 
  212.     [niftyMatrix getCellSize:&cellSize];
  213.     cellSize.width = NX_WIDTH (&scrollBoundsRect);
  214.     [niftyMatrix setCellSize:&cellSize];
  215.     [niftyMatrix sizeToCells];
  216.     
  217.     // Set NiftyMatrix sizing parameters.
  218.     [niftyMatrix setAutosizeCells:YES];
  219.     [[niftyMatrix superview] setAutoresizeSubviews:YES];
  220.     [niftyMatrix setAutosizing:NX_WIDTHSIZABLE];
  221.     
  222.     // Scroll when the user clicks in the EnhancedNiftyMatrix and then 
  223.     // drags the mouse out of contentView.
  224.     [niftyMatrix setAutoscroll:YES];
  225.     
  226.     // Stick the matrix in the ScrollView.
  227.     [scrollView setDocView:niftyMatrix];
  228.     [niftyMatrix display];
  229.     [selectedArticleMatrix free];
  230.     selectedArticleMatrix = niftyMatrix;
  231. }
  232.  
  233. - (void) loadMatrixWithArticles
  234. // Loads the nifty matrix with the selected cells from the article matrix.
  235. // We also sort them so that multipart pics will probably be in the correct
  236. // order.
  237. {
  238.     List * articleList = [[mainWindowControl articleMatrix] cellList];
  239.     MiscSortedList * sortedArticleList = [[MiscSortedList alloc] init];
  240.     Article * articleCell;
  241.     DecodeCell * sortedArticleCell;
  242.     int    i;
  243.     int    sortedArticleCount;
  244.     int oldSortType=[Article sortType];
  245.     
  246.     // Get the selected articles and sort them.
  247.     [sortedArticleList setSortEnabled:NO];
  248.     sortedArticleList = [[mainWindowControl articleMatrix] 
  249.         getSelectedCells:sortedArticleList];
  250.     [Article setSortType:SORT_BY_SUBJECT];
  251.     [sortedArticleList sort];
  252.     [Article setSortType:oldSortType];
  253.     
  254.     // Resize our matrix so it will hold the new selected cells.
  255.     sortedArticleCount = [sortedArticleList count];
  256.     [selectedArticleMatrix renewRows:sortedArticleCount cols:1];
  257.  
  258.     // Fill the matrix.
  259.     for (i=0; i<sortedArticleCount; i++) {
  260.         sortedArticleCell = [selectedArticleMatrix cellAt:i :0];
  261.         articleCell = [sortedArticleList objectAt:i];
  262.         // The article index is the index of the article in the articleMatrix.
  263.         [sortedArticleCell setArticleIndex:[articleList indexOf:articleCell]];
  264.         [sortedArticleCell setStringValue:
  265.             [articleCell header]->fieldBody[SUBJECT]];
  266.         // Since we might be reusing cells we should set this explicitly.
  267.         [sortedArticleCell setDecodeStatus:NOT_DECODED];
  268.     }
  269.     
  270.     // Scroll to the top and redisplay.
  271. //    [[selectedArticleMatrix window] disableFlushWindow];
  272.     [selectedArticleMatrix scrollCellToVisible:0 :0];
  273.     [selectedArticleMatrix sizeToCells];
  274.     [selectedArticleMatrix display];
  275. //    [[selectedArticleMatrix window] reenableFlushWindow];
  276. //    [[selectedArticleMatrix    window] flushWindow];
  277.     
  278.     // Set our counter to display the number of selected articles.
  279.     [numArticlesTF setIntValue:[selectedArticleMatrix cellCount]];
  280. }
  281.  
  282. - decodeOrAbortButtonClicked:sender
  283. // The sender is the "Decode" or "Abort" button (the same button with
  284. // a title and alt-title).
  285. {
  286.     // The "Decode" button was clicked.
  287.     if ([sender state] == 1) {
  288.         [self uudecodeMultipleArticles];
  289.     }
  290.     // The "Abort" button was clicked.
  291.     else {    
  292.         continueDecoding = NO;
  293.     }
  294.     return self;
  295. }
  296.  
  297. - cancelModalPanel:sender
  298. // The cancel button was clicked
  299. {
  300.     continueDecoding = NO;
  301.     decode_end();
  302.     [NXApp stopModal];
  303.     [panel close];
  304.  
  305.     return self;
  306. }
  307.  
  308. @end
  309.  
  310.