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