root/mmap/sharedit.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. initarea
  2. refreshscreen
  3. handler
  4. main

/*    This example uses curses library. In Linux use:
         cc -o sharedit sharedit.c -lncurses
      in other Unix'es use:
         cc -o sharedit shared.c -lcurses
   
      usage:
      sharedit filename

*/

#include<stdio.h>
#include<signal.h>
#include<fcntl.h>
#include<sys/mman.h>
#include<curses.h>
#include<errno.h>
#define ROWS 23
#define COLS 80
#define REFRESH 1

char *area;
int row=0,col=0;

void initarea()
/*  Change all 0 bytes to space character if a new file*/
{
        int i;
        for (i=0;i<ROWS*COLS;i++)
                if (area[i]==0)
                        area[i]=' ';
}

void refreshscreen()
/* Move all data in the file into window using curses function and refresh */
{
        int i;
        for (i=0;i<ROWS;i++)
                mvwaddnstr(stdscr,i,0,area+i*COLS,COLS);
        move(row,col);                  /* recover curses position */
        refresh();                      /* redraw the window    */
}

void handler(int s)
/* SIGALRM handler in order to refresh the screen 
    in order to reflect changes (possibly by another process */
{
        refreshscreen();
        alarm(REFRESH);
        /* some systems alarm handler is cleared, reset it */
        signal(SIGALRM,handler);        
                                        
}

int main(int argc, char *argv[])
{
        int fd;
        int key;

        if (argc != 2) {
                fprintf(stderr,"Usage: sharedit filename\n");
                return -1;
        }
        fd=open(argv[1],O_RDWR|O_CREAT,0600);
        /* open the first argument as a file, create with rw------ if
           file does not exist */

        lseek(fd,ROWS*COLS,SEEK_SET);   /* Guarantee that file size */
        read(fd,&key,1);                /* is large enough          */
        lseek(fd,-1,SEEK_CUR);          
        write(fd,&key,1);               
        
        if (fd<0) {
                perror(argv[0]);
                return -2;
        }
        area=mmap(0,ROWS*COLS, PROT_READ|PROT_WRITE, MAP_SHARED,fd,0);

        if (area==NULL) {
                perror("mmap:");
                return -3;
        }
        initarea();

        /* Curses routines to initialize the interactive window */
        initscr(); cbreak(); noecho();
        keypad(stdscr,TRUE);
        clear();

        /* adjust alarm */
        signal(SIGALRM,handler);
        alarm(REFRESH);

        refreshscreen();
        /* infinite loop until F10 key is pressed */
        while ((key=getch())!=KEY_F(10)) {
                switch (key) {
                case KEY_LEFT:  if (col>0)
                                        col--;
                                break;
                case KEY_RIGHT: if (col<COLS-1)
                                        col++;
                                break;
                case KEY_UP:    if (row>0)
                                        row--;
                                break;
                case KEY_DOWN:  if (row<ROWS-1)
                                        row++;
                                break;
                default:        if (isprint(key)) {
                                        area[row*COLS+col]=key;
                                        addch(key);
                                        if (col<COLS-1) col++;
                                }
                }
                /* Cursor position report in the status (bottom) line */
                mvprintw(ROWS,0,"%2d,%2d",col,row);
                move(row,col);
        }

}





/* [<][>][^][v][top][bottom][index][help] */