/*
From sch57.mcn.msk.su!karlson@pulsar.ac.msk.su Wed May 24 12:18:55 1995
Return-Path: sch57.mcn.msk.su!karlson@pulsar.ac.msk.su
To: moshkow.ac.msk.su!moshkow@pulsar.ac.msk.su
References: <199505191819.VAA00558@moshkow.ac.msk.su>
Organization: sch57
From: Nikita Kozhekin (Kitya Karlson)"[SHAMIL']" <sch57.mcn.msk.su!karlson@pulsar.ac.msk.su>
Date: Wed, 24 May 95 10:05:22 +0400 (MSD)
X-Mailer: dMail (Demos Mail v1.11a)
Subject: Re: About Monitor 2.95
Lines: 414

×ïô ñ éè é îáûåì. Ôïìøëï ×ù òõóóëéå âõë÷ù éú ëïííåîôáòéå÷ õâåòéôå.
Áìøôåòîáôé÷îáñ ëïäéòï÷ëá óéìøîï Linux îåò÷éòõåô ïäîáëï ;-(
Åóìé ÷ù ðïìõþáåôå ðïþôõ ÷ ËÏÉ-8, ôï üôï îåïâñúáôåìøîï.
Åóìé ÷ù ðïìõþéôå ðïþôõ ÷ MS-DOS, ôï îå úáâõäøôå úáíåîéôø CR LF îá CR.
(Ðòïóôåêûéê óðïóïâ -- úáçòõúéôø ÷ jed, ÷óôá÷éôø é õäáìéôø ðòïâåì é ÷ùêôé).


Î. Ëïöåëéî

Îáþáìá ðòïçòáííéòï÷áîéñ ÷ X-Window

Ìéóôéîç 1. MESSAGE.H
*/

/* ×ëìàþáåíùê íïäõìø: message.h  */

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h> /* Òáâïôá ó óåíáæïòáíé */
#include <sys/shm.h> /* Òáâïôá ó òáúäåìñåíïê ðáíñôøà */

/* Òáâïôá ÷ X-Window */
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xos.h>
#include <X11/keysym.h>

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#define SEM_ID     2001 /* Ëìàþ íáóóé÷á óåíáæïòï÷ */
#define SHM_ID     2002 /* Ëìàþ òáúäåìñåíïê ðáíñôé */
#define PERMIS     0666 /* Ðòá÷á äïóôõðá: ÷óå íïçõô
                           þéôáôø é ðéóáôø*/

#define MSG_TYPE_EMPTY   0 /* Ôéðù óïïâýåîéê:  */
#define MSG_TYPE_STRING  1 /* ðõóôïå, óôòïëá,  */
#define MSG_TYPE_FINISH  2 /* ëïîåã äéáìïçá    */

#define MAX_STRING               20
 /* Íáëóéíáìøîáñ äìéîá óïïâýåîéñ */

#define WND_WDT        200 /* Ûéòéîá ïëîá */
#define WND_HGH        100 /* ×ùóïôá ïëîá */
#define WND_MIN_WDT    50 /* Íéîéíáìøîáñ ûéòéîá ïëîá */
#define WND_MIN_HGH    50 /* Íéîéíáìøîáñ ÷ùóïôá ïëîá */
#define WND_BORDER_WDT 5   /* Ûéòéîá âïòäàòá */

struct msg_t {
   int type;
   char string[MAX_STRING];
}; /* Óôòõëôõòá óïïâýåîéñ */

inline void sys_err( char * msg )
{
  puts( msg );
  exit( 1 );
} /* Óéóôåíîáñ ïûéâëá */

/*  Òáâïôá óï óôòõëôõòïê semun */
inline union semun semun (int i)  {
  union semun s;
  s.val = i;
  return s;
}
inline union semun
        semun (struct semid_ds * b)
{
   union semun s;
   s.buf = b;
   return s;
}

/* Éîéãéáìéúáãéñ ïëîá îáðéóáîá ÷ window.c */
void SetWindowManagerHints (
            Display *  prDisplay,
            char    *  psPrgClass,
            char    *  argv[],
            int        argc,
            Window     nWnd,
            int        x ,
            int        y,
            int        nWidth,
            int        nHeight,
            int        nMinWidth,
            int        nMinHeight,
            char    *  psTitle,
            char    *  psIconTitle,
            Pixmap     nIconPixmap);


Ìéóôéîç 2. WINDOW.C

/* Éîéãéáìéúáãéñ ïëîá */

#include "message.h"

