home *** CD-ROM | disk | FTP | other *** search
/ System Booster / System Booster.iso / Commodities / ClipTool / src / buffers.c next >
Encoding:
C/C++ Source or Header  |  1996-09-27  |  12.5 KB  |  554 lines

  1. /*
  2.  *  ClipTool (Udklipsværktøj) - A Commodities Exchange Application
  3.  *  Copyright (C) 1994 Torsten Poulin
  4.  *
  5.  *  buffers.c - the text buffer and clipboard routines.
  6.  *
  7.  *  This program is free software; you can redistribute it and/or modify
  8.  *  it under the terms of the GNU General Public License as published by
  9.  *  the Free Software Foundation; either version 2 of the License, or
  10.  *  (at your option) any later version.
  11.  *
  12.  *  This program is distributed in the hope that it will be useful,
  13.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.  *  GNU General Public License for more details.
  16.  *
  17.  *  You should have received a copy of the GNU General Public License
  18.  *  along with this program; if not, write to the Free Software
  19.  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20.  *
  21.  *             The author can be contacted by mail at
  22.  *               Torsten Poulin
  23.  *               Banebrinken 99, 2, 77
  24.  *               DK-2400 Copenhagen NV
  25.  *               Denmark
  26.  *             or via email: torsten@diku.dk
  27.  *
  28.  * $Log:    buffers.c,v $
  29.  * Revision 1.1  94/02/20  21:30:22  Torsten
  30.  * Initial revision
  31.  * 
  32.  */
  33.  
  34. static char const RCSid[] = "$Id: buffers.c,v 1.1 94/02/20 21:30:22 Torsten Exp $";
  35.  
  36. #include "cliptool.h"
  37. #include "ctstrings.h"
  38.  
  39. #define ID_FTXT MAKE_ID('F','T','X','T')
  40. #define ID_CHRS MAKE_ID('C','H','R','S')
  41.  
  42. struct bufferlisthead *currentbuffer;
  43. long ntotal, ncurrent;
  44. static struct bufferlisthead *firstlisthead;
  45. static struct bufferlisthead *lastlisthead;
  46.  
  47. static void inserttextbuffer(struct textbuffer *);
  48. static void disposelistheader(void);
  49. static void readFTXTclip(struct textbuffer **);
  50. static void writeFTXTclip(struct textbuffer *);
  51. static BOOL readTEXTfile(UBYTE *, struct textbuffer **);
  52. static BOOL readFTXTfile(UBYTE *, struct textbuffer **);
  53. static BOOL writeTEXTfile(UBYTE *, struct textbuffer *);
  54. static BOOL writeFTXTfile(UBYTE *, struct textbuffer *);
  55. static void storetext(struct textbuffer **, UBYTE *, long);
  56. static void addicon(UBYTE *, BOOL);
  57.  
  58.  
  59. /*
  60.  * Move to the previous text buffer list.
  61.  */
  62.  
  63. void prevtext(void)
  64. {
  65.   if (firstlisthead && firstlisthead != lastlisthead) {
  66.     if (currentbuffer->prev) {
  67.       currentbuffer = currentbuffer->prev;
  68.       ncurrent--;
  69.     }
  70.     else {
  71.       currentbuffer = lastlisthead; /* wrap around */
  72.       ncurrent = ntotal;
  73.     }
  74.     updatetitlebar();
  75.     showtext();
  76.   }
  77. }
  78.  
  79.  
  80. /*
  81.  * Move to the next text buffer list.
  82.  */
  83.  
  84. void nexttext(void)
  85. {
  86.   if (firstlisthead && firstlisthead != lastlisthead) {
  87.     if (currentbuffer->next) {
  88.       currentbuffer = currentbuffer->next;
  89.       ncurrent++;
  90.     }
  91.     else {
  92.       currentbuffer = firstlisthead; /* wrap around */
  93.       ncurrent = 1;
  94.     }
  95.     updatetitlebar();
  96.     showtext();
  97.   }
  98. }
  99.  
  100.  
  101. /*
  102.  * Private function to insert a new text buffer list
  103.  * at the end of the header list.
  104.  */
  105.  
  106. static void inserttextbuffer(struct textbuffer *tb)
  107. {
  108.   struct bufferlisthead *newblh;
  109.  
  110.   if (tb) {
  111.     if (newblh = malloc(sizeof(struct bufferlisthead))) {
  112.       newblh->tb = tb;
  113.       newblh->next = NULL;
  114.       newblh->prev = lastlisthead;
  115.       if (lastlisthead)    lastlisthead->next = newblh;
  116.       else firstlisthead = newblh;
  117.       currentbuffer = lastlisthead = newblh;
  118.       ncurrent = ++ntotal;
  119.       updatetitlebar();
  120.     }
  121.   }
  122. }
  123.  
  124.  
  125. /*
  126.  * Private function to dispose a buffer list header
  127.  * and move the current buffer header one step forward.
  128.  */
  129.  
  130. static void disposelistheader(void)
  131. {
  132.   if (currentbuffer) {        /* list isn't empty */
  133.     if (currentbuffer == firstlisthead) {
  134.       if (currentbuffer == lastlisthead) {
  135.     free(currentbuffer);    /* disposing the only header */
  136.     currentbuffer = firstlisthead = lastlisthead = NULL;
  137.     ncurrent = ntotal = 0;
  138.       }
  139.       else {
  140.     firstlisthead = currentbuffer->next;
  141.     currentbuffer->next->prev = NULL;
  142.     free(currentbuffer);    /* disposing first header */
  143.     currentbuffer = firstlisthead;
  144.     ncurrent = 1;
  145.     ntotal--;
  146.       }
  147.     }
  148.     else if (currentbuffer == lastlisthead) {
  149.       lastlisthead = currentbuffer->prev;
  150.       currentbuffer->prev->next = NULL;
  151.       free(currentbuffer);    /* disposing the last header */
  152.       currentbuffer = firstlisthead;
  153.       ncurrent = 1;
  154.       ntotal--;
  155.     }
  156.     else {
  157.       struct bufferlisthead *temp = currentbuffer;
  158.  
  159.       currentbuffer = currentbuffer->next;
  160.       temp->prev->next = temp->next;
  161.       temp->next->prev = temp->prev;
  162.       free(temp);        /* disposing interior header */
  163.       ntotal--;
  164.     }
  165.     updatetitlebar();
  166.   }
  167. }
  168.  
  169.  
  170. /*
  171.  * move the contents of the current buffer to the clipboard.
  172.  */
  173.  
  174. void cut(void)
  175. {
  176.   if (currentbuffer) {
  177.     writeFTXTclip(currentbuffer->tb);
  178.     freetext();
  179.   }
  180. }
  181.  
  182.  
  183. /*
  184.  * copy the contents of the current buffer to the clipboard.
  185.  */
  186.  
  187. void copy(void)
  188. {
  189.   if (currentbuffer)
  190.     writeFTXTclip(currentbuffer->tb);
  191. }
  192.  
  193.  
  194. /*
  195.  * Store the contents of the clipboard in the
  196.  * buffer list, and update the display.
  197.  */
  198.  
  199. void paste(void)
  200. {
  201.   struct textbuffer *tb = NULL;
  202.  
  203.   readFTXTclip(&tb);
  204.   inserttextbuffer(tb);
  205.   showtext();
  206. }
  207.  
  208.  
  209. /*
  210.  * This function removes the current buffer from
  211.  * the list and frees the memory it occupied.
  212.  */
  213.  
  214. void freetext(void)
  215. {
  216.   struct textbuffer *tb, *temp;
  217.  
  218.   if (currentbuffer) {
  219.     tb = currentbuffer->tb;
  220.     while (tb) {
  221.       temp = tb->next;
  222.       free(tb);
  223.       tb = temp;
  224.     }
  225.     disposelistheader();
  226.     showtext();
  227.   }
  228. }
  229.  
  230.  
  231. /*
  232.  * This is a rather simplistic implementation of storetext().
  233.  * It relies on the fact that SAS/C requests memory from the
  234.  * system pool in relatively large chunks to reduce fragmentation.
  235.  */
  236.  
  237. static void storetext(struct textbuffer **root, UBYTE *buf, long rlen)
  238. {
  239.   static struct textbuffer *last;
  240.   struct textbuffer *tb;
  241.  
  242.   if (tb = malloc(sizeof(struct textbuffer) + rlen)) {
  243.     tb->next = NULL;
  244.     tb->length = rlen - 1;
  245.     memcpy(tb->data, buf, rlen);
  246.     if (!*root) *root = tb;
  247.     else last->next = tb;
  248.     last = tb;
  249.   }
  250. }
  251.  
  252.  
  253. static void readFTXTclip(struct textbuffer **tbptr)
  254. {
  255.   struct IFFHandle *iff;
  256.   struct ContextNode *cn;
  257.   long rlen;
  258.   long error = 0;
  259.   UBYTE readbuf[RBUFSZ];
  260.  
  261.   if (iff = AllocIFF()) {
  262.     if (iff->iff_Stream = (ULONG) OpenClipboard(unitnumber)) {
  263.       InitIFFasClip(iff);
  264.       if (!OpenIFF(iff, IFFF_READ)) {
  265.     if (!StopChunk(iff, ID_FTXT, ID_CHRS)) {
  266.       for (;;) {
  267.         if ((error = ParseIFF(iff, IFFPARSE_SCAN)) == IFFERR_EOC)
  268.           continue; /* go to the next context */
  269.         else if (error)
  270.           break;
  271.         cn = CurrentChunk(iff);
  272.         if (cn && cn->cn_Type == ID_FTXT && cn->cn_ID == ID_CHRS) {
  273.           while ((rlen = ReadChunkBytes(iff, readbuf, RBUFSZ)) > 0)
  274.         storetext(tbptr, readbuf, rlen);
  275.         }
  276.       }
  277.     }
  278.     CloseIFF(iff);
  279.       }
  280.       CloseClipboard((struct ClipboardHandle *) iff->iff_Stream);
  281.     }
  282.     FreeIFF(iff);
  283.   }
  284. }
  285.  
  286.  
  287. static void writeFTXTclip(struct textbuffer *tb)
  288. {
  289.   struct IFFHandle *iff;
  290.  
  291.   if (iff = AllocIFF()) {
  292.     if (iff->iff_Stream = (ULONG) OpenClipboard(unitnumber)) {
  293.       InitIFFasClip(iff);
  294.       if (!OpenIFF(iff, IFFF_WRITE)) {
  295.     /* write FORM FTXT */
  296.     if (!PushChunk(iff, ID_FTXT, ID_FORM, IFFSIZE_UNKNOWN)) {
  297.       for (; tb; tb = tb->next) {
  298.         /* write a CHRS chunk... */
  299.         if (!PushChunk(iff, 0, ID_CHRS, tb->length)) {
  300.           /* ...followed by its chunk data */
  301.           if (WriteChunkBytes(iff,tb->data,tb->length) != tb->length)
  302.         break;
  303.           PopChunk(iff);
  304.         }
  305.       }
  306.       PopChunk(iff);
  307.     }
  308.     CloseIFF(iff);
  309.       }
  310.       CloseClipboard((struct ClipboardHandle *) iff->iff_Stream);
  311.     }
  312.     FreeIFF(iff);
  313.   }
  314. }
  315.  
  316.  
  317. static BOOL readTEXTfile(UBYTE *fname, struct textbuffer **tbptr)
  318. {
  319.   long rlen;
  320.   UBYTE readbuf[RBUFSZ];
  321.   BPTR file;
  322.  
  323.   if (file = Open(fname, MODE_OLDFILE)) {
  324.     while ((rlen = Read(file, readbuf, RBUFSZ)) > 0)
  325.       storetext(tbptr, readbuf, rlen);
  326.     Close(file);
  327.   }
  328.   else return FALSE;
  329.   return TRUE;
  330. }
  331.  
  332.  
  333. static BOOL readFTXTfile(UBYTE *fname, struct textbuffer **tbptr)
  334. {
  335.   struct IFFHandle *iff;
  336.   struct ContextNode *cn;
  337.   long rlen;
  338.   long error = 0;
  339.   UBYTE readbuf[RBUFSZ];
  340.  
  341.   if (iff = AllocIFF()) {
  342.     if (iff->iff_Stream = Open(fname, MODE_OLDFILE)) {
  343.       InitIFFasDOS(iff);
  344.       if (!(error = OpenIFF(iff, IFFF_READ))) {
  345.     if (!(error = StopChunk(iff, ID_FTXT, ID_CHRS))) {
  346.       for (;;) {
  347.         if ((error = ParseIFF(iff, IFFPARSE_SCAN)) == IFFERR_EOC)
  348.           continue; /* go to the next context */
  349.         else if (error)
  350.           break;
  351.         cn = CurrentChunk(iff);
  352.         if (cn && cn->cn_Type == ID_FTXT && cn->cn_ID == ID_CHRS) {
  353.           while ((rlen = ReadChunkBytes(iff, readbuf, RBUFSZ)) > 0)
  354.         storetext(tbptr, readbuf, rlen);
  355.         }
  356.       }
  357.     }
  358.     CloseIFF(iff);
  359.       }
  360.       Close(iff->iff_Stream);
  361.     }
  362.     FreeIFF(iff);
  363.   }
  364.   return (BOOL) (error ? FALSE : TRUE);
  365. }
  366.  
  367.  
  368. static BOOL writeTEXTfile(UBYTE *fname, struct textbuffer *tb)
  369. {
  370.   BPTR file;
  371.  
  372.   if (file = Open(fname, MODE_NEWFILE)) {
  373.     for (; tb; tb = tb->next) {
  374.       if (Write(file, tb->data, tb->length) != tb->length)
  375.     break;
  376.     }
  377.     Close(file);
  378.     addicon(fname, FALSE);
  379.   }
  380.   else return FALSE;
  381.   return TRUE;
  382. }
  383.  
  384.  
  385. static BOOL writeFTXTfile(UBYTE *fname, struct textbuffer *tb)
  386. {
  387.   struct IFFHandle *iff;
  388.   long error = 0;
  389.  
  390.   if (iff = AllocIFF()) {
  391.     if (iff->iff_Stream = Open(fname, MODE_NEWFILE)) {
  392.       InitIFFasDOS(iff);
  393.       if (!(error = OpenIFF(iff, IFFF_WRITE))) {
  394.     /* write FORM FTXT */
  395.     if (!(error = PushChunk(iff, ID_FTXT, ID_FORM, IFFSIZE_UNKNOWN))) {
  396.       for (; tb; tb = tb->next) {
  397.         /* write a CHRS chunk... */
  398.         if (!PushChunk(iff, 0, ID_CHRS, tb->length)) {
  399.           /* ...followed by its chunk data */
  400.           if (WriteChunkBytes(iff,tb->data,tb->length) != tb->length) {
  401.         error = IFFERR_WRITE;
  402.         break;
  403.           }
  404.           PopChunk(iff);
  405.         }
  406.       }
  407.       PopChunk(iff);
  408.     }
  409.     CloseIFF(iff);
  410.       }
  411.       Close(iff->iff_Stream);
  412.     }
  413.     FreeIFF(iff);
  414.     addicon(fname, TRUE);
  415.   }
  416.   return (BOOL) (error ? FALSE : TRUE);
  417. }
  418.  
  419.  
  420. void loaddropped(UBYTE *fname, BPTR dirlock)
  421. {
  422.   BPTR curdirlock;
  423.   struct textbuffer *tb = NULL;
  424.   BOOL ok;
  425.  
  426.   curdirlock = CurrentDir(dirlock);
  427.   if (!(ok = readFTXTfile(fname, &tb)))
  428.     ok = readTEXTfile(fname, &tb);
  429.   if (!ok)
  430.     msgreq(ls(MSG_FILE_ACCESS_ERROR), fname);
  431.   else {
  432.     inserttextbuffer(tb);
  433.     showtext();
  434.   }
  435.   CurrentDir(curdirlock);
  436. }
  437.  
  438.  
  439. void loadtext(BOOL asFTXT)
  440. {
  441.   BPTR curdirlock, dirlock;
  442.   struct textbuffer *tb = NULL;
  443.   BOOL ok;
  444.  
  445.   if (AslRequestTags(filereq,
  446.              ASL_Hail, (asFTXT
  447.                 ? ls(MSG_LOADFTXT)
  448.                 : ls(MSG_LOADTEXT)),
  449.              ASL_FuncFlags, 0,
  450.              ASL_Window, guiwin,
  451.              TAG_END)) {
  452.     if (dirlock = Lock(filereq->rf_Dir, SHARED_LOCK)) {
  453.       curdirlock = CurrentDir(dirlock);
  454.       if (asFTXT) ok = readFTXTfile(filereq->rf_File, &tb);
  455.       else ok = readTEXTfile(filereq->rf_File, &tb);
  456.       if (!ok)
  457.     msgreq(ls(MSG_FILE_ACCESS_ERROR), filereq->rf_File);
  458.       else {
  459.     inserttextbuffer(tb);
  460.     showtext();
  461.       }
  462.       CurrentDir(curdirlock);
  463.       UnLock(dirlock);
  464.     }
  465.   }
  466. }
  467.  
  468.  
  469. /*
  470.  * Save the contents of the current buffer list,
  471.  * either as text or FTXT depending on 'asFTXT'.
  472.  */
  473.  
  474. void savetext(BOOL asFTXT)
  475. {
  476.   BPTR curdirlock, dirlock;
  477.   BOOL ok;
  478.  
  479.   if (currentbuffer) {
  480.     if (AslRequestTags(filereq,
  481.                ASL_Hail, (asFTXT
  482.                   ? ls(MSG_SAVEASFTXT)
  483.                   : ls(MSG_SAVEASTEXT)),
  484.                ASL_FuncFlags, FILF_SAVE,
  485.                ASL_Window, guiwin,
  486.                TAG_END)) {
  487.       if (dirlock = Lock(filereq->rf_Dir, SHARED_LOCK)) {
  488.     curdirlock = CurrentDir(dirlock);
  489.     if (asFTXT) ok = writeFTXTfile(filereq->rf_File, currentbuffer->tb);
  490.     else ok = writeTEXTfile(filereq->rf_File, currentbuffer->tb);
  491.     if (!ok)
  492.       msgreq(ls(MSG_FILE_ACCESS_ERROR), filereq->rf_File);       
  493.     CurrentDir(curdirlock);
  494.     UnLock(dirlock);
  495.       }
  496.     }
  497.   }
  498. }
  499.  
  500.  
  501. /*
  502.  * This function is used by the ARexx interface to load a file.
  503.  * IFF FTXT files are handled transparently.
  504.  */
  505.  
  506. void rxload(UBYTE *fname, UBYTE *dname)
  507. {
  508.   BPTR curdirlock, dirlock;
  509.   struct textbuffer *tb = NULL;
  510.  
  511.   if (dirlock = Lock(dname, SHARED_LOCK)) {
  512.     curdirlock = CurrentDir(dirlock);
  513.     if (!readFTXTfile(fname, &tb))
  514.       readTEXTfile(fname, &tb);
  515.     inserttextbuffer(tb);
  516.     showtext();
  517.     CurrentDir(curdirlock);
  518.     UnLock(dirlock);
  519.   }
  520. }
  521.  
  522.  
  523. /*
  524.  * This function is used by the ARexx interface to save a file.
  525.  */
  526.  
  527. void rxsave(UBYTE *fname, UBYTE *dname, BOOL asFTXT)
  528. {
  529.   BPTR curdirlock, dirlock;
  530.  
  531.   if (currentbuffer) {
  532.     if (dirlock = Lock(dname, SHARED_LOCK)) {
  533.       curdirlock = CurrentDir(dirlock);
  534.       if (asFTXT) writeFTXTfile(fname, currentbuffer->tb);
  535.       else writeTEXTfile(fname, currentbuffer->tb);
  536.       CurrentDir(curdirlock);
  537.       UnLock(dirlock);
  538.     }
  539.   }
  540. }
  541.  
  542.  
  543. static void addicon(UBYTE *fname, BOOL ftxt)
  544. {
  545.   struct DiskObject *diskobj;
  546.  
  547.   synchronizechecked(); /* just in case... */
  548.   if (createicons)
  549.     if (diskobj = GetDefDiskObject(WBPROJECT)) {
  550.       PutDiskObject(fname, diskobj);
  551.       FreeDiskObject(diskobj);
  552.     }
  553. }
  554.