home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 2 BBS / 02-BBS.zip / MSGDP206.SZH / EDITMAIL.C < prev    next >
Text File  |  1990-09-20  |  21KB  |  1,206 lines

  1. /*
  2.  
  3. Title:    MsgEd
  4.  
  5. File:    Editmail.c
  6.  
  7. Author: Jim Nutt
  8.  
  9. Copr:    Released into the PUBLIC DOMAIN 29 Jul 1990 by jim nutt
  10.  
  11. Description:
  12.  
  13.     routines to do text editing on messages
  14.  
  15. Support Files:
  16.  
  17.     msged.h
  18.  
  19. */
  20.  
  21. #define NOSPELL
  22. #include "msged.h"
  23. #include "editmail.h"
  24.  
  25. #ifndef NOSPELL
  26. #ifdef __ZTC__
  27. #include <sound.h>
  28. #endif
  29. #endif
  30.  
  31. #include <process.h>
  32. #if defined(__TURBOC__)
  33. #include <dir.h>
  34. #else
  35. #include <direct.h>
  36. #endif
  37.  
  38. void _pascal e_assignkey(unsigned int key, char *label);
  39. int  _pascal setcwd(char *path);
  40. int  _pascal wrap(LINE *cl, int x, int y);
  41. void _pascal refresh(LINE * curline, int i);
  42. void _pascal putl(LINE *l);
  43. int  _pascal editmsg(void);
  44. char *    _pascal e_getlabels(int i);
  45. char *    _pascal e_getbind(unsigned int key);
  46.  
  47. #define clearline(l,c)    memset(l,0,c)
  48. #define BUFLEN 256
  49. #define EDITMAIL
  50.  
  51. static int _near  _pascal down1(int y);
  52. static void _near _pascal insert_char(char c);
  53. static void _near _pascal unmark(LINE *current);
  54. static void _near _pascal atputl(LINE *cl, int y);
  55. static void _near _pascal setline(void);
  56. #ifndef NOSPELL
  57. static int _near  _pascal aspell(char *l);
  58. #endif
  59.  
  60. static int done = FALSE;
  61. static int insert = ON;
  62. static int x = 1, y = 1;
  63.  
  64. static char line[BUFLEN];
  65.  
  66. #ifndef NOSPELL
  67. char lwrd[128];
  68. #endif
  69.  
  70. static LINE *current = NULL;
  71. static LINE *first = NULL;
  72. static LINE *pastebuf = NULL;
  73. static int changed = 0;
  74. static int noteflag;
  75.  
  76. LINE *anchorpt = NULL;
  77. extern LINE *top;
  78. extern LINE *bottom;
  79.  
  80. static void _near _pascal rotate()
  81.  
  82. {
  83.     rot13 = (rot13 + 1) % 3;
  84. }
  85.  
  86. static void _near _pascal nada()
  87.  
  88. {
  89. }
  90.  
  91. static void _near _pascal rundos()
  92.  
  93. {
  94.     char tmp[PATHLEN];
  95.     char cmd[64];
  96.  
  97.     getcwd(tmp,PATHLEN);
  98.     memset(cmd,0,sizeof cmd);
  99.     gotoxy(9,1);
  100.     clreol();
  101.     set_color(co_info);
  102.     bputs("DOS command: ");
  103.     bgets(cmd,63,63);
  104. #ifdef __ZTC__
  105.     if (swapping) swap_on();
  106.     else swap_off();
  107. #endif
  108.     cls();
  109.     system(cmd);
  110. #ifdef __ZTC__
  111.     if (!swapping) swap_on();
  112.     else swap_off();
  113. #endif
  114.     maxx = maxy = 0;
  115.     video_init();
  116.     if (rm > maxx)
  117.         rm = maxx - 1;
  118.     puts("\nPress any key to return to msged.");
  119.     getkey();
  120.     setcwd(tmp);
  121.     showheader(message);
  122.     x = y = 1;
  123.     refresh(current, 1);
  124. }
  125.  
  126. char *    _pascal e_getbind(unsigned int key)
  127.  
  128. {
  129.     unsigned int i = 0;
  130.     void (_near _pascal *action)();
  131.  
  132.     if (key & 0xff)
  133.         action = editckeys[key & 0xff];
  134.     else
  135.         action = editakeys[(key >> 8) & 0xff];
  136.  
  137.     while ((editcmds[i].label != NULL) &&
  138.            (action != editcmds[i].action))
  139.         i++;
  140.  
  141.     return(editcmds[i].label);
  142.  
  143. }
  144.  
  145. char *    _pascal e_getlabels(int i)
  146.  
  147. {
  148.     return(editcmds[i].label);
  149. }
  150.  
  151. void    _pascal e_assignkey(unsigned int key, char *label)
  152.  
  153. {
  154.     unsigned int i = 0;
  155.  
  156.     while ((editcmds[i].label != NULL) &&
  157.            (strncmp(editcmds[i].label,label,strlen(editcmds[i].label)) != 0))
  158.         i++;
  159.  
  160.     if (editcmds[i].label != NULL)
  161.         if (key & 0xff)
  162.             editckeys[key & 0xff] = editcmds[i].action;
  163.         else
  164.             editakeys[(key >> 8) & 0xff] = editcmds[i].action;
  165. }
  166.  
  167. #ifndef NOSPELL
  168. static int _near _pascal aspell(char *l)
  169.  
  170. {
  171.     static int speller = 2;
  172.  
  173. #if defined(__OS2__) || defined(NOSPELL)
  174.     l;
  175.     return(1);
  176. #else
  177.     speller = (speller == 2)?chkspl():speller;
  178.  
  179.     if (!(spell && speller))
  180.         return(1);
  181.  
  182.     return !chkwrd(l);
  183. #endif /* __OS2__ */                                       /**OS2**/
  184. }
  185. #endif
  186.  
  187. LINE * _pascal insline(LINE *cl)
  188.  
  189. {
  190.     LINE *nl;
  191.  
  192.     if ((nl = (LINE *) calloc(1, sizeof(LINE))) == NULL)
  193.         return nl;
  194.  
  195.     if (cl == NULL)
  196.         return nl;
  197.  
  198.     nl->next = cl;
  199.     nl->text = strdup("");
  200.     nl->prev = cl->prev;
  201.     if (nl->prev != NULL)
  202.         nl->prev->next = nl;
  203.     else
  204.         first = nl;
  205.     return cl->prev = nl;
  206. }
  207.  
  208. static void _near _pascal setline(void)
  209.  
  210. {
  211.     clearline(line,sizeof line);
  212.     if (current->text != NULL)
  213.         strcpy(line,current->text);
  214.     else
  215.         current->text = strdup("");
  216. }
  217.  
  218.  
  219. static void _near _pascal unmark(LINE *current)
  220.  
  221. {
  222.     if (changed) {
  223.         if (current->text != NULL)
  224.             free(current->text);
  225.  
  226.         current->text = strdup(line);
  227.         changed = FALSE;
  228.     }
  229. }
  230.  
  231. void _pascal putl(LINE *l)
  232.  
  233. {
  234.     if (l->quote)
  235.         set_color(co_quote);
  236.     else if (l->hide)
  237.         set_color(co_info);
  238.     else if (l->block)
  239.         set_color(co_block);
  240.     else
  241.         set_color(co_normal);
  242.     bputs(l->text);
  243.     set_color(co_normal);
  244. }
  245.  
  246. static void _near _pascal atputl(LINE *cl, int y)
  247.  
  248. {
  249.     if ((y+6) <= maxy) {
  250.         gotoxy(1,y+6);
  251.         putl(cl);
  252.         clreol();
  253.     }
  254. }
  255.  
  256.  
  257.  
  258. static void _near _pascal go_bol()
  259.  
  260. {
  261.     x = 1;
  262. }
  263.  
  264. static int _near _pascal down1(int y)
  265. {
  266.     if (++y > (maxy - 6)) {
  267.         y = maxy - 6;
  268.         scrollup(1, 7, maxx, maxy, 1);
  269.     }
  270.     gotoxy(1, y + 6);
  271.     return (y);
  272. }
  273.  
  274. int _pascal wrap(LINE *cl,int x,int y)
  275.  
  276. {
  277.     int i = 0;
  278.     int x2 = x;
  279.     LINE *nl = NULL;
  280.     char *s = NULL;
  281.     char *w = NULL;
  282.     char *t = NULL;
  283.  
  284.     while (cl != NULL) {
  285.         nl = cl->next;
  286.         if ((cl->text != NULL) && (strlen(cl->text) < (size_t) rm)) {
  287.             if ((nl == NULL) || (strchr(cl->text,'\n')) ||
  288.                 (nl->text == NULL)) {
  289.                 atputl(cl,y);
  290.                 return(x2);
  291.             }
  292.  
  293.             if ((size_t) (i = (rm - strlen(cl->text))) > strlen(nl->text)) {
  294.                 s = (char *) realloc(cl->text,strlen(cl->text) + strlen(nl->text) + 1);
  295.                 if (s)
  296.                     cl->text = strcat(s,nl->text);
  297.                 else {
  298.                     refresh(cl,y);
  299.                     return(x2);
  300.                 }
  301.  
  302.                 cl->next = nl->next;
  303.                 if (cl->next)
  304.                     cl->next->prev = cl;
  305.                 if (nl->text) free(nl->text);
  306.                 if (nl) free(nl);
  307.                 if ((y+6) < maxy) {
  308.                     int y2 = y + 7;
  309.                     atputl(cl,y);
  310.                     scrollup(1,y+7,maxx,maxy,1);
  311.                     nl = cl->next;
  312.                     while ((nl != NULL) && (y2++ < maxy))
  313.                         nl = nl->next;
  314.                     if (nl)
  315.                         atputl(nl,y2-7);
  316.                 }
  317.             }
  318.             else {
  319.                 t = nl->text + i;
  320.                 while ((t > nl->text) && !isspace(*t)) t--;
  321.                 if (t <= nl->text) {
  322.                     atputl(cl,y);
  323.                     atputl(nl,y+1);
  324.                     return(x2);
  325.                 }
  326.                 s = nl->text;
  327.                 nl->text = strdup(++t);
  328.                 *t = '\0';
  329.                 t = (char *) realloc(cl->text,strlen(cl->text) + strlen(s) + 1);
  330.                 if (t)
  331.                     cl->text = strcat(t,s);
  332.                 else {
  333.                     refresh(cl,y);
  334.                     return(x2);
  335.                 }
  336.                 if (s) free(s);
  337.                 atputl(cl,y);
  338.                 atputl(nl,y+1);
  339.             }
  340.         }
  341.         else {
  342.             w = cl->text + rm;
  343.             while ((w > cl->text) && !isspace(*w)) w--;
  344.             while ((w > cl->text) && isspace(*w)) w++;
  345.             if (w <= cl->text) w = cl->text + rm;
  346.             if ((cl->text + x2) > w)
  347.                 x2 -= (int) (w - cl->text);
  348.             if ((strchr(w,'\n') == NULL) && (nl != NULL)) {
  349.                 t = (char *) realloc(nl->text,strlen(nl->text) + strlen(w) + 1);
  350.                 if (t) {
  351.                     memmove(t + strlen(w), t, strlen(t)+1);
  352.                     memmove(t,w,strlen(w));
  353.                 }
  354.                 else {
  355.                     refresh(cl,y);
  356.                     return(x2);
  357.                 }
  358.                 nl->text = t;
  359.                 *w = '\0';
  360.                 atputl(cl,y);
  361.             }
  362.             else {
  363.                 nl = (LINE *) calloc(1, sizeof(LINE));
  364.                 if (nl == NULL) {
  365.                     refresh(cl,y);
  366.                     return(x2);
  367.                 }
  368.                 nl->next = cl->next;
  369.                 nl->prev = cl;
  370.                 if (nl->next)
  371.                     nl->next->prev = nl;
  372.                 cl->next = nl;
  373.                 nl->text = (w)?strdup(w):strdup("");
  374.                 *w = '\0';
  375.                 atputl(cl,y);
  376.                 if ((y+7) < maxy) {
  377.                     scrolldown(1,y+7,maxx,maxy,1);
  378.                     atputl(nl,y+1);
  379.                 }
  380.             }
  381.         }
  382.         cl = cl->next;
  383.         y++;
  384.     }
  385.  
  386.     refresh(cl,y);
  387.     return(x2);
  388. }
  389.  
  390. static void _near _pascal insert_char(char c)
  391.  
  392. {
  393.     int x2;
  394.  
  395.     changed = FALSE;
  396.     strins(line, c, x);
  397.     if (current->text) free(current->text);
  398.     current->text = strdup(line);
  399.     current->quote = 0;
  400.     x2 = wrap(current,x,y);
  401.     if (x2 != x) {
  402.         current = current->next;
  403.         x = x2;
  404.         y = down1(y);
  405.         atputl(current,y);
  406.     }
  407.     x++;
  408.     strcpy(line,current->text);
  409.     gotoxy(x,y);
  410. }
  411.  
  412. static void _near _pascal delete_character()
  413.  
  414. {
  415.     LINE *nl;
  416.     int  y2 = y;
  417.     char *s, *t;
  418.     char ch;
  419.  
  420.     if (*line == '\n') {
  421.  
  422.         if (current->text)
  423.             free(current->text);
  424.         if (current->prev)
  425.             current->prev->next = current->next;
  426.         if (current->next)
  427.             current->next->prev = current->prev;
  428.         nl = current;
  429.         current = (current->next)?current->next:(current->prev)?current->prev:nl;
  430.         if (nl && (nl != current))
  431.             free(nl);
  432.  
  433.         clearline(line,BUFLEN);
  434.         nl = current;
  435.         scrollup(1,y+7,maxx,maxy,1);
  436.         while (nl) {
  437.             atputl(nl,y2++);
  438.             nl = nl->next;
  439.         }
  440.         if (current->text)
  441.               strcpy(line,current->text);
  442.     }
  443.     else {
  444.         if (current->text) free(current->text);
  445.         strdel(line,x);
  446.         if (!strchr(line,'\n') && (current->next) && ((s = current->next->text)) != NULL)   {
  447.             if ((t = strchr(s,' ')) != NULL) {
  448.                 while (isspace(*t)) t++;
  449.                 ch = *t; *t = '\0';
  450.                 strcat(line,s);
  451.                 *t = ch;
  452.                 current->next->text = strdup(t);
  453.                 free(s);
  454.             }
  455.         }
  456.         current->text = strdup(line);
  457.         wrap(current,x,y);
  458.         if (current && current->text)
  459.             strcpy(line,current->text);
  460.         else
  461.             clearline(line,BUFLEN);
  462.     }
  463.     atputl(current,y);
  464.     gotoxy(x,y);
  465.     changed = FALSE;
  466. }
  467.  
  468. static void _near _pascal backspace()
  469.  
  470. {
  471.     if (x == 1) {
  472.         if (current->prev == NULL)
  473.             return;
  474.         go_up();
  475.         x = strlen(line);
  476.         if (x == 1)
  477.             delete_character();
  478.         else {
  479.             while ((x > 1) && isspace(*(line + x - 1))) x--;
  480.             x++;
  481.             while (*(line + x)) strdel(line,x);
  482.             delete_character();
  483.         }
  484.         return;
  485.     }
  486.  
  487.     strdel(line, --x);
  488.  
  489.     if (current->text) free(current->text);
  490.     current->text = strdup(line);
  491.     wrap(current,x,y);
  492.     if (current && current->text)
  493.         strcpy(line,current->text);
  494.     else
  495.         clearline(line,BUFLEN);
  496.     changed = FALSE;
  497.     gotoxy(x, y + 6);
  498. }
  499.  
  500. static void _near _pascal delword()
  501.  
  502. {
  503.     char *s = line + x - 1;
  504.  
  505.     while ((*s) && !isspace(*s)) s++;
  506.     while ((*s) && isspace(*s)) s++;
  507.     strcpy(current->text + x - 1,s);
  508.     changed = FALSE;
  509.     wrap(current,x,y);
  510.     strcpy(line,current->text);
  511. }
  512.  
  513. static void _near      _pascal go_eol()
  514.  
  515. {
  516.     x = strlen(line);
  517.  
  518.     if (*(line + x - 1) != '\n')
  519.         x++;
  520.  
  521.     x = max(1, min(rm,x));
  522. }
  523.  
  524. static void _near      _pascal go_up()
  525.  
  526. {
  527.     if (current->prev == NULL)
  528.         return;
  529.  
  530.     unmark(current);
  531.  
  532.     current = current->prev;
  533.  
  534.     if (y == 1) {
  535.         scrolldown(1, y + 6, maxx, maxy, 1);
  536.         atputl(current,y);
  537.     }
  538.     else
  539.         y--;
  540.  
  541.     setline();
  542.  
  543.  
  544.     if ((size_t) x > strlen(line))
  545.         go_eol();
  546. }
  547.  
  548. static void _near      _pascal go_down()
  549.  
  550. {
  551.     if (current->next == NULL)
  552.         return;
  553.  
  554.     unmark(current);
  555.  
  556.     current = current->next;
  557.  
  558.     if (y > (maxy - 7)) {
  559.         scrollup(1, 7, maxx, maxy, 1);
  560.         atputl(current,y);
  561.     }
  562.     else
  563.         y++;
  564.  
  565.     setline();
  566.  
  567.     if ((size_t) x > strlen(line))
  568.         go_eol();
  569.  
  570.     x = max(1, x);
  571. }
  572.  
  573. static void _near    _pascal go_left()
  574.  
  575. {
  576.     if (x == 1) {
  577.         if (current->prev != NULL) {
  578.             go_up();
  579.             go_eol();
  580.         }
  581.         return;
  582.     }
  583.     x--;
  584. }
  585.  
  586. static void _near      _pascal go_right()
  587.  
  588. {
  589.     if (*(line + x - 1) == '\0') {
  590.         if (current->next != NULL) {
  591.             go_down();
  592.             x = 1;
  593.         }
  594.         return;
  595.     }
  596.  
  597.     if (*(line + x - 1) == '\n') {
  598.         if (current->next != NULL) {
  599.             go_down();
  600.             x = 1;
  601.         }
  602.         return;
  603.     }
  604.     x++;
  605. }
  606.  
  607. static void _near      _pascal go_word_right()
  608.  
  609. {
  610.     if (*(line + x - 1) == '\0') {
  611.         if (current->next != NULL) {
  612.             go_down();
  613.             x = 1;
  614.         }
  615.         return;
  616.     }
  617.  
  618.     if (*(line + x - 1) == '\n') {
  619.         if (current->next != NULL) {
  620.             go_down();
  621.             x = 1;
  622.         }
  623.         return;
  624.     }
  625.  
  626.     while (isspace(*(line + x - 1)) && ((size_t) x <= strlen(line)))
  627.         x++;
  628.     while (!isspace(*(line + x - 1)) && ((size_t) x <= strlen(line)))
  629.         x++;
  630.     while (isspace(*(line + x - 1)) && ((size_t) x <= strlen(line)))
  631.         x++;
  632.  
  633.     if (*(line + x - 2) == '\n')
  634.         x--;
  635. }
  636.  
  637. static void _near      _pascal go_word_left()
  638.  
  639. {
  640.     if (x == 1) {
  641.         if (current->prev != NULL) {
  642.             go_up();
  643.             go_eol();
  644.         }
  645.         return;
  646.     }
  647.  
  648.     while (isspace(*(line + x - 1)) && (x > 1))
  649.         x--;
  650.     while (!isspace(*(line + x - 1)) && (x > 1))
  651.         x--;
  652.     while (isspace(*(line + x - 1)) && (x > 1))
  653.         x--;
  654.     while (!isspace(*(line + x - 1)) && (x > 1))
  655.         x--;
  656.  
  657.     if (x != 1)
  658.         x++;
  659. }
  660.  
  661. static void _near      _pascal newline()
  662.  
  663. {
  664.     char    l[BUFLEN];
  665.     char   *t = line + x - 1;
  666.  
  667.     changed = FALSE;
  668.     if (current->text != NULL)
  669.         free(current->text);
  670.  
  671.     clearline(l, BUFLEN);
  672.     strncpy(l, line, x - 1);
  673.     strcat(l, "\n");
  674.     current = insline(current);
  675.     current->text = strdup(l);
  676.     current = current->next;
  677.     current->text = strdup(t);
  678.  
  679.     clreol();
  680.     x = 1;
  681.     y = down1(y);
  682.     gotoxy(x, y + 6);
  683.     if ((y+6) < maxy)
  684.         scrolldown(1,y+6,maxx,maxy,1);
  685.  
  686.     wrap(current,x,y);
  687.     setline();
  688. }
  689.  
  690. static void _near      _pascal go_pgup()
  691.  
  692. {
  693.     int     count = y - 1;
  694.     LINE   *l = current;
  695.  
  696.     unmark(current);
  697.     while (count-- && current->prev) {
  698.         current = current->prev;
  699.     }
  700.  
  701.     count = maxy - 7;
  702.     while (count-- && current->prev) {
  703.         current = current->prev;
  704.     }
  705.  
  706.     if (l != current) {
  707.         y = 1;
  708.         l = current;
  709.         count = 0;
  710.         clrwnd(1,7,maxx,maxy);
  711.         while (((count + 7) < maxy) && (l->next)) {
  712.             atputl(l,count++ + 1);
  713.             l = l->next;
  714.         }
  715.         atputl(l,count + 1);
  716.     }
  717.     setline();
  718. }
  719.  
  720. static void _near      _pascal go_pgdown()
  721.  
  722. {
  723.     int     count = maxy - 7;
  724.     LINE   *l = current;
  725.  
  726.  
  727.     unmark(current);
  728.     while (count-- && current->next) {
  729.         current = current->next;
  730.     }
  731.  
  732.     if (l != current) {
  733.         count = 0;
  734.         l = current;
  735.         clrwnd(1,7,maxx,maxy);
  736.         while (((count + 7) < maxy) && l->next) {
  737.             atputl(l, ++count);
  738.             l = l->next;
  739.         }
  740.         atputl(l, ++count);
  741.     }
  742.     y = 1;
  743.     setline();
  744. }
  745.  
  746. static void _near      _pascal delete_line()
  747.  
  748. {
  749.     LINE   *t = current;
  750.     LINE   *l = current;
  751.     int     y2;
  752.  
  753.     changed = FALSE;
  754.  
  755.     if (current->next == NULL) {
  756.         if (current->text != NULL)
  757.             free(current->text);
  758.         current->text = strdup("");
  759.         current->hide = current->block = current->quote = 0;
  760.         gotoxy(x=1,y+6);
  761.         clearline(line,sizeof(line));
  762.         clreol();
  763.         return;
  764.     }
  765.  
  766.     if ((y+6) < maxy)
  767.         scrollup(1, y + 6, maxx, maxy, 1);
  768.     else
  769.         scrollup(1,maxy,maxx,maxy,0);
  770.  
  771.     t = current;
  772.  
  773.     clearline(line, BUFLEN);
  774.  
  775.     if (current->prev != NULL) {     /* first line? */
  776.         current->next->prev = current->prev; /* no */
  777.         current->prev->next = current->next;
  778.     }
  779.     else {
  780.         current->next->prev = NULL; /* yes */
  781.         first = current->next;
  782.     }
  783.  
  784.     current = current->next;
  785.  
  786.     message->text = first;
  787.  
  788.     if (t->text != NULL)
  789.         free(t->text);
  790.  
  791.     t->text = NULL;
  792.  
  793.     free(t);
  794.     t = NULL;
  795.     setline();
  796.  
  797.     if ((size_t) x > strlen(line))
  798.         go_eol();
  799.  
  800.     l = current; y2 = y;
  801.     while (((y2 + 6) < maxy) && l->next && l->next->text) {
  802.         y2++;
  803.         l = l->next;
  804.     }
  805.  
  806.     atputl(l,y2);
  807.     x = max(1,x);
  808. }
  809.  
  810. static void _near      _pascal anchor()
  811.  
  812. {
  813.     if (anchorpt != NULL) {
  814.         set_color(co_normal);
  815.         refresh(current,y=1);
  816.         anchorpt->block = 0;
  817.         anchorpt->column = 0;
  818.         anchorpt = NULL;
  819.         while (pastebuf) {
  820.             free(pastebuf->text);
  821.             if (pastebuf->next) {
  822.                 pastebuf = pastebuf->next;
  823.                 free(pastebuf->prev);
  824.             }
  825.             else {
  826.                 free(pastebuf);
  827.                 pastebuf = NULL;
  828.             }
  829.         }
  830.     }
  831.     anchorpt = current;
  832.     current->column = x;
  833.     current->block = 1;
  834.     atputl(current,y);
  835. }
  836.  
  837. static void _near      _pascal cut()
  838.  
  839. {
  840.     LINE *f = current;
  841.     LINE *l = current;
  842.  
  843.     unmark(current);
  844.     while (l->next && (l != anchorpt))
  845.         l = l->next;
  846.  
  847.     if (l != anchorpt) {
  848.         l = current;
  849.         while (f->prev && (f != anchorpt))
  850.             f = f->prev;
  851.         if (f != anchorpt)
  852.             return;
  853.     }
  854.  
  855.     if (f->prev == NULL)
  856.         first = l->next;
  857.     else
  858.         f->prev->next = l->next;
  859.  
  860.     if (l->next != NULL) {
  861.         current = l->next;
  862.         l->next->prev = f->prev;
  863.     }
  864.     else
  865.         current = f->prev;
  866.  
  867.     l->next = NULL;
  868.     f->prev = NULL;
  869.  
  870.     if (first == NULL)
  871.         first = current = (LINE *) calloc(1,sizeof(LINE));
  872.  
  873.     pastebuf = f;
  874.  
  875.     setline();
  876.     refresh(current,1);
  877.     y = x = 1;
  878. }
  879.  
  880. static void _near      _pascal paste()
  881.  
  882. {
  883.     LINE *l = pastebuf;
  884.     LINE *t,*s = NULL;
  885.     LINE *t1 = current->prev;
  886.  
  887.     if (l == NULL)
  888.         return;
  889.  
  890.     unmark(current);
  891.     while (l) {
  892.         t = (LINE *) calloc(1,sizeof(LINE));
  893.         if (s == NULL)
  894.             s = t;
  895.         current->prev = t;
  896.         t->next = current;
  897.         t->prev = t1;
  898.         if (t1 == NULL)
  899.             first = t;
  900.         else
  901.             t1->next = t;
  902.         t->text = (l->text)?strdup(l->text):strdup("");
  903.         l = l->next;
  904.         t1 = t;
  905.     }
  906.  
  907.     current = s;
  908.     setline();
  909.     refresh(current,1);
  910.     y = x = 1;
  911. }
  912.  
  913. static void _near      _pascal quit()
  914.  
  915. {
  916.     anchorpt = NULL;
  917.     set_color(co_normal);
  918.     shownotes = noteflag;
  919.     if (changed) {
  920.         if (current->text)
  921.             free(current->text);
  922.  
  923.         if ((current->text = strdup(line)) == 0) {
  924.             gotoxy(9,1);
  925.             set_color(co_warn);
  926.             bputs("*warning* ");
  927.             bputs("memory error! message truncated, press a key");
  928.             clreol();
  929.             getkey();
  930.             set_color(co_normal);
  931.         }
  932.     }
  933.  
  934.     done =    SAVE;
  935. }
  936.  
  937.  
  938. static void _near      _pascal die()
  939.  
  940. {
  941.     if (!confirm())
  942.         showheader(message);
  943.     else
  944.         done = ABORT;
  945. }
  946.  
  947. static void _near      _pascal imptxt()
  948.  
  949. {
  950.     message->text = first;
  951.     if (current->text != NULL)
  952.         free(current->text);
  953.     if (strlen(line) > 0) {
  954.         current->text = strdup(line);
  955.     }
  956.     else
  957.         current->text = NULL;
  958.     import(current);
  959.     first = message->text;
  960.     refresh(current, 1);
  961.     x = y = 1;
  962.     setline();
  963.     changed = FALSE;
  964. }
  965.  
  966. static void _near _pascal outtext()
  967.  
  968. {
  969.     if (pastebuf != NULL)
  970.         export(pastebuf);
  971.     else if (anchorpt != NULL)
  972.         export(anchorpt);
  973.     else if (current != NULL)
  974.         export(current);
  975. }
  976.  
  977.  
  978. static void _near _pascal shellos()
  979.  
  980. {
  981.     char tmp[PATHLEN];
  982.  
  983.     getcwd(tmp,PATHLEN);
  984.     setcwd(home);
  985.     unmark(current);
  986.     cls();
  987.     gotoxy(1,1);
  988.     fputs("\nType EXIT to return to msged.\n",stderr);
  989. #ifdef __ZTC__
  990.     if (!swapping) swap_off();
  991.     else swap_on();
  992. #endif
  993.     spawnl(0,comspec,comspec,NULL);
  994. #ifdef __ZTC__
  995.     if (swapping) swap_off();
  996.     else swap_on();
  997. #endif
  998.     maxx = maxy = 0;
  999.     video_init();
  1000.     if (rm > maxx)
  1001.         rm = maxx;
  1002.     setcwd(tmp);
  1003.     showheader(message);
  1004.     x = y = 1;
  1005.     refresh(current, 1);
  1006. }
  1007.  
  1008. static void _near      _pascal toggle_ins()
  1009.  
  1010. {
  1011.     insert = !insert;
  1012.     if (insert) {
  1013.         set_color(co_info);
  1014.         gotoxy((maxx - 4), 6);
  1015.         bputs("ins");
  1016.     }
  1017.     else {
  1018.         gotoxy((maxx - 4), 6);
  1019.         bputs("   ");
  1020.     }
  1021.     set_color(co_normal);
  1022. }
  1023.  
  1024. static void _near      _pascal tabit()
  1025.  
  1026. {
  1027.     if (!(x%tabsize))
  1028.         insert_char((char) ' ');
  1029.  
  1030.     while (x % tabsize)
  1031.         insert_char((char) ' ');
  1032.  
  1033.     insert_char((char) ' ');
  1034. }
  1035.  
  1036. static void _near      _pascal go_tos()
  1037.  
  1038. {
  1039.     int     count = y - 1;
  1040.  
  1041.     unmark(current);
  1042.     while (count-- && current->prev) {
  1043.         current = current->prev;
  1044.     }
  1045.     x = y = 1;
  1046.     setline();
  1047. }
  1048.  
  1049. static void _near      _pascal go_bos()
  1050.  
  1051. {
  1052.     unmark(current);
  1053.     while (((y + 6) < maxy) && current->next) {
  1054.         current = current->next;
  1055.         y++;
  1056.     }
  1057.     x = 1;
  1058.     setline();
  1059. }
  1060.  
  1061. static void _near _pascal go_tom()
  1062.  
  1063. {
  1064.     unmark(current);
  1065.     current = first;
  1066.     setline();
  1067.     refresh(current,1);
  1068.     x = y = 1;
  1069. }
  1070.  
  1071. static void _near _pascal go_bom()
  1072.  
  1073. {
  1074.     unmark(current);
  1075.     while (current->next)
  1076.         current = current->next;
  1077.     x = y = 1;
  1078.  
  1079.     setline();
  1080.     if (current->prev) {
  1081.         refresh(current->prev,1);
  1082.         y = 2;
  1083.     }
  1084.     else
  1085.         refresh(current,1);
  1086. }
  1087.  
  1088. static void _near _pascal killeol()
  1089.  
  1090. {
  1091.     if (strchr(line,'\n') == NULL)
  1092.         strset(line + x - 1,'\0');
  1093.     else {
  1094.         *(line + x - 1) = '\n';
  1095.         strset(line+x,'\0');
  1096.     }
  1097.     changed = TRUE;
  1098.     clreol();
  1099. }
  1100.  
  1101. int _pascal editmsg()
  1102.  
  1103. {
  1104.     unsigned int     ch;
  1105.  
  1106.     noteflag = shownotes;
  1107.     anchorpt = NULL;
  1108.     shownotes = TRUE;
  1109.     x = y = 1;
  1110.     current = first = message->text;
  1111.  
  1112.     if (insert) {
  1113.         set_color(co_info);
  1114.         gotoxy((maxx-4), 6);
  1115.         bputs("ins");
  1116.         set_color(co_normal);
  1117.     }
  1118.  
  1119.     if (first == NULL) {
  1120.         if ((current = first = (LINE *) calloc(1, sizeof(LINE))) == NULL) {
  1121.             gotoxy(9,1);
  1122.             set_color(co_warn);
  1123.             bputs("*warning* no memory!  press a key");
  1124.             clreol();
  1125.             getkey();
  1126.             set_color(co_normal);
  1127.             return(ABORT);
  1128.         }
  1129.  
  1130.         first->text = NULL;
  1131.         first->prev = NULL;
  1132.     }
  1133.  
  1134.     setline();
  1135.  
  1136.     refresh(current, 1);
  1137.     gotoxy(1, 7);
  1138.     done = FALSE;
  1139.  
  1140.     while (!done) {
  1141.         set_color(co_normal);
  1142.         gotoxy(x,y+6);
  1143.         video_update();
  1144.         ch = getkey();
  1145.         if (ch & 0xff) {
  1146. #ifndef NOSPELL
  1147.             if (!isalpha(ch & 0xff) && isprint(ch & 0xff)) {
  1148.                 char *l = line + x - 2;
  1149.                 int i = 0;
  1150.  
  1151.                 memset(lwrd,0,sizeof lwrd);
  1152.                 while (isalpha(*l))
  1153.                     lwrd[i++] = *l--;
  1154.  
  1155.                 strrev(lwrd);
  1156.  
  1157.                 if (strlen(lwrd) > 1) {
  1158.                     if (!aspell(lwrd)) {
  1159.                         gotoxy(maxx>>1, 5); clreol();
  1160.                         set_color(co_warn);
  1161.                         bputs(lwrd);
  1162. #ifdef __ZTC__
  1163.                         sound_beep(1171);
  1164. #endif
  1165.  
  1166.                     }
  1167.                 }
  1168.             }
  1169. #endif
  1170.  
  1171.             if (editckeys[(ch & 0xff)] == NULL) {
  1172.                 changed = TRUE;
  1173.                 if (insert)
  1174.                     insert_char((char) DOROT13((char) (ch & 0xff)));
  1175.                 else {
  1176.                     *(line + x - 1) = (char) (ch & 0xff);
  1177.                     gotoxy(x,y+6);
  1178.                     bputc((char) (ch & 0xff));
  1179.                     x++;
  1180.                     changed = TRUE;
  1181.                     if (x > rm) {
  1182.                         changed = FALSE;
  1183.                         if (current->text) free(current->text);
  1184.                         current->text = strdup(line);
  1185.                         x = wrap(current,x,y);
  1186.                         y = down1(y);
  1187.                         current = current->next;
  1188.                         setline();
  1189.                     }
  1190.                     gotoxy(x,y+6);
  1191.                 }
  1192.             }
  1193.             else
  1194.                 editckeys[(ch & 0xff)]();
  1195.         }
  1196.         else if (editakeys[(ch >> 8)] != NULL)
  1197.             editakeys[(ch >> 8)]();
  1198.         else
  1199.             continue;
  1200.     }
  1201.  
  1202.     message->text = (current->prev == NULL)?current:first;
  1203.     shownotes = noteflag;
  1204.     return(done);
  1205. }
  1206.