void SetWindowManagerHints (
     Display *  prDisplay,
     char    *  psPrgClass,
     char    *  argv[],
     int        argc,
     Window     nWnd,
     int        x,
     int        y,
     int        nWidth,
     int        nHeight,
     int        nMinWidth,
     int        nMinHeight,
     char    *  psTitle,
     char    *  psIconTitle,
     Pixmap     nIconPixmap)
{
  XSizeHints rSizeHints;
#ifdef X11R3  /* X11R3 é îéöå */
  rSizeHints.flags      = PPosition | PSize | PMinSize;
  rSizeHints.x          = x;
  rSizeHints.y          = y;
  rSizeHints.width      = nWidth;
  rSizeHints.height     = nHeight;
  rSizeHints.min_width  = nMinWidth;
  rSizeHints.min_height = nMinHeight;

  XSetStandardProperties ( prDisplay, nWnd, psTitle,
                           psIconTitle, nIconPixmap,
                           argv, argc, &rSizeHints );
#else /* X11R4 é ÷ùûå */
  XWMHints       rWMHints;
  XClassHint     rClassHint;
  XTextProperty  prWindowName, prIconName;
  if ( !XStringListToTextProperty(&psTitle, 1,
        &prWindowName) || !XStringListToTextProperty(
        &psIconTitle, 1, &prIconName))  {
         sys_err("No memory!");
  }

  rSizeHints.flags      = PPosition | PSize | PMinSize;
  rSizeHints.min_width  = nMinWidth;
  rSizeHints.min_height = nMinHeight;

  rWMHints.flags =
         StateHint | IconPixmapHint | InputHint;

  rWMHints.initial_state   = NormalState;
  rWMHints.input            = True;
  rWMHints.icon_pixmap     = nIconPixmap;

  rClassHint.res_name      = argv[0];
  rClassHint.res_class     = psPrgClass;

XSetWMProperties ( prDisplay, nWnd,
                  &prWindowName, &prIconName,
                  argv, argc, &rSizeHints,
                  &rWMHints, &rClassHint);
#endif
}


Ìéóôéîç 3. CLIENT.C

/* Ìéóôéîç ðòïçòáííù ëìéåîôá: client.c
Ëïíðéìñãéñ : g++ window.c client.c -o client -lX11 & */

#include "message.h"

#define WND_X            0 /* Ëïïòäéîáôù ïëîá */
#define WND_Y          100


#define WND_TITLE       "Client Window"
/* Úáçïìï÷ïë ïëîá */
#define WND_ICON_TITLE  "Client Icon"
/* Úáçïìï÷ïë ðéëôïçòáííù */
#define PRG_CLASS       "Client"

