home *** CD-ROM | disk | FTP | other *** search
/ Big Green CD 8 / BGCD_8_Dev.iso / NEXTSTEP / Graphics / ToyViewer-2.6a / src / TVController.m < prev    next >
Encoding:
Text File  |  1997-01-22  |  12.3 KB  |  520 lines

  1. #import <appkit/OpenPanel.h>
  2. #import <appkit/publicWraps.h>
  3. #import <appkit/Application.h>
  4. #import <appkit/Listener.h>
  5. #import <appkit/NXImage.h>
  6. #import <appkit/PrintInfo.h>
  7. #import <appkit/Pasteboard.h>
  8. #import <stdio.h>
  9. #import <stdlib.h>
  10. #import <string.h>
  11. #import <sys/types.h>
  12. #import <sys/stat.h>
  13. #import <sys/file.h>
  14. #import "TVController.h"
  15. #import "PrefControl.h"
  16. #import "ToyWin.h"
  17. #import "ToyWinPPM.h"
  18. #import "ToyWinEPS.h"
  19. #import "ToyWinBMP.h"
  20. #import "ToyWinGIF.h"
  21. #import "ToyWinPCD.h"
  22. #import "DirList.h"
  23. #import "ADController.h"
  24. #import "strfunc.h"
  25. #import "Exttab.h"
  26. #import "common.h"
  27.  
  28. TVController *theController = NULL;
  29.  
  30. @implementation TVController
  31.  
  32. #define  typeNumber    18
  33.  
  34. /* ToyViewer treats these extensions as pre-defined */
  35. static const char *const fileType[typeNumber + 1] = {
  36.     "tiff", "tif", "TIFF", "TIF",
  37.     "eps", "EPS",
  38.     "gif", "GIF",
  39.     "bmp", "BMP", "dib", "DIB",
  40.     "ppm", "pgm", "pbm", "pnm",
  41.     "pcd", "PCD",
  42.     NULL };
  43. static const char fileTypeID[typeNumber] = {
  44.     Type_tiff, Type_tiff, Type_tiff, Type_tiff,
  45.     Type_eps, Type_eps,
  46.     Type_gif, Type_gif,
  47.     Type_bmp, Type_bmp, Type_bmp, Type_bmp,
  48.     Type_ppm, Type_ppm, Type_ppm, Type_ppm,
  49.     Type_pcd, Type_pcd };
  50. /* extern */ const char **fileTypeBuffer;
  51. /* extern */ short *fileTypeIDBuffer;
  52. static char odir[MAXFILENAMELEN];    /* Last Opened Directory */
  53. static Exttab *extTable;
  54.  
  55. /* If file has no extension, this func. recognize its file type */
  56. static int discriminate(const char *fn)
  57. {
  58.     int maybe = Type_none;
  59.     int cc;
  60.     FILE *fp;
  61.  
  62.     if ((fp = fopen(fn, "r")) == NULL)
  63.         return Type_none;
  64.     switch (cc = getc(fp)) {
  65.     case 0x0a: maybe = Type_pcx;  break;
  66.     case '%':  maybe = Type_eps;  break;
  67.     case 'B':  maybe = Type_bmp;  break;
  68.     case 'G':  maybe = Type_gif;  break;
  69.     case 'I':  maybe = Type_tiff;  break;
  70.     case 'M':  maybe = Type_mag;  break;
  71.     case 'P':  maybe = Type_ppm;  break;
  72.     case 0x89:  maybe = Type_png;  break;
  73.     case 0xff:
  74.         if (getc(fp) == 0xd8)
  75.             maybe = Type_jpg;
  76.         break;
  77.     default: break;
  78.     }
  79.     fclose(fp);
  80.     return maybe;
  81. }
  82.  
  83.  
  84. - appDidInit:sender
  85. {
  86.     int i, j, n;
  87.     char buf[MAXFILENAMELEN], *p, **q;
  88.     NXCoord    lmg, rmg, tmg, bmg;
  89.     const char *sendTypes[3];
  90.     const char *returnTypes[3];
  91.     const char *const *types = [NXImage imageFileTypes];
  92.  
  93.     // [preference init];
  94.     if (thePreference == NULL) thePreference = preference;
  95.     theController = self;
  96.  
  97.     extTable = [[Exttab alloc] init];
  98.     n = dircopy(buf, NXArgv[0], YES);
  99.     strcpy(&buf[n], toyviewerTAB);
  100.     [extTable readExtData: buf];
  101.     p = getenv("HOME");
  102.     sprintf(buf, "%s/%s", p, toyviewerRC);
  103.     [extTable readExtData: buf];
  104.     sprintf(buf, "%s/Library/ToyViewer/rc.%s", p, __ARCHITECTURE__);
  105.     [extTable readExtData: buf];
  106.     n = [extTable entry];
  107.  
  108.     for (i = 0; types[i]; i++) ;
  109.     n += i + typeNumber + 1;
  110.     fileTypeBuffer = (const char **)malloc(sizeof(char *const *) * n);
  111.     fileTypeIDBuffer = (short *)malloc(sizeof(short) * n);
  112.     i = 0;
  113.     if ((q = [extTable table]) != NULL)
  114.         for (j = 0; q[j]; j++) {
  115.             fileTypeBuffer[i] = q[j];
  116.             fileTypeIDBuffer[i++] = Type_user;
  117.         }
  118.     for (j = 0; fileType[j]; j++) {
  119.         fileTypeBuffer[i] = fileType[j];
  120.         fileTypeIDBuffer[i++] = fileTypeID[j];
  121.     }
  122.     for (j = 0; types[j]; j++) {
  123.         fileTypeBuffer[i] = types[j];
  124.         fileTypeIDBuffer[i++] = Type_other;
  125.     }
  126.     fileTypeBuffer[i] = NULL;
  127.     [DirList setExtList: fileTypeBuffer];
  128.  
  129.     if ([thePreference isUpdatedServices])
  130.         NXUpdateDynamicServices();    // service re-providing
  131.     [[NXApp appListener] setServicesDelegate: self];
  132.     sendTypes[0] = NULL;
  133.     returnTypes[0] = NXPostScriptPboardType;
  134.     returnTypes[1] = NXTIFFPboardType;
  135.     returnTypes[2] = NULL;
  136.     [NXApp registerServicesMenuSendTypes:sendTypes
  137.             andReturnTypes:returnTypes];
  138.  
  139.     printInfo = [NXApp printInfo];
  140.     [printInfo setOrientation:NX_LANDSCAPE andAdjust:YES];
  141.     [printInfo getMarginLeft:&lmg right:&rmg top:&tmg bottom:&bmg];
  142.     lmg = (lmg + rmg) * 0.3;
  143.     tmg = (tmg + bmg) * 0.3;
  144.     [printInfo setMarginLeft:lmg right:lmg top:tmg bottom:tmg];
  145.  
  146.     [self initWallpaper];
  147.     return self;
  148. }
  149.  
  150. - (int)getFTypeID: (const char *)aType
  151. {
  152.     int    i;
  153.  
  154.     if (aType && *aType) {
  155.         for (i = 0; fileTypeBuffer[i]; i++)
  156.             if (strcmp(aType, fileTypeBuffer[i]) == 0)
  157.                 return fileTypeIDBuffer[i];
  158.     }
  159.     return Type_none;
  160. }
  161.  
  162.  
  163. /* Local Method */
  164. - allocWinFromFile: (const char *)fn :(const char *)aType
  165.         type:(int *)ftype display:(BOOL)display
  166.     /* Return Value:  nil: Error,  id: New ToyWin */
  167. {
  168.     id twtmp = nil;
  169.     int itype = Type_none;
  170.     const char *key = NULL;
  171.  
  172.     itype = [self getFTypeID: aType];
  173.     if (itype == Type_none) { /* Unknown Extension */
  174.         if ((itype = discriminate(fn)) == Type_none)
  175.             return nil;
  176.         key = NULL;
  177.     }else
  178.         key = aType;
  179.  
  180.     if (viaPipe(itype)) { /* Type_user and ... */
  181.         if (key == NULL)
  182.             switch (itype) {
  183.             case Type_pcx:    key = "pcx"; break;
  184.             case Type_mag:    key = "mag"; break;
  185.             case Type_jpg:    key = "jpg"; break;
  186.             case Type_xbm:    key = "xbm"; break;
  187.             case Type_jbg:    key = "bie"; break;
  188.             case Type_png:    key = "png"; break;
  189.             }
  190.         twtmp = [ToyWinPPM alloc];
  191.         if (display) [twtmp init:nil by:0];
  192.         else [twtmp initMapOnly];
  193.         [twtmp setExecList:
  194.             [extTable execListAlloc: key with: fn] ext: key]; 
  195.     }else if (itype == Type_pcd) {
  196.         twtmp = [ToyWinPCD alloc];
  197.         if (display) [twtmp init:nil by:0];
  198.         else [twtmp initMapOnly];
  199.         [twtmp setting];
  200.     }else {
  201.         switch (itype) {
  202.         case Type_bmp:
  203.             twtmp = [ToyWinBMP alloc]; break;
  204.         case Type_gif:
  205.             twtmp = [ToyWinGIF alloc]; break;
  206.         case Type_eps:
  207.             twtmp = [ToyWinEPS alloc];
  208.             display = YES;
  209.             break;
  210.         case Type_ppm:
  211.             twtmp = [ToyWinPPM alloc]; break;
  212.         case Type_tiff:
  213.         case Type_other:
  214.         default:
  215.             twtmp = [ToyWin alloc];
  216.             display = YES;
  217.             break;
  218.         }
  219.         if (display) [twtmp init:nil by:0];
  220.         else [twtmp initMapOnly];
  221.     }
  222.     *ftype = itype;
  223.     return twtmp;    // return New ToyWin
  224. }
  225.  
  226. - drawFile: (const char *)fn :(const char *)aType
  227.     /* Return Value:  nil: Error,  id: New ToyWin */
  228. {
  229.     unsigned char *map[MAXPLANE];
  230.     id newtw;
  231.     commonInfo *cinf;
  232.     int itype, err = 0;
  233.  
  234.     newtw = [self allocWinFromFile:fn : aType type:&itype display:YES];
  235.     if (!newtw)
  236.         return nil;
  237.     cinf = [newtw drawToyWin:(const char *)fn type:itype map:map err:&err];
  238.     if (cinf == NULL && err) {
  239.         if (err > 0) errAlert(fn, err);
  240.         [newtw free];
  241.         return nil;
  242.     }
  243.     [self newWindow: newtw];
  244.     return newtw;
  245. }
  246.  
  247. /* Local Method */
  248. /* This method is NOT used for EPS and TIFF */
  249. - (NXBitmapImageRep *)imageFromFile: (const char *)fn :(const char *)aType map:(unsigned char **)map
  250. {
  251.     id newtw;
  252.     commonInfo *cinf;
  253.     NXBitmapImageRep *img;
  254.     int itype, err = 0, spp;
  255.  
  256.     map[0] = NULL;
  257.     newtw = [self allocWinFromFile:fn : aType type:&itype display:NO];
  258.     if (!newtw)
  259.         return NULL;
  260.     cinf = [newtw drawToyWin:(const char *)fn type:itype map:map err:&err];
  261.     if (cinf == NULL && err) {
  262.         if (err > 0) errAlert(fn, err);
  263.         [newtw free];
  264.         return NULL;
  265.     }
  266.  
  267.     if ((img = [NXBitmapImageRep alloc]) != NULL) {
  268.         spp = cinf->numcolors;
  269.         if (cinf->alpha) spp++;
  270.         [img initDataPlanes: map    pixelsWide: cinf->width
  271.         pixelsHigh: cinf->height bitsPerSample: cinf->bits
  272.         samplesPerPixel: spp    hasAlpha: cinf->alpha
  273.         isPlanar: YES        colorSpace: cinf->cspace
  274.         bytesPerRow: cinf->xbytes 
  275.         bitsPerPixel: cinf->bits];
  276.     }
  277.     [newtw free];
  278.     if (cinf->palette)
  279.         free((void *)cinf->palette);
  280.     free((void *)cinf);
  281.         /* An instance of ToyWin initialized by "initMapOnly"
  282.             does not have instances of ToyView in it.
  283.             So, "cinf" must be freed here. */
  284.     return img;
  285. }
  286.  
  287. /* Get stream from file without actual window.
  288.    This method is used to provide Pasteboard-Services and Initial Wallpaper.
  289.  */
  290. - (NXStream *)openStreamFromFile: (const char *)fn :(const char *)aType
  291. {
  292.     unsigned char *map[MAXPLANE];
  293.     NXBitmapImageRep *img;
  294.     NXStream *pbStream = NULL;
  295.     ToyWinEPS *tweps;
  296.     int    itype, err;
  297.  
  298.     if ((pbStream = NXOpenMemory(NULL, 0, NX_READWRITE)) == NULL)
  299.         return NULL;
  300.  
  301.     itype = [self getFTypeID: aType];
  302.     if (itype == Type_eps) {
  303.         tweps = [[ToyWinEPS alloc] initMapOnly];
  304.         pbStream = [tweps openStreamFromFile:fn err:&err];
  305.         [tweps free];
  306.         if (pbStream == NULL && err > 0) {
  307.             errAlert(fn, err);
  308.             if (pbStream)
  309.                 NXCloseMemory(pbStream, NX_FREEBUFFER);
  310.             return NULL;
  311.         }
  312.         return pbStream;
  313.     }
  314.     map[0] = NULL;
  315.     img = (itype == Type_tiff)
  316.         ? [[NXBitmapImageRep alloc] initFromFile: fn]
  317.         : [self imageFromFile: fn : aType map: map];
  318.     if (img) {
  319.         [img writeTIFF: pbStream];
  320.         NXSeek(pbStream, 0L, NX_FROMSTART);
  321.         [img free];
  322.     }else {
  323.         NXCloseMemory(pbStream, NX_FREEBUFFER);
  324.         pbStream = NULL;
  325.     }
  326.     if (map[0])
  327.         free((void *)map[0]);
  328.     return pbStream;
  329. }
  330.  
  331. - openFile:sender
  332. {
  333.     char fn[MAXFILENAMELEN];
  334.     id openPanel;
  335.     
  336.     if (!odir[0])
  337.         strcpy(odir, getenv("HOME"));
  338.     openPanel = [OpenPanel new];
  339.     [[openPanel chooseDirectories: NO] allowMultipleFiles:YES];
  340.     if ([openPanel runModalForDirectory:odir
  341.             file:NULL types:fileTypeBuffer]) {
  342.         const char *const *files = [openPanel filenames];
  343.         strcpy(odir, [openPanel directory]);
  344.         for ( ; files && *files; files++) {
  345.             sprintf(fn, "%s/%s", odir, *files);
  346.             if (! [self isOpened: fn]) {
  347.                 int j;
  348.                 if ((j = getExtension(fn)) == 0)
  349.                     return self; /* No Extension */
  350.                 [self drawFile: fn : &fn[j]];
  351.             }
  352.         }
  353.     }
  354.     return self;
  355. }
  356.  
  357. #define  AutoThreshold    4
  358.  
  359. /* Local Method */
  360. - openDirectory: (const char *)dir
  361. {
  362.     char fn[MAXFILENAMELEN];
  363.     const char *p;
  364.     int    n, i;
  365.     id    dirlist;
  366.     static id autoDisplayCtr = nil;
  367.  
  368.     dirlist = [[DirList alloc] init];
  369.     n = [dirlist getDirList: dir];
  370.     if (n <= 0) {
  371.         errAlert(dir, Err_NOFILE);
  372.         [dirlist free];
  373.     }else if (n < AutoThreshold) {
  374.         for (i = 0; i < n; i++) {
  375.             p = [dirlist filenameAt: i];
  376.             sprintf(fn, "%s/%s", dir, p);
  377.             if (! [self isOpened: fn]) {
  378.                 int j = getExtension(p);
  379.                 (void)[self drawFile: fn : &p[j]];
  380.             }
  381.         }
  382.         [dirlist free];
  383.     }else { /* Auto Display */
  384.         char bdir[MAXFILENAMELEN];
  385.         id bundle, ad;
  386.         if (autoDisplayCtr == nil) {
  387.             n = dircopy(bdir, NXArgv[0], YES);
  388.             strcpy(&bdir[n], "ADController.bundle");
  389.             bundle = [[NXBundle alloc] initForDirectory: bdir];
  390.             if (bundle == nil) /* ERROR */
  391.                 return nil;
  392.             autoDisplayCtr = [bundle classNamed:"ADController"];
  393.             if (autoDisplayCtr == nil) /* ERROR */
  394.                 return nil;
  395.         }
  396.         ad = [autoDisplayCtr alloc];
  397.         [ad init:self dir:dir with:dirlist];
  398.     }
  399.  
  400.     return self;
  401. }
  402.  
  403. - autoDisplay:sender
  404. {
  405.     char fn[MAXFILENAMELEN];
  406.     id openPanel;
  407.     const char *const *files;
  408.  
  409.     if (!odir[0])
  410.         strcpy(odir, getenv("HOME"));
  411.     openPanel = [OpenPanel new];
  412.     [[openPanel chooseDirectories: YES] allowMultipleFiles:NO];
  413.     if (![openPanel runModalForDirectory:odir file:NULL])
  414.         return self;
  415.  
  416.     files = [openPanel filenames];
  417.     strcpy(odir, [openPanel directory]);
  418.     sprintf(fn, "%s/%s", odir, *files);
  419.     [self openDirectory: fn];
  420.     return self;
  421. }
  422.  
  423.  
  424. - readSelectionFromPasteboard:pb
  425. {
  426.     const NXAtom    *cont;
  427.     NXStream    *st;
  428.     id   twtmp = nil;
  429.     char *ext, fn[256];
  430.     int  err;
  431.     static int untitledCount = 0;
  432.  
  433.     ext = NULL;
  434.     for (cont = [pb types]; cont && *cont; cont++) {
  435.         if (*cont == NXTIFFPboardType) {
  436.             twtmp = [[ToyWin alloc] init:nil by:0];
  437.             ext = "tiff";
  438.             break;
  439.         }
  440.         if (*cont == NXPostScriptPboardType) {
  441.             twtmp = [[ToyWinEPS alloc] init:nil by:0];
  442.             ext = "eps";
  443.             break;
  444.         }
  445.     }
  446.     if (ext == NULL) {
  447.         NXBeep();
  448.         return self;
  449.     }
  450.     st = [pb readTypeToStream: *cont];
  451.     sprintf(fn, "%s/Untitled%d.%s", getenv("HOME"), ++untitledCount, ext);
  452.  
  453.     err = [twtmp drawFromFile:(const char *)fn or:st];
  454.     if (err == 0)
  455.         [self newWindow: twtmp];
  456.     else {
  457.         if (err > 0)
  458.             errAlert(fn, err);
  459.         [twtmp free];
  460.     }
  461.     NXCloseMemory(st, NX_FREEBUFFER);
  462.     return self;
  463. }
  464.  
  465. - openPasteBoard:sender
  466. {
  467.     Pasteboard  *pb = [Pasteboard new];  // don't free it
  468.     return [self readSelectionFromPasteboard:pb];
  469. }
  470.  
  471. - (int)app:sender openFile:(const char *)fn type:(const char *)aType
  472. {
  473.     struct stat  buf;
  474.     int    mode;
  475.     id    res = nil;
  476.  
  477.     if (printInfo == nil)
  478.         [self appDidInit:sender];
  479.     if (stat((char *)fn, &buf) != 0) return NO;
  480.     mode = (buf.st_mode & S_IFMT);
  481.     if (mode == S_IFDIR) {
  482.         if (access(fn, X_OK) != 0) return NO;
  483.         res = [self openDirectory: fn];
  484.     }else {
  485.         if ([self isOpened: fn]) return YES;
  486.         res = [self drawFile: fn : aType];
  487.     }
  488.     return (res != nil);
  489. }
  490.  
  491. - (BOOL)appAcceptsAnotherFile:sender
  492. {
  493.     return YES;
  494. }
  495.  
  496. - messageDisplay:(const char *)msg
  497. {
  498.     if (msg) {
  499.         [messagePanel makeKeyAndOrderFront: self];
  500.         [messageText setStringValue: msg];
  501.         [messagePanel setFloatingPanel: YES];
  502.         NXPing();
  503.     }else {
  504.         [messagePanel setFloatingPanel: NO];
  505.         [messagePanel close];
  506.     }
  507.     return messageText;
  508. }
  509.  
  510. - validRequestorForSendType:(NXAtom)typeSent
  511.                         andReturnType:(NXAtom)typeReturned
  512. {
  513.     if (typeReturned == NXPostScriptPboardType
  514.             || typeReturned == NXTIFFPboardType)
  515.         return self;
  516.     return nil;
  517. }
  518.  
  519. @end
  520.