int main(int argc, char * argv[])
/* Ïóîï÷îáñ ðòïãåäõòá */
{
  Display    *prDisplay;
  Window     nWnd;
  int        semid,shmid,x,y,nScreenNum;
  GC         prGC;
  XEvent     rEvent;
  msg_t      *msg_p;
  char       s[MAX_STRING];
  KeySym     nKeySym,naModList[2];

  if (( semid = semget(SEM_ID,1, 0)) < 0 )
   sys_err("CLIENT: can't get semaphore!");
   /* Þôåîéå íáóóé÷á óåíáæïòï÷ */
  if (( shmid = shmget(SHM_ID,sizeof(msg_t),0))<0)
   sys_err("CLIENT: can't get shared memory segment!");
   /* Äïóôõð ë óåçíåîôõ òáúäåìñåíïê ðáíñôé */
  if ((msg_p = (msg_t * ) shmat(shmid, 0, 0)) == NULL)
   sys_err("CLIENT: shared memory attach error!");
   /* Ðïìõþåîéå áäòåóá */

  if ((prDisplay = XOpenDisplay(NULL))==NULL)
    sys_err("CLIENT: can't connect to the X server!");
  /* Ðïäëìàþåîéå ë X-óåò÷åòõ */

  /* Òåçéóôòáãéñ ïëîá */
  nScreenNum = DefaultScreen(prDisplay);
  nWnd = XCreateSimpleWindow(prDisplay,
         RootWindow(prDisplay,nScreenNum), WND_X,
         WND_Y, WND_WDT, WND_HGH, WND_BORDER_WDT,
         BlackPixel(prDisplay, nScreenNum),
         WhitePixel(prDisplay,nScreenNum));
  SetWindowManagerHints(prDisplay, PRG_CLASS, argv,
                        argc, nWnd, WND_X, WND_Y,
                        WND_WDT, WND_HGH, WND_MIN_WDT,
                        WND_MIN_HGH, WND_TITLE,
                        WND_ICON_TITLE, 0);

  /* ×ùâïò þôåîéñ óïâùôéê */
  XSelectInput(prDisplay, nWnd
                   , ExposureMask | KeyPressMask);

  /* Ðïëáú ïëîá */
  XMapWindow(prDisplay, nWnd);

  /* Õóôáîï÷ëá îï÷ïê ëîïðëé ëìá÷éáôõòù */
  naModList[0] = XK_Control_L;
  naModList[1] = XK_Shift_L;
  XRebindKeysym( prDisplay, XK_A, naModList, 2, "EXIT",
                                        strlen("EXIT"));
  x = 0;
  y = 0;
  /* Óïúäáîéå çòáæéþåóëïçï ëïîôåëóôá */
  prGC = XCreateGC(prDisplay, nWnd, 0, NULL);

  /* Çìá÷îùê ãéëì: þôåîéå óïâùôéê */
  for (;;) {
    /* ×ùâïò óïâùôéñ éú ïþåòåäé */
    XNextEvent(prDisplay, &rEvent);

    switch (rEvent.type) {
      case Expose : /* Úáðòïó îá ðåòåòéóï÷ëõ */
        if (rEvent.xexpose.count!=0) break;
        XSetForeground(prDisplay, prGC,
                       BlackPixel(prDisplay, 0));
        /* ×ù÷ïä óôòïëé */
        XDrawString(prDisplay, nWnd, prGC, 10, 50,
                    "Client,", strlen("Client,"));
        break;

      case KeyPress :
        /* Îáöáôéå ëìá÷éûé */
        memset(s, 0, sizeof(s));
        XSetForeground(prDisplay, prGC,
                       BlackPixel(prDisplay, 0));
        XDrawString(prDisplay, nWnd, prGC, 10, 66,
                    "TALK:", strlen("TALK:"));
       /* Þôåîéå óôòïëé-óïïô÷åôóô÷éñ îáöáôïê ëìá÷éûé */
        XLookupString(&rEvent.xkey, s, sizeof(s),
                      &nKeySym, NULL);
        /* Öäåí-ó ... */
        while ( semctl (semid, 0, GETVAL, semun(0) ) ||
                        msg_p->type != MSG_TYPE_EMPTY);
        /* Âìïëéòï÷ëá */
        semctl(semid, 0, GETVAL, semun(1));
        strncpy(msg_p->string,s,MAX_STRING);
        /* Üèï-ïôïâòáöåîéå */
        XDrawString(prDisplay, nWnd, prGC, 10+x,
                    80 + y, s, strlen(s));
        if ((10+x) > WND_WDT) {x =0; y=y+10;}
                             else x = x + 10;
        if (strcmp(s,"EXIT"))
              msg_p->type= MSG_TYPE_STRING;
              else msg_p->type = MSG_TYPE_FINISH;
        /* Óîñôéå âìïëéòï÷ëé */
        semctl(semid, 0, SETVAL, semun(0));
        if (!strcmp(s,"EXIT"))  {
        /* Ëïîåã òáâïôù */
                           shmdt((char*)msg_p);
                           XFreeGC(prDisplay,prGC);
                           XCloseDisplay(prDisplay);
                           exit(0);
        }
        break;
     }
  }
  /* Ïó÷ïâïöäåîéå çòáæéþåóëïçï ëïîôåëóôá */
  XFreeGC(prDisplay,prGC);
  XCloseDisplay(prDisplay);
  exit(0);
}

Ìéóôéîç 4. SERVER.C

/* Ìéóôéîç ðòïçòáííù óåò÷åòá: server.c
Ëïíðéìñãéñ : g++ window.c server.c -o server -lX11 & */

#include "message.h"

#define WND_X 300 /* Ëïïòäéîáôù */
#define WND_Y 100

#define WND_TITLE       "Server Window" /* Úáçïìï÷ëé */
#define WND_ICON_TITLE  "Server Icon"
#define PRG_CLASS       "Server"

int main(int argc, char * argv[])
{
  Display    *prDisplay;
  Window     nWnd;
  int        semid,shmid,x,y,nScreenNum;
  GC         prGC;
  XEvent     rEvent;
  msg_t      *msg_p;
  char       s[MAX_STRING];

  /* Óïúäáîéå óåíáæïòï÷ */
  if ((semid = semget(SEM_ID,1, PERMIS | IPC_CREAT))
                                               < 0 )
  sys_err("SERVER: can't create semaphore!");
  /* Óïúäáîéå òáúäåìñåíïçï óåçíåîôá */
  if ((shmid = shmget(SHM_ID,sizeof(msg_t),
                             PERMIS | IPC_CREAT))<0)
  sys_err("SERVER: can't create shared memory segment!");
  if ((msg_p = (msg_t * ) shmat(shmid, 0, 0))
                                       == NULL)
  sys_err("SERVER: shared memory attach error!");
  semctl( semid, 0 , SETVAL, semun(0));
  msg_p->type = MSG_TYPE_EMPTY;

  /* Ðïäëìàþåîéå ë X-óåò÷åòõ */
  if ((prDisplay = XOpenDisplay(NULL))==NULL)
  sys_err("SERVER: can't connect to the X server!");

  /* Éîéãéáìéúáãéñ ïëîá é üëòáîá */
  nScreenNum = DefaultScreen(prDisplay);
  nWnd = XCreateSimpleWindow(prDisplay,
         RootWindow(prDisplay, nScreenNum), WND_X,
         WND_Y, WND_WDT, WND_HGH, WND_BORDER_WDT,
         BlackPixel(prDisplay, nScreenNum),
         WhitePixel(prDisplay, nScreenNum));
  SetWindowManagerHints(prDisplay, PRG_CLASS, argv,
                        argc, nWnd, WND_X, WND_Y,
                        WND_WDT, WND_HGH, WND_MIN_WDT,
                        WND_MIN_HGH, WND_TITLE,
                        WND_ICON_TITLE, 0);

  /* ×ùâïò óïâùôéê: ðåòåòéóï÷ëá, ëìá÷éáôõòá */
  XSelectInput(prDisplay, nWnd,
                       ExposureMask | KeyPressMask);

  /* ×ù÷ïä ïëîá */
  XMapWindow(prDisplay, nWnd);
  x = 0;
  y = 0;
  /* Óïúäáîéå çòáæéþåóëïçï ëïîôåëóôá */
  prGC = XCreateGC(prDisplay, nWnd, 0 ,NULL);
  for (;;) {
    if (msg_p->type != MSG_TYPE_EMPTY) {
        /* Âìïëéòï÷áîï - öäåí-ó ... */
        if (semctl(semid, 0, GETVAL, semun(0)))
                                      continue;
        /* Âìïëéòï÷ëá */
        semctl(semid, 0, SETVAL, semun(1));
        if (msg_p->type == MSG_TYPE_STRING) {
          XSetForeground(prDisplay, prGC,
                         BlackPixel(prDisplay, 0));
          /* ×ù÷ïä ðòïþéôáîîïê óôòïëé */
          XDrawString(prDisplay, nWnd, prGC, 10 + x,
                              78 + y, msg_p->string,
                              strlen(msg_p->string));
          if ((10+x) > WND_WDT) {x =0; y=y+10;}
                                else x = x + 10;
        }
        if (msg_p->type == MSG_TYPE_FINISH) break;
        msg_p->type = MSG_TYPE_EMPTY;
        /* Ïôíåîá âìïëéòï÷ëé */
        semctl(semid, 0, SETVAL, semun(0));
    }
        /* ×ù÷ïä ðòéçìáûåîéñ äìñ ôåè, ëôï ðïîñì */
        XSetForeground(prDisplay, prGC,
                       BlackPixel(prDisplay, 0));
        XDrawString(prDisplay, nWnd, prGC, 10, 50,
                      "Server,",strlen("Server,"));
        XDrawString(prDisplay, nWnd, prGC, 20, 66,
                      "LISTEN:",strlen("LISTEN:"));
  }
  /* Ïó÷ïâïöäåîéå çòáæéþåóëïçï ëïîôåëóôá */
  XFreeGC(prDisplay, prGC);
  /* Úáëòùôéå äéóðìåñ */
  XCloseDisplay(prDisplay);
  if (semctl(semid, 0, IPC_RMID,
           semun(((struct semid_ds *) 0)) )<0)
  sys_err("SERVER: semaphore remove error!");
  /* Õäáìåîéå íáóóé÷á óåíáæïòï÷ */
  shmdt((char *)msg_p);
  /* Õäáìåîéå óåçíåîôá òáúäåìñåíïê ðáíñôé */
  if ( shmctl( shmid, IPC_RMID,
              (struct shmid_ds *) 0)<0)
  sys_err("SERVER: shared memory remove error!");
  /* ×ùèïä */
  exit(0);
}
/*
--
-----------------------------------------------------------
NIKITA KOZHEKIN (KITYA KARLSON) [SHAMIL] \  Microsoft is not the answer.
        e-mail : KARLSON@SCH57.MCN.MSK.SU\  Microsoft is the question.
        phone  : (095) 373-0554          \  Linux is the answer.
-----------------------------------------------------------
Russia, 111395, Moscow, Snayperskaya str., h.4, app. 182.
                   |   Letters are welcome from 13 to 12.
 /--\/---\/\/-|    |   E-mail welcome around the clock.
|  *  <------/|----|   ------------------------------------
 \         / \/        K K  K K /~~  |
  |_/\___/             KK   KK  \--\ |=|
                       K K  K K  __/ | |


*/
